diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index b05e25e..5c293f3 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ["3.9", "3.10", "3.11", "3.12"]
+ python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v3
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 30b9692..b0da528 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support parallel tool calling by default in `Chat`.
- Legacy support for function calling is available by passing `legacy_function_calling=True` to the `Chat` constructor.
+- :new: `@incremental_display` decorator (see https://github.com/rgbkrk/chatlab/pull/136) that allows you to stream visualizations to the user as the model fills out function arguments.
+
+![building a graph quickly](https://private-user-images.githubusercontent.com/836375/308375331-8953f679-5051-4416-b8a1-0994bde8b032.gif?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MDkwODIyMjEsIm5iZiI6MTcwOTA4MTkyMSwicGF0aCI6Ii84MzYzNzUvMzA4Mzc1MzMxLTg5NTNmNjc5LTUwNTEtNDQxNi1iOGExLTA5OTRiZGU4YjAzMi5naWY_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwMjI4JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDIyOFQwMDU4NDFaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0yNmIxMWIzMTczM2VmYzA0M2VlMDY1MmE0YmE0ODUwZjJjNzMxYjIzYjc1MDI1MmJjYTBhNWZhMzg5MjExZThmJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.hhQqvJtvm3cI8W-JTuQiu8rryl97O_xLKf7dpR2QFSQ)
+
+
## [1.3.0]
diff --git a/chatlab/__init__.py b/chatlab/__init__.py
index 52f4853..206df5f 100644
--- a/chatlab/__init__.py
+++ b/chatlab/__init__.py
@@ -32,6 +32,7 @@
)
from .registry import FunctionRegistry
from spork import Markdown
+from instructor import Partial
__version__ = __version__
@@ -51,4 +52,5 @@
"FunctionRegistry",
"ChatlabMetadata",
"expose_exception_to_llm",
+ "Partial",
]
diff --git a/chatlab/chat.py b/chatlab/chat.py
index 1c91f66..2d1267e 100644
--- a/chatlab/chat.py
+++ b/chatlab/chat.py
@@ -169,10 +169,15 @@ async def __process_stream(
and tool_call.function.arguments is not None
and tool_call.id is not None
):
- # Must build up
tool_argument = ToolArguments(
id=tool_call.id, name=tool_call.function.name, arguments=tool_call.function.arguments
)
+
+ # If the user provided a custom renderer, set it on the tool argument object for displaying
+ func = self.function_registry.get_chatlab_metadata(tool_call.function.name)
+ if func is not None and func.render is not None:
+ tool_argument.custom_render = func.render
+
tool_argument.display()
tool_calls.append(tool_argument)
diff --git a/chatlab/decorators.py b/chatlab/decorators.py
index b2036c3..00c8a03 100644
--- a/chatlab/decorators.py
+++ b/chatlab/decorators.py
@@ -30,15 +30,14 @@
"""
-class ChatlabMetadata:
- """ChatLab metadata for a function."""
-
- expose_exception_to_llm: bool
+from typing import Callable, Optional
- def __init__(self, expose_exception_to_llm=False):
- """Initialize ChatLab metadata for a function."""
- self.expose_exception_to_llm = expose_exception_to_llm
+from pydantic import BaseModel
+class ChatlabMetadata(BaseModel):
+ """ChatLab metadata for a function."""
+ expose_exception_to_llm: bool = False
+ render: Optional[Callable] = None
def expose_exception_to_llm(func):
"""Expose exceptions from calling the function to the LLM.
@@ -70,3 +69,42 @@ def expose_exception_to_llm(func):
func.chatlab_metadata.expose_exception_to_llm = True
return func
+
+
+'''
+The `incremental_display` decorator lets you render a function while the model is streaming in arguments.
+
+def visualize_knowledge_graph(kg: KnowledgeGraph, comment: str = "Knowledge Graph"):
+ """Visualizes a knowledge graph using graphviz."""
+ dot = Digraph(comment=comment)
+
+ for node in kg.nodes:
+ dot.node(str(node.id), node.label, color=node.color)
+
+ for edge in kg.edges:
+ dot.edge(str(edge.source), str(edge.target), label=edge.label, color=edge.color)
+
+ return dot
+
+
+@incremental_display(visualize_knowledge_graph)
+def store_knowledge_graph(kg: KnowledgeGraph, comment: str = "Knowledge Graph"):
+ """Databases a knowledge graph"""
+ ...
+
+chat.register(store_knowledge_graph)
+'''
+
+def incremental_display(render_func: Callable):
+ def decorator(func):
+ if not hasattr(func, "chatlab_metadata"):
+ func.chatlab_metadata = ChatlabMetadata()
+
+ # Make sure that chatlab_metadata is an instance of ChatlabMetadata
+ if not isinstance(func.chatlab_metadata, ChatlabMetadata):
+ raise Exception("func.chatlab_metadata must be an instance of ChatlabMetadata")
+
+ func.chatlab_metadata.render = render_func
+ return func
+ return decorator
+
diff --git a/chatlab/py.typed b/chatlab/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/chatlab/registry.py b/chatlab/registry.py
index 3631160..d461a7d 100644
--- a/chatlab/registry.py
+++ b/chatlab/registry.py
@@ -60,11 +60,12 @@ class WhatTime(BaseModel):
from openai.types import FunctionDefinition, FunctionParameters
from openai.types.chat.completion_create_params import Function, FunctionCall
-from pydantic import BaseModel, create_model
+from pydantic import BaseModel, Field, create_model
from openai.types.chat import ChatCompletionToolParam
from .decorators import ChatlabMetadata
+from .errors import ChatLabError
class APIManifest(TypedDict, total=False):
@@ -80,13 +81,13 @@ class APIManifest(TypedDict, total=False):
"""
-class FunctionArgumentError(Exception):
+class FunctionArgumentError(ChatLabError):
"""Exception raised when a function is called with invalid arguments."""
pass
-class UnknownFunctionError(Exception):
+class UnknownFunctionError(ChatLabError):
"""Exception raised when a function is called that is not registered."""
pass
@@ -123,6 +124,49 @@ class FunctionSchemaConfig:
arbitrary_types_allowed = True
+def extract_model_from_function(func_name: str, function: Callable) -> Type[BaseModel]:
+ # extract function parameters and their type annotations
+ sig = inspect.signature(function)
+
+ fields = {}
+ required_fields = []
+ for name, param in sig.parameters.items():
+ # skip 'self' for class methods
+ if name == "self":
+ continue
+
+ # determine type annotation
+ if param.annotation == inspect.Parameter.empty:
+ # no annotation, raise instead of falling back to Any
+ raise Exception(f"`{name}` parameter of {func_name} must have a JSON-serializable type annotation")
+ type_annotation = param.annotation
+
+ default_value: Any = ...
+
+ # determine if there is a default value
+ if param.default != inspect.Parameter.empty:
+ default_value = param.default
+ else:
+ required_fields.append(name)
+
+ # Check if the annotation is Union that includes None, indicating an optional parameter
+ if get_origin(type_annotation) is Union:
+ args = get_args(type_annotation)
+ if len(args) == 2 and type(None) in args:
+ type_annotation = next(arg for arg in args if arg is not type(None))
+ default_value = None
+
+ fields[name] = (type_annotation, Field(default=default_value) if default_value is not ... else ...)
+
+ model = create_model(
+ function.__name__,
+ __config__=FunctionSchemaConfig, # type: ignore
+ __required__=required_fields,
+ **fields, # type: ignore
+ )
+ return model
+
+
def generate_function_schema(
function: Callable,
parameter_schema: Optional[Union[Type["BaseModel"], dict]] = None,
@@ -149,44 +193,7 @@ def generate_function_schema(
elif parameter_schema is not None:
parameters = parameter_schema.model_json_schema() # type: ignore
else:
- # extract function parameters and their type annotations
- sig = inspect.signature(function)
-
- fields = {}
- for name, param in sig.parameters.items():
- # skip 'self' for class methods
- if name == "self":
- continue
-
- # determine type annotation
- if param.annotation == inspect.Parameter.empty:
- # no annotation, raise instead of falling back to Any
- raise Exception(f"`{name}` parameter of {func_name} must have a JSON-serializable type annotation")
- type_annotation = param.annotation
-
- # determine if there is a default value
- if param.default != inspect.Parameter.empty:
- default_value = param.default
- else:
- default_value = ...
-
- # Check if the annotation is Union that includes None, indicating an optional parameter
- if get_origin(type_annotation) is Union:
- args = get_args(type_annotation)
- if len(args) == 2 and type(None) in args:
- # It's an optional parameter
- type_annotation = next(arg for arg in args if arg is not type(None))
- default_value = None if default_value is ... else default_value
-
- fields[name] = (type_annotation, default_value)
-
- # create the pydantic model and return its JSON schema to pass into the 'parameters' part of the
- # function schema used by OpenAI
- model = create_model(
- function.__name__,
- __config__=FunctionSchemaConfig, # type: ignore
- **fields, # type: ignore
- )
+ model = extract_model_from_function(func_name, function)
parameters: dict = model.model_json_schema() # type: ignore
if "properties" not in parameters:
@@ -458,25 +465,8 @@ async def call(self, name: str, arguments: Optional[str] = None) -> Any:
function = possible_function
- parameters: dict = {}
-
- if arguments is not None and arguments != "":
- try:
- parameters = json.loads(arguments)
- except json.JSONDecodeError:
- raise FunctionArgumentError(f"Invalid Function call on {name}. Arguments must be a valid JSON object")
-
- prepared_arguments = {}
-
- for param_name, param in inspect.signature(function).parameters.items():
- param_type = param.annotation
- arg_value = parameters.get(param_name)
-
- # Check if parameter type is a subclass of BaseModel and deserialize JSON into Pydantic model
- if inspect.isclass(param_type) and issubclass(param_type, BaseModel):
- prepared_arguments[param_name] = param_type.model_validate(arg_value)
- else:
- prepared_arguments[param_name] = cast(Any, arg_value)
+ # TODO: Use the model extractor here
+ prepared_arguments = extract_arguments(name, function, arguments)
if asyncio.iscoroutinefunction(function):
result = await function(**prepared_arguments)
@@ -494,3 +484,26 @@ def __contains__(self, name) -> bool:
def function_definitions(self) -> list[FunctionDefinition]:
"""Get a list of function definitions."""
return list(self.__schemas.values())
+
+
+def extract_arguments(name: str, function: Callable, arguments: Optional[str]) -> dict:
+ dict_arguments = {}
+ if arguments is not None and arguments != "":
+ try:
+ dict_arguments = json.loads(arguments)
+ except json.JSONDecodeError:
+ raise FunctionArgumentError(f"Invalid Function call on {name}. Arguments must be a valid JSON object")
+
+ prepared_arguments = {}
+
+ for param_name, param in inspect.signature(function).parameters.items():
+ param_type = param.annotation
+ arg_value = dict_arguments.get(param_name)
+
+ # Check if parameter type is a subclass of BaseModel and deserialize JSON into Pydantic model
+ if inspect.isclass(param_type) and issubclass(param_type, BaseModel):
+ prepared_arguments[param_name] = param_type.model_validate(arg_value)
+ else:
+ prepared_arguments[param_name] = cast(Any, arg_value)
+
+ return prepared_arguments
diff --git a/chatlab/views/tools.py b/chatlab/views/tools.py
index 02cfb0b..348d75c 100644
--- a/chatlab/views/tools.py
+++ b/chatlab/views/tools.py
@@ -1,13 +1,22 @@
+from typing import Callable, Optional
+from pydantic import ValidationError
from spork import AutoUpdate
+import warnings
+
from ..components.function_details import ChatFunctionComponent
-from ..registry import FunctionRegistry, FunctionArgumentError, UnknownFunctionError
+from ..registry import FunctionRegistry, FunctionArgumentError, UnknownFunctionError, extract_model_from_function
from ..messaging import assistant_function_call, function_result, tool_result
from openai.types.chat import ChatCompletionMessageToolCallParam
+from IPython.display import display
+from IPython.core.getipython import get_ipython
+
+from instructor.dsl.partialjson import JSONParser
+
class ToolCalled(AutoUpdate):
"""Once a tool has finished up, this is the view."""
@@ -19,7 +28,7 @@ class ToolCalled(AutoUpdate):
result: str = ""
def render(self):
- return ChatFunctionComponent(name=self.name, verbage="ok", input=self.arguments, output=self.result)
+ return ChatFunctionComponent(name=self.name, verbage=self.verbage, input=self.arguments, output=self.result)
# TODO: This is only here for legacy function calling
def get_function_called_message(self):
@@ -38,6 +47,8 @@ class ToolArguments(AutoUpdate):
verbage: str = "Receiving arguments for"
finished: bool = False
+ custom_render: Optional[Callable] = None
+
# TODO: This is only here for legacy function calling
def get_function_message(self):
return assistant_function_call(self.name, self.arguments)
@@ -45,7 +56,73 @@ def get_function_message(self):
def get_tool_arguments_parameter(self) -> ChatCompletionMessageToolCallParam:
return {"id": self.id, "function": {"name": self.name, "arguments": self.arguments}, "type": "function"}
+ def format_as_raw(self):
+ ip = get_ipython()
+
+ if ip is None or ip.display_formatter is None:
+ return
+
+ rendered = self.render()
+
+ if rendered is None:
+ return
+
+ data, metadata = ip.display_formatter.format(rendered) # type: ignore
+ return data
+
+ def display(self) -> None:
+ raw_format = self.format_as_raw()
+
+ if raw_format is None:
+ display(None, display_id=self.display_id)
+ return
+
+ # First display will always display the raw format
+ display(raw_format, raw=True, display_id=self.display_id)
+
+ def update(self) -> None:
+ """
+ Update the display with the current state of the object.
+
+ This method is intended to be called after modifications to the object
+ to refresh the display in the notebook environment.
+ """
+ raw_format = self.format_as_raw()
+
+ if raw_format is None:
+ return
+
+ display(raw_format, raw=True, update=True, display_id=self.display_id)
+
def render(self):
+ if self.custom_render is not None:
+ # We use the same definition as was in the original function
+ try:
+ parser = JSONParser()
+ possible_args = parser.parse(self.arguments)
+
+ Model = extract_model_from_function(self.name, self.custom_render)
+ # model = Model.model_validate(possible_args)
+ model = Model(**possible_args)
+
+ # Pluck the kwargs out from the crafted model, as we can't pass the pydantic model as the arguments
+ # However any "inner" models should retain their pydantic Model nature
+ kwargs = {k: getattr(model, k) for k in model.__dict__.keys()}
+
+ except FunctionArgumentError:
+ return None
+ except ValidationError:
+ return None
+
+ try:
+ return self.custom_render(**kwargs)
+ except Exception as e:
+ # Exception in userland code
+ # Would be preferable to bubble up, however
+ # it might be due to us passing a not-quite model
+ warnings.warn_explicit(f"Exception in userland code: {e}", UserWarning, "chatlab", 0)
+ raise
+
return ChatFunctionComponent(name=self.name, verbage=self.verbage, input=self.arguments)
def append_arguments(self, arguments: str):
diff --git a/notebooks/cooking.ipynb b/notebooks/cooking.ipynb
new file mode 100644
index 0000000..9499db1
--- /dev/null
+++ b/notebooks/cooking.ipynb
@@ -0,0 +1,563 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vdom.v1+json": {
+ "attributes": {
+ "style": {
+ "alignItems": "center",
+ "display": "flex",
+ "flexDirection": "column",
+ "fontFamily": "'Arial', sans-serif",
+ "gap": "20px",
+ "margin": "20px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333",
+ "fontSize": "24px"
+ }
+ },
+ "children": [
+ "British Baked Potato"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {
+ "style": {
+ "backgroundColor": "white",
+ "borderRadius": "8px",
+ "boxShadow": "0 4px 6px rgba(0,0,0,0.1)",
+ "marginBottom": "20px",
+ "maxWidth": "500px",
+ "padding": "20px",
+ "width": "80%"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333",
+ "fontSize": "24px"
+ }
+ },
+ "children": [
+ "Ingredients"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {
+ "style": {
+ "listStyle": "none",
+ "padding": "0"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontSize": "16px",
+ "marginBottom": "10px"
+ }
+ },
+ "children": [
+ "4 of Large potatoes"
+ ],
+ "tagName": "li"
+ },
+ {
+ "attributes": {
+ "style": {
+ "fontSize": "16px",
+ "marginBottom": "10px"
+ }
+ },
+ "children": [
+ "2 tablespoons of Olive oil"
+ ],
+ "tagName": "li"
+ },
+ {
+ "attributes": {
+ "style": {
+ "fontSize": "16px",
+ "marginBottom": "10px"
+ }
+ },
+ "children": [
+ "to taste of Sea salt"
+ ],
+ "tagName": "li"
+ }
+ ],
+ "tagName": "ul"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {
+ "style": {
+ "backgroundColor": "white",
+ "borderRadius": "8px",
+ "boxShadow": "0 4px 6px rgba(0,0,0,0.1)",
+ "marginBottom": "20px",
+ "maxWidth": "500px",
+ "padding": "20px",
+ "width": "80%"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333",
+ "fontSize": "24px"
+ }
+ },
+ "children": [
+ "Steps"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "lineHeight": "1.5",
+ "margin": "5px 0"
+ }
+ },
+ "children": [
+ "Preheat your oven to 220°C (430°F)."
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "lineHeight": "1.5",
+ "margin": "5px 0"
+ }
+ },
+ "children": [
+ "Wash the potatoes thoroughly and pat them dry with a kitchen towel."
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "lineHeight": "1.5",
+ "margin": "5px 0"
+ }
+ },
+ "children": [
+ "Prick the potatoes all over with a fork. This allows steam to escape during the cooking process."
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "lineHeight": "1.5",
+ "margin": "5px 0"
+ }
+ },
+ "children": [
+ "Rub the potatoes with olive oil. This helps to crisp the skin."
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "lineHeight": "1.5",
+ "margin": "5px 0"
+ }
+ },
+ "children": [
+ "Sprinkle sea salt over the potatoes. The salt not only seasons the potatoes but also helps to crisp up the skin."
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "lineHeight": "1.5",
+ "margin": "5px 0"
+ }
+ },
+ "children": [
+ "Place the potatoes directly on the middle shelf of the oven. This ensures even cooking."
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "lineHeight": "1.5",
+ "margin": "5px 0"
+ }
+ },
+ "children": [
+ "Bake for about 20 minutes, then reduce the oven temperature to 190°C (375°F) and continue baking for another 60-90 minutes, or until the potatoes are cooked through and the skin is crispy."
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "lineHeight": "1.5",
+ "margin": "5px 0"
+ }
+ },
+ "children": [
+ "Remove the potatoes from the oven and let them cool for a few minutes."
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "lineHeight": "1.5",
+ "margin": "5px 0"
+ }
+ },
+ "children": [
+ "Slice open the top of each potato, being careful not to cut all the way through. Fluff up the inside with a fork."
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "lineHeight": "1.5",
+ "margin": "5px 0"
+ }
+ },
+ "children": [
+ "Serve hot, with your choice of fillings or toppings. Popular options include butter, cheese, baked beans, and coleslaw."
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "div"
+ }
+ ],
+ "tagName": "div"
+ }
+ ],
+ "tagName": "div"
+ }
+ ],
+ "tagName": "div"
+ },
+ "text/html": [
+ "
British Baked Potato Ingredients 4 of Large potatoes 2 tablespoons of Olive oil to taste of Sea salt Steps Preheat your oven to 220°C (430°F).
Wash the potatoes thoroughly and pat them dry with a kitchen towel.
Prick the potatoes all over with a fork. This allows steam to escape during the cooking process.
Rub the potatoes with olive oil. This helps to crisp the skin.
Sprinkle sea salt over the potatoes. The salt not only seasons the potatoes but also helps to crisp up the skin.
Place the potatoes directly on the middle shelf of the oven. This ensures even cooking.
Bake for about 20 minutes, then reduce the oven temperature to 190°C (375°F) and continue baking for another 60-90 minutes, or until the potatoes are cooked through and the skin is crispy.
Remove the potatoes from the oven and let them cool for a few minutes.
Slice open the top of each potato, being careful not to cut all the way through. Fluff up the inside with a fork.
Serve hot, with your choice of fillings or toppings. Popular options include butter, cheese, baked beans, and coleslaw.
"
+ ],
+ "text/plain": [
+ "British Baked Potato Ingredients 4 of Large potatoes 2 tablespoons of Olive oil to taste of Sea salt Steps Preheat your oven to 220°C (430°F).
Wash the potatoes thoroughly and pat them dry with a kitchen towel.
Prick the potatoes all over with a fork. This allows steam to escape during the cooking process.
Rub the potatoes with olive oil. This helps to crisp the skin.
Sprinkle sea salt over the potatoes. The salt not only seasons the potatoes but also helps to crisp up the skin.
Place the potatoes directly on the middle shelf of the oven. This ensures even cooking.
Bake for about 20 minutes, then reduce the oven temperature to 190°C (375°F) and continue baking for another 60-90 minutes, or until the potatoes are cooked through and the skin is crispy.
Remove the potatoes from the oven and let them cool for a few minutes.
Slice open the top of each potato, being careful not to cut all the way through. Fluff up the inside with a fork.
Serve hot, with your choice of fillings or toppings. Popular options include butter, cheese, baked beans, and coleslaw.
"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/markdown": [
+ "I've stored the recipe for a classic British Baked Potato for you. Here's how to make it:\n",
+ "\n",
+ "### British Baked Potato\n",
+ "\n",
+ "#### Ingredients:\n",
+ "- 4 Large potatoes\n",
+ "- 2 tablespoons Olive oil\n",
+ "- Sea salt, to taste\n",
+ "\n",
+ "#### Steps:\n",
+ "1. **Preheat your oven** to 220°C (430°F).\n",
+ "2. **Wash the potatoes** thoroughly and pat them dry with a kitchen towel.\n",
+ "3. **Prick the potatoes** all over with a fork. This allows steam to escape during the cooking process.\n",
+ "4. **Rub the potatoes** with olive oil. This helps to crisp the skin.\n",
+ "5. **Sprinkle sea salt** over the potatoes. The salt not only seasons the potatoes but also helps to crisp up the skin.\n",
+ "6. **Place the potatoes** directly on the middle shelf of the oven. This ensures even cooking.\n",
+ "7. **Bake for about 20 minutes**, then reduce the oven temperature to 190°C (375°F) and continue baking for another 60-90 minutes, or until the potatoes are cooked through and the skin is crispy.\n",
+ "8. **Remove the potatoes** from the oven and let them cool for a few minutes.\n",
+ "9. **Slice open the top** of each potato, being careful not to cut all the way through. Fluff up the inside with a fork.\n",
+ "10. **Serve hot**, with your choice of fillings or toppings. Popular options include butter, cheese, baked beans, and coleslaw.\n",
+ "\n",
+ "Enjoy your delicious British Baked Potato!"
+ ],
+ "text/plain": [
+ "AssistantMessageView(display_id='ffde1008-79b2-4a67-8dde-825246b9291a', content=\"I've stored the recipe for a classic British Baked Potato for you. Here's how to make it:\\n\\n### British Baked Potato\\n\\n#### Ingredients:\\n- 4 Large potatoes\\n- 2 tablespoons Olive oil\\n- Sea salt, to taste\\n\\n#### Steps:\\n1. **Preheat your oven** to 220°C (430°F).\\n2. **Wash the potatoes** thoroughly and pat them dry with a kitchen towel.\\n3. **Prick the potatoes** all over with a fork. This allows steam to escape during the cooking process.\\n4. **Rub the potatoes** with olive oil. This helps to crisp the skin.\\n5. **Sprinkle sea salt** over the potatoes. The salt not only seasons the potatoes but also helps to crisp up the skin.\\n6. **Place the potatoes** directly on the middle shelf of the oven. This ensures even cooking.\\n7. **Bake for about 20 minutes**, then reduce the oven temperature to 190°C (375°F) and continue baking for another 60-90 minutes, or until the potatoes are cooked through and the skin is crispy.\\n8. **Remove the potatoes** from the oven and let them cool for a few minutes.\\n9. **Slice open the top** of each potato, being careful not to cut all the way through. Fluff up the inside with a fork.\\n10. **Serve hot**, with your choice of fillings or toppings. Popular options include butter, cheese, baked beans, and coleslaw.\\n\\nEnjoy your delicious British Baked Potato!\", finished=False, has_displayed=True)"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "from pydantic import BaseModel\n",
+ "from typing import List, Optional\n",
+ "from vdom.helpers import div, h1, p, ul, li, span\n",
+ "\n",
+ "from chatlab import Chat, system\n",
+ "from chatlab.decorators import incremental_display\n",
+ "\n",
+ "\n",
+ "class Ingredient(BaseModel):\n",
+ " name: str\n",
+ " quantity: str # Simplified to a string for flexibility\n",
+ "\n",
+ "\n",
+ "class CookingStep(BaseModel):\n",
+ " description: str\n",
+ " difficulty: Optional[str] = None\n",
+ "\n",
+ "\n",
+ "class Recipe(BaseModel):\n",
+ " title: str\n",
+ " ingredients: List[Ingredient] = []\n",
+ " steps: List[CookingStep] = []\n",
+ "\n",
+ "\n",
+ "def render_recipe_with_inline_style(recipe: Recipe):\n",
+ " \"\"\"Render the recipe with enhanced inline CSS styling using VDOM.\"\"\"\n",
+ " if recipe is None:\n",
+ " return\n",
+ "\n",
+ " container_style = {\n",
+ " \"display\": \"flex\",\n",
+ " \"flexDirection\": \"column\",\n",
+ " \"alignItems\": \"center\",\n",
+ " \"gap\": \"20px\",\n",
+ " \"margin\": \"20px\",\n",
+ " \"fontFamily\": \"'Arial', sans-serif\",\n",
+ " }\n",
+ "\n",
+ " section_style = {\n",
+ " \"backgroundColor\": \"white\",\n",
+ " \"borderRadius\": \"8px\",\n",
+ " \"boxShadow\": \"0 4px 6px rgba(0,0,0,0.1)\",\n",
+ " \"padding\": \"20px\",\n",
+ " \"width\": \"80%\",\n",
+ " \"maxWidth\": \"500px\",\n",
+ " \"marginBottom\": \"20px\",\n",
+ " }\n",
+ "\n",
+ " title_style = {\n",
+ " \"color\": \"#333\",\n",
+ " \"fontSize\": \"24px\",\n",
+ " }\n",
+ "\n",
+ " list_style = {\n",
+ " \"listStyle\": \"none\",\n",
+ " \"padding\": \"0\",\n",
+ " }\n",
+ "\n",
+ " list_item_style = {\n",
+ " \"marginBottom\": \"10px\",\n",
+ " \"fontSize\": \"16px\",\n",
+ " }\n",
+ "\n",
+ " step_paragraph_style = {\n",
+ " \"margin\": \"5px 0\",\n",
+ " \"lineHeight\": \"1.5\",\n",
+ " }\n",
+ "\n",
+ " highlight_style = {\n",
+ " \"color\": \"#d9534f\", # Bootstrap's `btn-danger` color for emphasis\n",
+ " \"fontWeight\": \"bold\",\n",
+ " }\n",
+ "\n",
+ " return div(\n",
+ " h1(recipe.title, style=title_style),\n",
+ " div(\n",
+ " h1(\"Ingredients\", style=title_style),\n",
+ " ul(\n",
+ " children=[\n",
+ " li(f\"{ingredient.quantity} of {ingredient.name}\", style=list_item_style)\n",
+ " for ingredient in recipe.ingredients\n",
+ " ],\n",
+ " style=list_style,\n",
+ " ),\n",
+ " style=section_style,\n",
+ " ),\n",
+ " div(\n",
+ " h1(\"Steps\", style=title_style),\n",
+ " div(\n",
+ " children=[\n",
+ " div(\n",
+ " p(step.description, style=step_paragraph_style),\n",
+ " p(f\"Note: {step.difficulty}\", style=highlight_style) if step.difficulty else span(),\n",
+ " )\n",
+ " for step in recipe.steps\n",
+ " ]\n",
+ " ),\n",
+ " style=section_style,\n",
+ " ),\n",
+ " style=container_style,\n",
+ " )\n",
+ "\n",
+ "\n",
+ "@incremental_display(render_recipe_with_inline_style)\n",
+ "def store_recipe(recipe: Recipe):\n",
+ " \"\"\"Store the recipe in a database and show a nice visual representation.\"\"\"\n",
+ " return \"Stored recipe and showed the steps visually to the user.\"\n",
+ "\n",
+ "\n",
+ "chat = Chat(\n",
+ " system(\n",
+ " \"When the user asks for a recipe, make sure to store it in the database and show a nice visual representation.\"\n",
+ " ),\n",
+ " chat_functions=[store_recipe],\n",
+ " model=\"gpt-4-turbo-preview\",\n",
+ ")\n",
+ "\n",
+ "await chat(\"Let's make a baked potato like they would in Britain.\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "chatlab-0EWIBOuo-py3.11",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/notebooks/knowledge-graph.ipynb b/notebooks/knowledge-graph.ipynb
index 02418c0..eef8692 100644
--- a/notebooks/knowledge-graph.ipynb
+++ b/notebooks/knowledge-graph.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": 1,
"metadata": {},
"outputs": [
{
@@ -19,124 +19,9 @@
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": 5,
"metadata": {},
"outputs": [
- {
- "data": {
- "text/html": [
- "𝑓 Ran visualize_knowledge_graph ... Input:
{\n",
- " "kg": {\n",
- " "nodes": [\n",
- " {\n",
- " "id": 1,\n",
- " "label": "Coffee Beans",\n",
- " "color": "brown"\n",
- " },\n",
- " {\n",
- " "id": 2,\n",
- " "label": "Grinder",\n",
- " "color": "grey"\n",
- " },\n",
- " {\n",
- " "id": 3,\n",
- " "label": "Ground Coffee",\n",
- " "color": "brown"\n",
- " },\n",
- " {\n",
- " "id": 4,\n",
- " "label": "Water",\n",
- " "color": "blue"\n",
- " },\n",
- " {\n",
- " "id": 5,\n",
- " "label": "Heating",\n",
- " "color": "orange"\n",
- " },\n",
- " {\n",
- " "id": 6,\n",
- " "label": "Hot Water",\n",
- " "color": "blue"\n",
- " },\n",
- " {\n",
- " "id": 7,\n",
- " "label": "Coffee Maker",\n",
- " "color": "black"\n",
- " },\n",
- " {\n",
- " "id": 8,\n",
- " "label": "Brewing",\n",
- " "color": "black"\n",
- " },\n",
- " {\n",
- " "id": 9,\n",
- " "label": "Coffee",\n",
- " "color": "brown"\n",
- " },\n",
- " {\n",
- " "id": 10,\n",
- " "label": "Cup",\n",
- " "color": "white"\n",
- " }\n",
- " ],\n",
- " "edges": [\n",
- " {\n",
- " "source": 1,\n",
- " "target": 2,\n",
- " "label": "is ground by"\n",
- " },\n",
- " {\n",
- " "source": 2,\n",
- " "target": 3,\n",
- " "label": "produces"\n",
- " },\n",
- " {\n",
- " "source": 4,\n",
- " "target": 5,\n",
- " "label": "is heated by"\n",
- " },\n",
- " {\n",
- " "source": 5,\n",
- " "target": 6,\n",
- " "label": "produces"\n",
- " },\n",
- " {\n",
- " "source": 3,\n",
- " "target": 7,\n",
- " "label": "is placed in"\n",
- " },\n",
- " {\n",
- " "source": 6,\n",
- " "target": 7,\n",
- " "label": "is poured into"\n",
- " },\n",
- " {\n",
- " "source": 7,\n",
- " "target": 8,\n",
- " "label": "performs"\n",
- " },\n",
- " {\n",
- " "source": 8,\n",
- " "target": 9,\n",
- " "label": "results in"\n",
- " },\n",
- " {\n",
- " "source": 9,\n",
- " "target": 10,\n",
- " "label": "is served in"\n",
- " }\n",
- " ]\n",
- " },\n",
- " "comment": "Coffee Brewing Process"\n",
- "}
"
- ],
- "text/plain": [
- "ToolArguments(display_id='f72bb39d-e045-4a8e-b0bf-2a764f8c2dd9', id='call_VtdlyED4Hak06B2qje1AoRmP', name='visualize_knowledge_graph', arguments='{\\n \"kg\": {\\n \"nodes\": [\\n {\\n \"id\": 1,\\n \"label\": \"Coffee Beans\",\\n \"color\": \"brown\"\\n },\\n {\\n \"id\": 2,\\n \"label\": \"Grinder\",\\n \"color\": \"grey\"\\n },\\n {\\n \"id\": 3,\\n \"label\": \"Ground Coffee\",\\n \"color\": \"brown\"\\n },\\n {\\n \"id\": 4,\\n \"label\": \"Water\",\\n \"color\": \"blue\"\\n },\\n {\\n \"id\": 5,\\n \"label\": \"Heating\",\\n \"color\": \"orange\"\\n },\\n {\\n \"id\": 6,\\n \"label\": \"Hot Water\",\\n \"color\": \"blue\"\\n },\\n {\\n \"id\": 7,\\n \"label\": \"Coffee Maker\",\\n \"color\": \"black\"\\n },\\n {\\n \"id\": 8,\\n \"label\": \"Brewing\",\\n \"color\": \"black\"\\n },\\n {\\n \"id\": 9,\\n \"label\": \"Coffee\",\\n \"color\": \"brown\"\\n },\\n {\\n \"id\": 10,\\n \"label\": \"Cup\",\\n \"color\": \"white\"\\n }\\n ],\\n \"edges\": [\\n {\\n \"source\": 1,\\n \"target\": 2,\\n \"label\": \"is ground by\"\\n },\\n {\\n \"source\": 2,\\n \"target\": 3,\\n \"label\": \"produces\"\\n },\\n {\\n \"source\": 4,\\n \"target\": 5,\\n \"label\": \"is heated by\"\\n },\\n {\\n \"source\": 5,\\n \"target\": 6,\\n \"label\": \"produces\"\\n },\\n {\\n \"source\": 3,\\n \"target\": 7,\\n \"label\": \"is placed in\"\\n },\\n {\\n \"source\": 6,\\n \"target\": 7,\\n \"label\": \"is poured into\"\\n },\\n {\\n \"source\": 7,\\n \"target\": 8,\\n \"label\": \"performs\"\\n },\\n {\\n \"source\": 8,\\n \"target\": 9,\\n \"label\": \"results in\"\\n },\\n {\\n \"source\": 9,\\n \"target\": 10,\\n \"label\": \"is served in\"\\n }\\n ]\\n },\\n \"comment\": \"Coffee Brewing Process\"\\n}', verbage='Ran', finished=True)"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
{
"data": {
"image/svg+xml": [
@@ -146,163 +31,205 @@
"\n",
"\n",
- "\n",
- "\n",
- " \n",
+ "\n",
+ "\n",
+ " \n",
"\n",
"\n",
"1 \n",
- "\n",
- "Coffee Beans \n",
+ "\n",
+ "Ice Cream \n",
" \n",
"\n",
"\n",
"2 \n",
- "\n",
- "Grinder \n",
+ "\n",
+ "Ingredients \n",
" \n",
"\n",
"\n",
"1->2 \n",
- " \n",
- " \n",
- "is ground by \n",
+ " \n",
+ " \n",
+ "consists of \n",
+ " \n",
+ "\n",
+ "\n",
+ "6 \n",
+ "\n",
+ "Types \n",
+ " \n",
+ "\n",
+ "\n",
+ "1->6 \n",
+ " \n",
+ " \n",
+ "has types \n",
+ " \n",
+ "\n",
+ "\n",
+ "11 \n",
+ "\n",
+ "Preparation \n",
+ " \n",
+ "\n",
+ "\n",
+ "1->11 \n",
+ " \n",
+ " \n",
+ "prepared by \n",
" \n",
"\n",
"\n",
"3 \n",
- "\n",
- "Ground Coffee \n",
+ "\n",
+ "Cream \n",
" \n",
"\n",
"\n",
"2->3 \n",
- " \n",
- " \n",
- "produces \n",
- " \n",
- "\n",
- "\n",
- "7 \n",
- "\n",
- "Coffee Maker \n",
- " \n",
- "\n",
- "\n",
- "3->7 \n",
- " \n",
- " \n",
- "is placed in \n",
+ " \n",
+ " \n",
+ "includes \n",
" \n",
"\n",
"\n",
"4 \n",
- "\n",
- "Water \n",
+ "\n",
+ "Sugar \n",
+ " \n",
+ "\n",
+ "\n",
+ "2->4 \n",
+ " \n",
+ " \n",
+ "includes \n",
" \n",
"\n",
"\n",
"5 \n",
- "\n",
- "Heating \n",
+ "\n",
+ "Flavorings \n",
" \n",
- "\n",
- "\n",
- "4->5 \n",
- " \n",
- " \n",
- "is heated by \n",
- " \n",
- "\n",
- "\n",
- "6 \n",
- "\n",
- "Hot Water \n",
- " \n",
- "\n",
+ "\n",
"\n",
- "5->6 \n",
- " \n",
- " \n",
- "produces \n",
+ "2->5 \n",
+ " \n",
+ " \n",
+ "includes \n",
+ " \n",
+ "\n",
+ "\n",
+ "7 \n",
+ "\n",
+ "Soft Serve \n",
" \n",
"\n",
"\n",
"6->7 \n",
- " \n",
- " \n",
- "is poured into \n",
+ " \n",
+ " \n",
+ "includes \n",
" \n",
"\n",
"\n",
"8 \n",
- "\n",
- "Brewing \n",
+ "\n",
+ "Gelato \n",
" \n",
- "\n",
+ "\n",
"\n",
- "7->8 \n",
- " \n",
- " \n",
- "performs \n",
+ "6->8 \n",
+ " \n",
+ " \n",
+ "includes \n",
" \n",
"\n",
"\n",
"9 \n",
- "\n",
- "Coffee \n",
+ "\n",
+ "Sorbet \n",
" \n",
- "\n",
+ "\n",
"\n",
- "8->9 \n",
- " \n",
- " \n",
- "results in \n",
+ "6->9 \n",
+ " \n",
+ " \n",
+ "includes \n",
" \n",
"\n",
"\n",
"10 \n",
- "\n",
- "Cup \n",
+ "\n",
+ "Frozen Yogurt \n",
" \n",
- "\n",
+ "\n",
"\n",
- "9->10 \n",
- " \n",
- " \n",
- "is served in \n",
+ "6->10 \n",
+ " \n",
+ " \n",
+ "includes \n",
+ " \n",
+ "\n",
+ "\n",
+ "12 \n",
+ "\n",
+ "Freezing \n",
+ " \n",
+ "\n",
+ "\n",
+ "11->12 \n",
+ " \n",
+ " \n",
+ "involves \n",
+ " \n",
+ "\n",
+ "\n",
+ "13 \n",
+ "\n",
+ "Churning \n",
+ " \n",
+ "\n",
+ "\n",
+ "11->13 \n",
+ " \n",
+ " \n",
+ "involves \n",
" \n",
" \n",
" \n"
],
"text/plain": [
- ""
+ ""
]
},
"metadata": {},
"output_type": "display_data"
},
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Warning: light is not a known color.\n",
+ "Warning: light is not a known color.\n",
+ "Warning: light is not a known color.\n",
+ "Warning: light is not a known color.\n"
+ ]
+ },
{
"data": {
"text/markdown": [
- "The process of brewing coffee involves the following steps, which are visually represented in this knowledge graph:\n",
+ "Here's a visual guide to understanding Ice Cream:\n",
"\n",
- "1. **Coffee Beans:** Start with whole coffee beans, which are the raw material for making coffee.\n",
- "2. **Grinder:** The coffee beans are ground using a grinder. This process is important for the freshness and flavor of the coffee, as grinding increases the surface area and helps in better extraction of flavors.\n",
- "3. **Ground Coffee:** The result of grinding the coffee beans is ground coffee, which is ready for brewing.\n",
- "4. **Water:** Begin with clean water, which is essential for the taste of the coffee.\n",
- "5. **Heating:** The water is then heated to the right temperature, which is typically between 195°F and 205°F (90°C to 96°C).\n",
- "6. **Hot Water:** The heated water becomes hot water, ready to be used in brewing.\n",
- "7. **Coffee Maker:** The ground coffee is placed in the coffee maker's filter basket or other brewing device, and the hot water is poured over it.\n",
- "8. **Brewing:** The coffee maker then brews the coffee, which involves the hot water passing through the ground coffee to extract its flavors and compounds.\n",
- "9. **Coffee:** The result of the brewing process is coffee, which is the beverage we enjoy.\n",
- "10. **Cup:** The brewed coffee is served in a cup.\n",
+ "- At the core, we have **Ice Cream**, which consists of several key **Ingredients**: Cream, Sugar, and various Flavorings. These ingredients come together to form the delicious treat we all enjoy.\n",
+ "- **Ice Cream** can be categorized into different **Types**, such as Soft Serve, Gelato, Sorbet, and Frozen Yogurt. Each type has its unique characteristics and preparation methods.\n",
+ "- The **Preparation** of Ice Cream involves crucial steps like **Freezing** and **Churning** to achieve the desired texture and consistency.\n",
"\n",
- "This is a simplified overview of the process, and variations can occur depending on the brewing method used (e.g., drip, espresso, French press, etc.). Each step is crucial to achieving the desired flavor and strength of the coffee."
+ "This visual representation helps to simplify the concept of Ice Cream, from its basic ingredients to the various types available and the preparation process involved."
],
"text/plain": [
- "AssistantMessageView(display_id='3c7ab206-6a47-46bc-a5b2-b710e99d9499', content=\"The process of brewing coffee involves the following steps, which are visually represented in this knowledge graph:\\n\\n1. **Coffee Beans:** Start with whole coffee beans, which are the raw material for making coffee.\\n2. **Grinder:** The coffee beans are ground using a grinder. This process is important for the freshness and flavor of the coffee, as grinding increases the surface area and helps in better extraction of flavors.\\n3. **Ground Coffee:** The result of grinding the coffee beans is ground coffee, which is ready for brewing.\\n4. **Water:** Begin with clean water, which is essential for the taste of the coffee.\\n5. **Heating:** The water is then heated to the right temperature, which is typically between 195°F and 205°F (90°C to 96°C).\\n6. **Hot Water:** The heated water becomes hot water, ready to be used in brewing.\\n7. **Coffee Maker:** The ground coffee is placed in the coffee maker's filter basket or other brewing device, and the hot water is poured over it.\\n8. **Brewing:** The coffee maker then brews the coffee, which involves the hot water passing through the ground coffee to extract its flavors and compounds.\\n9. **Coffee:** The result of the brewing process is coffee, which is the beverage we enjoy.\\n10. **Cup:** The brewed coffee is served in a cup.\\n\\nThis is a simplified overview of the process, and variations can occur depending on the brewing method used (e.g., drip, espresso, French press, etc.). Each step is crucial to achieving the desired flavor and strength of the coffee.\", finished=False, has_displayed=True)"
+ "AssistantMessageView(display_id='662bd5ad-4bbe-489c-8a67-0986521ae111', content=\"Here's a visual guide to understanding Ice Cream:\\n\\n- At the core, we have **Ice Cream**, which consists of several key **Ingredients**: Cream, Sugar, and various Flavorings. These ingredients come together to form the delicious treat we all enjoy.\\n- **Ice Cream** can be categorized into different **Types**, such as Soft Serve, Gelato, Sorbet, and Frozen Yogurt. Each type has its unique characteristics and preparation methods.\\n- The **Preparation** of Ice Cream involves crucial steps like **Freezing** and **Churning** to achieve the desired texture and consistency.\\n\\nThis visual representation helps to simplify the concept of Ice Cream, from its basic ingredients to the various types available and the preparation process involved.\", finished=False, has_displayed=True)"
]
},
"metadata": {},
@@ -310,24 +237,23 @@
}
],
"source": [
+ "import warnings\n",
"from graphviz import Digraph\n",
"from pydantic import BaseModel, Field\n",
"from typing import List\n",
- "from chatlab import Chat, system\n",
- "\n",
+ "from chatlab import Chat\n",
+ "from chatlab.decorators import incremental_display\n",
"\n",
"class Node(BaseModel):\n",
" id: int\n",
" label: str\n",
" color: str\n",
"\n",
- "\n",
"class Edge(BaseModel):\n",
" source: int\n",
" target: int\n",
" label: str\n",
- " color: str = \"black\"\n",
- "\n",
+ " color: str = Field(\"black\", description=\"A valid Graphviz color name or hex code.\")\n",
"\n",
"class KnowledgeGraph(BaseModel):\n",
" nodes: List[Node] = Field(..., default_factory=list)\n",
@@ -336,6 +262,9 @@
"\n",
"def visualize_knowledge_graph(kg: KnowledgeGraph, comment: str = \"Knowledge Graph\"):\n",
" \"\"\"Visualizes a knowledge graph using graphviz.\"\"\"\n",
+ " if kg is None:\n",
+ " return\n",
+ "\n",
" dot = Digraph(comment=comment)\n",
"\n",
" for node in kg.nodes:\n",
@@ -344,51 +273,27 @@
" for edge in kg.edges:\n",
" dot.edge(str(edge.source), str(edge.target), label=edge.label, color=edge.color)\n",
"\n",
- " display(dot)\n",
+ " return dot\n",
"\n",
- " return \"<>\"\n",
"\n",
+ "@incremental_display(visualize_knowledge_graph)\n",
+ "def store_knowledge_graph(kg: KnowledgeGraph, comment: str):\n",
+ " \"\"\"Creates a graphviz diagram for the user and stores it in their database.\"\"\"\n",
+ " return \"Stored graph, visual shown\"\n",
"\n",
"chat = Chat(\n",
- " system(\n",
- " \"You are running inside a jupyter notebook. Your responses appear as markdown in the notebook. Functions you run can produce side effects.\"\n",
- " ),\n",
- " model=\"gpt-4-1106-preview\",\n",
- " chat_functions=[visualize_knowledge_graph],\n",
+ " model=\"gpt-4-turbo-preview\",\n",
+ " chat_functions=[store_knowledge_graph],\n",
")\n",
"\n",
- "await chat(\"Visually teach me about the process of brewing coffee.\", temperature=0.9)"
+ "await chat(\"Visually teach me about Ice Cream\", temperature=0.7)"
]
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": 6,
"metadata": {},
"outputs": [
- {
- "data": {
- "text/html": [
- "𝑓 Ran visualize_knowledge_graph ... Input:
{"kg": {"nodes": [{"id": 1, "label": "Cats", "color": "grey"}, {"id": 2, "label": "Feline", "color": "orange"}, {"id": 3, "label": "Whiskers", "color": "black"}, {"id": 4, "label": "Purring", "color": "purple"}, {"id": 5, "label": "Hunting", "color": "green"}, {"id": 6, "label": "Napping", "color": "yellow"}], "edges": [{"source": 1, "target": 2, "label": "is a"}, {"source": 1, "target": 3, "label": "has"}, {"source": 1, "target": 4, "label": "capable of"}, {"source": 1, "target": 5, "label": "engages in"}, {"source": 1, "target": 6, "label": "enjoys"}]}, "comment": "Knowledge Graph about Cats"}
"
- ],
- "text/plain": [
- "ToolArguments(display_id='c05a5fd0-c997-4ae3-af54-4bb009ec47ce', id='call_ElQGcyNI8iwxB0vd8qu8eQ5D', name='visualize_knowledge_graph', arguments='{\"kg\": {\"nodes\": [{\"id\": 1, \"label\": \"Cats\", \"color\": \"grey\"}, {\"id\": 2, \"label\": \"Feline\", \"color\": \"orange\"}, {\"id\": 3, \"label\": \"Whiskers\", \"color\": \"black\"}, {\"id\": 4, \"label\": \"Purring\", \"color\": \"purple\"}, {\"id\": 5, \"label\": \"Hunting\", \"color\": \"green\"}, {\"id\": 6, \"label\": \"Napping\", \"color\": \"yellow\"}], \"edges\": [{\"source\": 1, \"target\": 2, \"label\": \"is a\"}, {\"source\": 1, \"target\": 3, \"label\": \"has\"}, {\"source\": 1, \"target\": 4, \"label\": \"capable of\"}, {\"source\": 1, \"target\": 5, \"label\": \"engages in\"}, {\"source\": 1, \"target\": 6, \"label\": \"enjoys\"}]}, \"comment\": \"Knowledge Graph about Cats\"}', verbage='Ran', finished=True)"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "𝑓 Ran visualize_knowledge_graph ... Input:
{"kg": {"nodes": [{"id": 1, "label": "Dogs", "color": "brown"}, {"id": 2, "label": "Canine", "color": "orange"}, {"id": 3, "label": "Barking", "color": "black"}, {"id": 4, "label": "Tail Wagging", "color": "purple"}, {"id": 5, "label": "Fetching", "color": "green"}, {"id": 6, "label": "Loyalty", "color": "yellow"}], "edges": [{"source": 1, "target": 2, "label": "is a"}, {"source": 1, "target": 3, "label": "capable of"}, {"source": 1, "target": 4, "label": "shows"}, {"source": 1, "target": 5, "label": "enjoys"}, {"source": 1, "target": 6, "label": "known for"}]}, "comment": "Knowledge Graph about Dogs"}
"
- ],
- "text/plain": [
- "ToolArguments(display_id='5a499b38-5089-40e1-b614-8a04380f04aa', id='call_csjm60iTTQH7R8TV0uE3KLF7', name='visualize_knowledge_graph', arguments='{\"kg\": {\"nodes\": [{\"id\": 1, \"label\": \"Dogs\", \"color\": \"brown\"}, {\"id\": 2, \"label\": \"Canine\", \"color\": \"orange\"}, {\"id\": 3, \"label\": \"Barking\", \"color\": \"black\"}, {\"id\": 4, \"label\": \"Tail Wagging\", \"color\": \"purple\"}, {\"id\": 5, \"label\": \"Fetching\", \"color\": \"green\"}, {\"id\": 6, \"label\": \"Loyalty\", \"color\": \"yellow\"}], \"edges\": [{\"source\": 1, \"target\": 2, \"label\": \"is a\"}, {\"source\": 1, \"target\": 3, \"label\": \"capable of\"}, {\"source\": 1, \"target\": 4, \"label\": \"shows\"}, {\"source\": 1, \"target\": 5, \"label\": \"enjoys\"}, {\"source\": 1, \"target\": 6, \"label\": \"known for\"}]}, \"comment\": \"Knowledge Graph about Dogs\"}', verbage='Ran', finished=True)"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
{
"data": {
"image/svg+xml": [
@@ -398,91 +303,77 @@
"\n",
"\n",
- "\n",
+ "\n",
"\n",
- " \n",
+ " \n",
"\n",
"\n",
"1 \n",
- "\n",
- "Cats \n",
+ "\n",
+ "Cat \n",
" \n",
"\n",
"\n",
"2 \n",
- "\n",
- "Feline \n",
+ "\n",
+ "Kitten \n",
" \n",
"\n",
"\n",
"1->2 \n",
- " \n",
- " \n",
- "is a \n",
+ " \n",
+ " \n",
+ "Young \n",
" \n",
"\n",
"\n",
"3 \n",
- "\n",
- "Whiskers \n",
+ "\n",
+ "Adult Cat \n",
" \n",
"\n",
"\n",
"1->3 \n",
- " \n",
- " \n",
- "has \n",
+ " \n",
+ " \n",
+ "Mature \n",
" \n",
"\n",
"\n",
"4 \n",
- "\n",
- "Purring \n",
+ "\n",
+ "Senior Cat \n",
" \n",
"\n",
"\n",
"1->4 \n",
- " \n",
- " \n",
- "capable of \n",
- " \n",
- "\n",
- "\n",
- "5 \n",
- "\n",
- "Hunting \n",
- " \n",
- "\n",
- "\n",
- "1->5 \n",
- " \n",
- " \n",
- "engages in \n",
- " \n",
- "\n",
- "\n",
- "6 \n",
- "\n",
- "Napping \n",
- " \n",
- "\n",
- "\n",
- "1->6 \n",
- " \n",
- " \n",
- "enjoys \n",
+ " \n",
+ " \n",
+ "Aged \n",
" \n",
" \n",
" \n"
],
"text/plain": [
- ""
+ ""
]
},
"metadata": {},
"output_type": "display_data"
},
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Warning: lightb is not a known color.\n",
+ "Warning: lig is not a known color.\n",
+ "Warning: lightgre is not a known color.\n",
+ "Warning: lig is not a known color.\n",
+ "Warning: lightgr is not a known color.\n",
+ "Warning: lightg is not a known color.\n"
+ ]
+ },
{
"data": {
"image/svg+xml": [
@@ -492,116 +383,99 @@
"\n",
"\n",
- "\n",
+ "\n",
"\n",
- " \n",
+ " \n",
"\n",
"\n",
"1 \n",
- "\n",
- "Dogs \n",
+ "\n",
+ "Dog \n",
" \n",
"\n",
"\n",
"2 \n",
- "\n",
- "Canine \n",
+ "\n",
+ "Puppy \n",
" \n",
"\n",
"\n",
"1->2 \n",
- " \n",
- " \n",
- "is a \n",
+ " \n",
+ " \n",
+ "Young \n",
" \n",
"\n",
"\n",
"3 \n",
- "\n",
- "Barking \n",
+ "\n",
+ "Adult Dog \n",
" \n",
"\n",
"\n",
"1->3 \n",
- " \n",
- " \n",
- "capable of \n",
+ " \n",
+ " \n",
+ "Mature \n",
" \n",
"\n",
"\n",
"4 \n",
- "\n",
- "Tail Wagging \n",
+ "\n",
+ "Senior Dog \n",
" \n",
"\n",
"\n",
"1->4 \n",
- " \n",
- " \n",
- "shows \n",
- " \n",
- "\n",
- "\n",
- "5 \n",
- "\n",
- "Fetching \n",
- " \n",
- "\n",
- "\n",
- "1->5 \n",
- " \n",
- " \n",
- "enjoys \n",
- " \n",
- "\n",
- "\n",
- "6 \n",
- "\n",
- "Loyalty \n",
- " \n",
- "\n",
- "\n",
- "1->6 \n",
- " \n",
- " \n",
- "known for \n",
+ " \n",
+ " \n",
+ "Aged \n",
" \n",
" \n",
" \n"
],
"text/plain": [
- ""
+ ""
]
},
"metadata": {},
"output_type": "display_data"
},
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Warning: lightb is not a known color.\n",
+ "Warning: ligh is not a known color.\n",
+ "Warning: lightgree is not a known color.\n",
+ "Warning: ligh is not a known color.\n",
+ "Warning: lightgre is not a known color.\n",
+ "Warning: l is not a known color.\n",
+ "Warning: lightgr is not a known color.\n"
+ ]
+ },
{
"data": {
"text/markdown": [
- "Here are two knowledge graphs, one about cats and one about dogs:\n",
+ "I have created two knowledge graphs, one about cats and one about dogs. \n",
"\n",
- "### Knowledge Graph about Cats\n",
- "- **Cats:** Central to the graph, representing the domesticated feline.\n",
- "- **Feline:** Cats are a type of feline, a family that includes other large and small wild cats.\n",
- "- **Whiskers:** Cats have whiskers, which are sensitive tactile hairs that help them navigate and sense their environment.\n",
- "- **Purring:** Cats are capable of purring, a behavior that can indicate contentment or comfort.\n",
- "- **Hunting:** Cats engage in hunting, using their natural instincts to catch prey, even when they are not hungry.\n",
- "- **Napping:** Cats enjoy napping and are known for sleeping for long periods throughout the day.\n",
+ "### Cat Knowledge Graph:\n",
+ "- **Cat**\n",
+ " - Young: Kitten\n",
+ " - Mature: Adult Cat\n",
+ " - Aged: Senior Cat\n",
"\n",
- "### Knowledge Graph about Dogs\n",
- "- **Dogs:** Central to the graph, representing the domesticated canine.\n",
- "- **Canine:** Dogs are a type of canine, a family that includes wolves, foxes, and other related species.\n",
- "- **Barking:** Dogs are capable of barking, which they use for communication, alerting, and sometimes just for attention.\n",
- "- **Tail Wagging:** Dogs show tail wagging as a sign of various emotions, including excitement, happiness, and nervousness.\n",
- "- **Fetching:** Dogs enjoy fetching objects, which is a playful activity and can also be part of their training.\n",
- "- **Loyalty:** Dogs are known for their loyalty to their human companions, often forming strong bonds.\n",
+ "### Dog Knowledge Graph:\n",
+ "- **Dog**\n",
+ " - Young: Puppy\n",
+ " - Mature: Adult Dog\n",
+ " - Aged: Senior Dog\n",
"\n",
- "These graphs highlight some of the key characteristics and behaviors associated with cats and dogs."
+ "These graphs illustrate the life stages of cats and dogs, from their early years to maturity and old age."
],
"text/plain": [
- "AssistantMessageView(display_id='8b576dbb-f0dc-4a4f-8428-237390227ca9', content='Here are two knowledge graphs, one about cats and one about dogs:\\n\\n### Knowledge Graph about Cats\\n- **Cats:** Central to the graph, representing the domesticated feline.\\n- **Feline:** Cats are a type of feline, a family that includes other large and small wild cats.\\n- **Whiskers:** Cats have whiskers, which are sensitive tactile hairs that help them navigate and sense their environment.\\n- **Purring:** Cats are capable of purring, a behavior that can indicate contentment or comfort.\\n- **Hunting:** Cats engage in hunting, using their natural instincts to catch prey, even when they are not hungry.\\n- **Napping:** Cats enjoy napping and are known for sleeping for long periods throughout the day.\\n\\n### Knowledge Graph about Dogs\\n- **Dogs:** Central to the graph, representing the domesticated canine.\\n- **Canine:** Dogs are a type of canine, a family that includes wolves, foxes, and other related species.\\n- **Barking:** Dogs are capable of barking, which they use for communication, alerting, and sometimes just for attention.\\n- **Tail Wagging:** Dogs show tail wagging as a sign of various emotions, including excitement, happiness, and nervousness.\\n- **Fetching:** Dogs enjoy fetching objects, which is a playful activity and can also be part of their training.\\n- **Loyalty:** Dogs are known for their loyalty to their human companions, often forming strong bonds.\\n\\nThese graphs highlight some of the key characteristics and behaviors associated with cats and dogs.', finished=False, has_displayed=True)"
+ "AssistantMessageView(display_id='02c49f2f-24c0-4e24-97be-884b3edae6cb', content='I have created two knowledge graphs, one about cats and one about dogs. \\n\\n### Cat Knowledge Graph:\\n- **Cat**\\n - Young: Kitten\\n - Mature: Adult Cat\\n - Aged: Senior Cat\\n\\n### Dog Knowledge Graph:\\n- **Dog**\\n - Young: Puppy\\n - Mature: Adult Dog\\n - Aged: Senior Dog\\n\\nThese graphs illustrate the life stages of cats and dogs, from their early years to maturity and old age.', finished=False, has_displayed=True)"
]
},
"metadata": {},
@@ -609,7 +483,9 @@
}
],
"source": [
- "await chat(\"Ok now make two knowledge graphs at the same time. One about cats and one about dogs.\")"
+ "with warnings.catch_warnings():\n",
+ " warnings.simplefilter(\"ignore\")\n",
+ " await chat(\"Ok now make two knowledge graphs. One about cats and one about dogs.\")"
]
}
],
diff --git a/notebooks/streaming-updates.ipynb b/notebooks/streaming-updates.ipynb
new file mode 100644
index 0000000..8ec730e
--- /dev/null
+++ b/notebooks/streaming-updates.ipynb
@@ -0,0 +1,1506 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vdom.v1+json": {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "textAlign": "center"
+ }
+ },
+ "children": [
+ "Fallout Characters"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {
+ "style": {
+ "display": "grid",
+ "gap": "20px",
+ "gridTemplateColumns": "repeat(auto-fill, minmax(250px, 1fr))",
+ "padding": "10px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "alignItems": "center",
+ "border": "1px solid #ddd",
+ "borderRadius": "5px",
+ "display": "flex",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "padding": "10px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333"
+ }
+ },
+ "children": [
+ "Vault Dweller"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Age: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "gray"
+ }
+ },
+ "children": [
+ "25"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Role: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#555"
+ }
+ },
+ "children": [
+ "Sole Survivor"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Affiliation: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#777"
+ }
+ },
+ "children": [
+ "Vault-Tec Corporation"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {
+ "style": {
+ "alignItems": "center",
+ "border": "1px solid #ddd",
+ "borderRadius": "5px",
+ "display": "flex",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "padding": "10px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333"
+ }
+ },
+ "children": [
+ "Lone Wanderer"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Age: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "gray"
+ }
+ },
+ "children": [
+ "21"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Role: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#555"
+ }
+ },
+ "children": [
+ "Wasteland Wanderer"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Affiliation: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#777"
+ }
+ },
+ "children": [
+ "Brotherhood of Steel"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {
+ "style": {
+ "alignItems": "center",
+ "border": "1px solid #ddd",
+ "borderRadius": "5px",
+ "display": "flex",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "padding": "10px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333"
+ }
+ },
+ "children": [
+ "Courier"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Age: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "gray"
+ }
+ },
+ "children": [
+ "30"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Role: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#555"
+ }
+ },
+ "children": [
+ "Delivery Person"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Affiliation: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#777"
+ }
+ },
+ "children": [
+ "New California Republic"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {
+ "style": {
+ "alignItems": "center",
+ "border": "1px solid #ddd",
+ "borderRadius": "5px",
+ "display": "flex",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "padding": "10px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333"
+ }
+ },
+ "children": [
+ "Sole Survivor"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Age: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "gray"
+ }
+ },
+ "children": [
+ "35"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Role: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#555"
+ }
+ },
+ "children": [
+ "Survivor"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Affiliation: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#777"
+ }
+ },
+ "children": [
+ "Minutemen"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {
+ "style": {
+ "alignItems": "center",
+ "border": "1px solid #ddd",
+ "borderRadius": "5px",
+ "display": "flex",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "padding": "10px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333"
+ }
+ },
+ "children": [
+ "Chosen One"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Age: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "gray"
+ }
+ },
+ "children": [
+ "28"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Role: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#555"
+ }
+ },
+ "children": [
+ "Savior of Arroyo"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Affiliation: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#777"
+ }
+ },
+ "children": [
+ "Arroyo Tribe"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {
+ "style": {
+ "alignItems": "center",
+ "border": "1px solid #ddd",
+ "borderRadius": "5px",
+ "display": "flex",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "padding": "10px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333"
+ }
+ },
+ "children": [
+ "Sole Survivor"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Age: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "gray"
+ }
+ },
+ "children": [
+ "40"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Role: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#555"
+ }
+ },
+ "children": [
+ "Parent searching for their child"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Affiliation: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#777"
+ }
+ },
+ "children": [
+ "Railroad"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {
+ "style": {
+ "alignItems": "center",
+ "border": "1px solid #ddd",
+ "borderRadius": "5px",
+ "display": "flex",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "padding": "10px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333"
+ }
+ },
+ "children": [
+ "Sole Survivor"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Age: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "gray"
+ }
+ },
+ "children": [
+ "32"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Role: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#555"
+ }
+ },
+ "children": [
+ "Mercenary"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Affiliation: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#777"
+ }
+ },
+ "children": [
+ "The Institute"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {
+ "style": {
+ "alignItems": "center",
+ "border": "1px solid #ddd",
+ "borderRadius": "5px",
+ "display": "flex",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "padding": "10px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333"
+ }
+ },
+ "children": [
+ "Sole Survivor"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Age: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "gray"
+ }
+ },
+ "children": [
+ "27"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Role: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#555"
+ }
+ },
+ "children": [
+ "Explorer"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Affiliation: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#777"
+ }
+ },
+ "children": [
+ "The Railroad"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {
+ "style": {
+ "alignItems": "center",
+ "border": "1px solid #ddd",
+ "borderRadius": "5px",
+ "display": "flex",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "padding": "10px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333"
+ }
+ },
+ "children": [
+ "Sole Survivor"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Age: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "gray"
+ }
+ },
+ "children": [
+ "33"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Role: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#555"
+ }
+ },
+ "children": [
+ "Settler"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Affiliation: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#777"
+ }
+ },
+ "children": [
+ "Commonwealth Minutemen"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {
+ "style": {
+ "alignItems": "center",
+ "border": "1px solid #ddd",
+ "borderRadius": "5px",
+ "display": "flex",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "padding": "10px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333"
+ }
+ },
+ "children": [
+ "Sole Survivor"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Age: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "gray"
+ }
+ },
+ "children": [
+ "29"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Role: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#555"
+ }
+ },
+ "children": [
+ "Scavenger"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Affiliation: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#777"
+ }
+ },
+ "children": [
+ "The Enclave"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {
+ "style": {
+ "alignItems": "center",
+ "border": "1px solid #ddd",
+ "borderRadius": "5px",
+ "display": "flex",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "padding": "10px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333"
+ }
+ },
+ "children": [
+ "Sole Survivor"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Age: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "gray"
+ }
+ },
+ "children": [
+ "31"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Role: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#555"
+ }
+ },
+ "children": [
+ "Trader"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Affiliation: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#777"
+ }
+ },
+ "children": [
+ "The Pitt Raiders"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ }
+ ],
+ "tagName": "div"
+ },
+ {
+ "attributes": {
+ "style": {
+ "alignItems": "center",
+ "border": "1px solid #ddd",
+ "borderRadius": "5px",
+ "display": "flex",
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "padding": "10px"
+ }
+ },
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "color": "#333"
+ }
+ },
+ "children": [
+ "Sole Survivor"
+ ],
+ "tagName": "h1"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Age: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "gray"
+ }
+ },
+ "children": [
+ "26"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Role: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#555"
+ }
+ },
+ "children": [
+ "Gunslinger"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ },
+ {
+ "attributes": {},
+ "children": [
+ {
+ "attributes": {
+ "style": {
+ "fontWeight": "bold"
+ }
+ },
+ "children": [
+ "Affiliation: "
+ ],
+ "tagName": "span"
+ },
+ {
+ "attributes": {
+ "style": {
+ "color": "#777"
+ }
+ },
+ "children": [
+ "The Kings"
+ ],
+ "tagName": "span"
+ }
+ ],
+ "tagName": "p"
+ }
+ ],
+ "tagName": "div"
+ }
+ ],
+ "tagName": "div"
+ }
+ ],
+ "tagName": "div"
+ },
+ "text/html": [
+ "Fallout Characters Vault Dweller Age: 25
Role: Sole Survivor
Affiliation: Vault-Tec Corporation
Lone Wanderer Age: 21
Role: Wasteland Wanderer
Affiliation: Brotherhood of Steel
Courier Age: 30
Role: Delivery Person
Affiliation: New California Republic
Sole Survivor Age: 35
Role: Survivor
Affiliation: Minutemen
Chosen One Age: 28
Role: Savior of Arroyo
Affiliation: Arroyo Tribe
Sole Survivor Age: 40
Role: Parent searching for their child
Affiliation: Railroad
Sole Survivor Age: 32
Role: Mercenary
Affiliation: The Institute
Sole Survivor Age: 27
Role: Explorer
Affiliation: The Railroad
Sole Survivor Age: 33
Role: Settler
Affiliation: Commonwealth Minutemen
Sole Survivor Age: 29
Role: Scavenger
Affiliation: The Enclave
Sole Survivor Age: 31
Role: Trader
Affiliation: The Pitt Raiders
Sole Survivor Age: 26
Role: Gunslinger
Affiliation: The Kings
"
+ ],
+ "text/plain": [
+ "Fallout Characters Vault Dweller Age: 25
Role: Sole Survivor
Affiliation: Vault-Tec Corporation
Lone Wanderer Age: 21
Role: Wasteland Wanderer
Affiliation: Brotherhood of Steel
Courier Age: 30
Role: Delivery Person
Affiliation: New California Republic
Sole Survivor Age: 35
Role: Survivor
Affiliation: Minutemen
Chosen One Age: 28
Role: Savior of Arroyo
Affiliation: Arroyo Tribe
Sole Survivor Age: 40
Role: Parent searching for their child
Affiliation: Railroad
Sole Survivor Age: 32
Role: Mercenary
Affiliation: The Institute
Sole Survivor Age: 27
Role: Explorer
Affiliation: The Railroad
Sole Survivor Age: 33
Role: Settler
Affiliation: Commonwealth Minutemen
Sole Survivor Age: 29
Role: Scavenger
Affiliation: The Enclave
Sole Survivor Age: 31
Role: Trader
Affiliation: The Pitt Raiders
Sole Survivor Age: 26
Role: Gunslinger
Affiliation: The Kings
"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/markdown": [
+ "I have created 12 characters from the Fallout Universe. You can see the details in the table above."
+ ],
+ "text/plain": [
+ "AssistantMessageView(display_id='b8dc3f0d-69a2-49e1-aec5-7493673974e3', content='I have created 12 characters from the Fallout Universe. You can see the details in the table above.', finished=False, has_displayed=True)"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "from pydantic import BaseModel\n",
+ "from typing import List\n",
+ "from chatlab import Chat, system\n",
+ "from chatlab.decorators import incremental_display\n",
+ "\n",
+ "from vdom import h1, div, p, span\n",
+ "\n",
+ "\n",
+ "class FalloutCharacter(BaseModel):\n",
+ " name: str\n",
+ " age: int\n",
+ " role: str\n",
+ " affiliation: str\n",
+ "\n",
+ "\n",
+ "def view_characters(characters: List[FalloutCharacter]):\n",
+ " \"\"\"Enhanced view of characters with grid layout and styling.\"\"\"\n",
+ " if characters is None or len(characters) == 0:\n",
+ " return None\n",
+ "\n",
+ " return div(\n",
+ " h1(\"Fallout Characters\", style={\"textAlign\": \"center\"}),\n",
+ " div(\n",
+ " style={\n",
+ " \"display\": \"grid\",\n",
+ " \"gridTemplateColumns\": \"repeat(auto-fill, minmax(250px, 1fr))\",\n",
+ " \"gap\": \"20px\",\n",
+ " \"padding\": \"10px\",\n",
+ " },\n",
+ " children=[\n",
+ " div(\n",
+ " style={\n",
+ " \"padding\": \"10px\",\n",
+ " \"border\": \"1px solid #ddd\",\n",
+ " \"borderRadius\": \"5px\",\n",
+ " \"display\": \"flex\",\n",
+ " \"flexDirection\": \"column\",\n",
+ " \"alignItems\": \"center\",\n",
+ " \"justifyContent\": \"center\",\n",
+ " },\n",
+ " children=[\n",
+ " h1(record.name, style={\"color\": \"#333\"}),\n",
+ " p(\n",
+ " span(\"Age: \", style={\"fontWeight\": \"bold\"}),\n",
+ " span(str(record.age), style={\"color\": \"gray\"}),\n",
+ " ),\n",
+ " p(\n",
+ " span(\"Role: \", style={\"fontWeight\": \"bold\"}),\n",
+ " span(record.role, style={\"color\": \"#555\"}),\n",
+ " ),\n",
+ " p(\n",
+ " span(\"Affiliation: \", style={\"fontWeight\": \"bold\"}),\n",
+ " span(record.affiliation, style={\"color\": \"#777\"}),\n",
+ " ),\n",
+ " ],\n",
+ " )\n",
+ " for record in characters\n",
+ " if record is not None\n",
+ " ],\n",
+ " ),\n",
+ " )\n",
+ "\n",
+ "\n",
+ "@incremental_display(view_characters)\n",
+ "def store_characters(characters: List[FalloutCharacter]):\n",
+ " \"\"\"This stores records. A visual display of the records will also be shown.\"\"\"\n",
+ " return f\"Stored {len(characters)} characters and presented a table to the user above in the conversation UI.\"\n",
+ "\n",
+ "\n",
+ "chat = Chat(\n",
+ " system(\n",
+ " \"You are running inside a jupyter notebook. Your responses appear as markdown in the notebook. Functions you run can produce side effects. Do not repeat input to functions back as text.\"\n",
+ " ),\n",
+ " model=\"gpt-3.5-turbo\",\n",
+ " # model=\"gpt-4-turbo-preview\",\n",
+ " chat_functions=[store_characters],\n",
+ ")\n",
+ "\n",
+ "await chat(\"Create some characters from the Fallout Universe. 12 will do.\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "chatlab-0EWIBOuo-py3.11",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/poetry.lock b/poetry.lock
index e3f5c40..77ca242 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -11,6 +11,116 @@ files = [
{file = "aiofiles-23.2.1.tar.gz", hash = "sha256:84ec2218d8419404abcb9f0c02df3f34c6e0a68ed41072acfb1cef5cbc29051a"},
]
+[[package]]
+name = "aiohttp"
+version = "3.9.3"
+description = "Async http client/server framework (asyncio)"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"},
+ {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"},
+ {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"},
+ {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"},
+ {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"},
+ {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"},
+ {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"},
+ {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"},
+ {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"},
+ {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"},
+ {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"},
+ {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"},
+]
+
+[package.dependencies]
+aiosignal = ">=1.1.2"
+async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""}
+attrs = ">=17.3.0"
+frozenlist = ">=1.1.1"
+multidict = ">=4.5,<7.0"
+yarl = ">=1.0,<2.0"
+
+[package.extras]
+speedups = ["Brotli", "aiodns", "brotlicffi"]
+
+[[package]]
+name = "aiosignal"
+version = "1.3.1"
+description = "aiosignal: a list of registered asynchronous callbacks"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"},
+ {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"},
+]
+
+[package.dependencies]
+frozenlist = ">=1.1.0"
+
[[package]]
name = "annotated-types"
version = "0.6.0"
@@ -73,6 +183,17 @@ six = ">=1.12.0"
astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"]
test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"]
+[[package]]
+name = "async-timeout"
+version = "4.0.3"
+description = "Timeout context manager for asyncio programs"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"},
+ {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"},
+]
+
[[package]]
name = "attrs"
version = "23.2.0"
@@ -310,6 +431,20 @@ files = [
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
]
+[[package]]
+name = "click"
+version = "8.1.7"
+description = "Composable command line interface toolkit"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
+ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
[[package]]
name = "colorama"
version = "0.4.6"
@@ -537,6 +672,17 @@ files = [
{file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"},
]
+[[package]]
+name = "docstring-parser"
+version = "0.15"
+description = "Parse Python docstrings in reST, Google and Numpydoc format"
+optional = false
+python-versions = ">=3.6,<4.0"
+files = [
+ {file = "docstring_parser-0.15-py3-none-any.whl", hash = "sha256:d1679b86250d269d06a99670924d6bce45adc00b08069dae8c47d98e89b667a9"},
+ {file = "docstring_parser-0.15.tar.gz", hash = "sha256:48ddc093e8b1865899956fcc03b03e66bb7240c310fac5af81814580c55bf682"},
+]
+
[[package]]
name = "docutils"
version = "0.20.1"
@@ -592,6 +738,92 @@ docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1
testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"]
typing = ["typing-extensions (>=4.8)"]
+[[package]]
+name = "frozenlist"
+version = "1.4.1"
+description = "A list-like structure which implements collections.abc.MutableSequence"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"},
+ {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"},
+ {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"},
+ {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"},
+ {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"},
+ {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"},
+ {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"},
+ {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"},
+ {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"},
+ {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"},
+ {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"},
+ {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"},
+ {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"},
+ {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"},
+ {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"},
+ {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"},
+ {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"},
+ {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"},
+ {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"},
+ {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"},
+ {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"},
+ {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"},
+ {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"},
+ {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"},
+ {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"},
+ {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"},
+ {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"},
+]
+
[[package]]
name = "h11"
version = "0.14.0"
@@ -703,6 +935,26 @@ files = [
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
+[[package]]
+name = "instructor"
+version = "0.6.1"
+description = "structured outputs for llm"
+optional = false
+python-versions = ">=3.10,<4.0"
+files = [
+ {file = "instructor-0.6.1-py3-none-any.whl", hash = "sha256:1924e7db821af0c5ac39450d1fe02704e155ead8f49fd15820e118e61085ee58"},
+ {file = "instructor-0.6.1.tar.gz", hash = "sha256:8ab0f6acff096946c6f66da38a7d859a58ff718f519b395ac9da608fa1711658"},
+]
+
+[package.dependencies]
+aiohttp = ">=3.9.1,<4.0.0"
+docstring-parser = ">=0.15,<0.16"
+openai = ">=1.1.0,<2.0.0"
+pydantic = ">=2.0.2,<3.0.0"
+rich = ">=13.7.0,<14.0.0"
+tenacity = ">=8.2.3,<9.0.0"
+typer = ">=0.9.0,<0.10.0"
+
[[package]]
name = "ipykernel"
version = "6.29.3"
@@ -758,7 +1010,6 @@ prompt-toolkit = ">=3.0.41,<3.1.0"
pygments = ">=2.4.0"
stack-data = "*"
traitlets = ">=5"
-typing-extensions = {version = "*", markers = "python_version < \"3.10\""}
[package.extras]
all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"]
@@ -889,7 +1140,6 @@ files = [
]
[package.dependencies]
-importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""}
jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0"
python-dateutil = ">=2.8.2"
pyzmq = ">=23.0"
@@ -1072,6 +1322,105 @@ files = [
{file = "more_itertools-10.2.0-py3-none-any.whl", hash = "sha256:686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684"},
]
+[[package]]
+name = "multidict"
+version = "6.0.5"
+description = "multidict implementation"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"},
+ {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"},
+ {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"},
+ {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"},
+ {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"},
+ {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"},
+ {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"},
+ {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"},
+ {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"},
+ {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"},
+ {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"},
+ {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"},
+ {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"},
+ {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"},
+ {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"},
+ {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"},
+ {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"},
+ {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"},
+ {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"},
+ {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"},
+ {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"},
+ {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"},
+ {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"},
+ {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"},
+ {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"},
+ {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"},
+ {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"},
+ {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"},
+ {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"},
+ {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"},
+ {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"},
+ {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"},
+ {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"},
+ {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"},
+ {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"},
+ {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"},
+ {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"},
+ {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"},
+ {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"},
+ {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"},
+ {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"},
+ {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"},
+ {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"},
+ {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"},
+ {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"},
+ {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"},
+ {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"},
+ {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"},
+ {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"},
+ {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"},
+ {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"},
+ {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"},
+ {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"},
+ {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"},
+ {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"},
+ {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"},
+ {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"},
+ {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"},
+ {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"},
+ {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"},
+ {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"},
+ {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"},
+ {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"},
+ {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"},
+ {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"},
+ {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"},
+ {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"},
+ {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"},
+ {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"},
+ {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"},
+ {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"},
+ {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"},
+ {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"},
+ {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"},
+ {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"},
+ {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"},
+ {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"},
+ {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"},
+ {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"},
+ {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"},
+ {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"},
+ {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"},
+ {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"},
+ {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"},
+ {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"},
+ {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"},
+ {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"},
+ {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"},
+ {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"},
+ {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"},
+]
+
[[package]]
name = "mypy"
version = "1.8.0"
@@ -2287,6 +2636,20 @@ pure-eval = "*"
[package.extras]
tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
+[[package]]
+name = "tenacity"
+version = "8.2.3"
+description = "Retry code until it succeeds"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"},
+ {file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"},
+]
+
+[package.extras]
+doc = ["reno", "sphinx", "tornado (>=4.5)"]
+
[[package]]
name = "toml"
version = "0.10.2"
@@ -2413,6 +2776,27 @@ rfc3986 = ">=1.4.0"
rich = ">=12.0.0"
urllib3 = ">=1.26.0"
+[[package]]
+name = "typer"
+version = "0.9.0"
+description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "typer-0.9.0-py3-none-any.whl", hash = "sha256:5d96d986a21493606a358cae4461bd8cdf83cbf33a5aa950ae629ca3b51467ee"},
+ {file = "typer-0.9.0.tar.gz", hash = "sha256:50922fd79aea2f4751a8e0408ff10d2662bd0c8bbfa84755a699f3bada2978b2"},
+]
+
+[package.dependencies]
+click = ">=7.1.1,<9.0.0"
+typing-extensions = ">=3.7.4.3"
+
+[package.extras]
+all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
+dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"]
+doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"]
+test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
+
[[package]]
name = "types-aiofiles"
version = "23.2.0.20240106"
@@ -2531,6 +2915,109 @@ files = [
{file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
]
+[[package]]
+name = "yarl"
+version = "1.9.4"
+description = "Yet another URL library"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"},
+ {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"},
+ {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"},
+ {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"},
+ {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"},
+ {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"},
+ {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"},
+ {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"},
+ {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"},
+ {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"},
+ {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"},
+ {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"},
+ {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"},
+ {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"},
+ {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"},
+ {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"},
+ {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"},
+ {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"},
+ {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"},
+ {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"},
+ {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"},
+ {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"},
+ {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"},
+ {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"},
+ {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"},
+ {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"},
+ {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"},
+ {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"},
+ {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"},
+ {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"},
+ {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"},
+ {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"},
+ {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"},
+ {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"},
+ {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"},
+ {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"},
+ {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"},
+ {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"},
+ {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"},
+ {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"},
+ {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"},
+ {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"},
+ {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"},
+ {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"},
+ {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"},
+ {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"},
+ {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"},
+ {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"},
+ {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"},
+ {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"},
+ {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"},
+ {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"},
+ {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"},
+ {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"},
+ {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"},
+ {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"},
+ {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"},
+ {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"},
+ {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"},
+ {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"},
+ {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"},
+ {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"},
+ {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"},
+ {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"},
+ {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"},
+ {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"},
+ {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"},
+ {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"},
+ {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"},
+ {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"},
+ {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"},
+ {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"},
+ {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"},
+ {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"},
+ {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"},
+ {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"},
+ {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"},
+ {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"},
+ {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"},
+ {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"},
+ {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"},
+ {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"},
+ {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"},
+ {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"},
+ {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"},
+ {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"},
+ {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"},
+ {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"},
+ {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"},
+ {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"},
+]
+
+[package.dependencies]
+idna = ">=2.0"
+multidict = ">=4.0"
+
[[package]]
name = "zipp"
version = "3.17.0"
@@ -2552,5 +3039,5 @@ test = ["mypy"]
[metadata]
lock-version = "2.0"
-python-versions = "^3.9"
-content-hash = "e32af71f64d1d9a17c8fba1b3ca975593dede1af9eafef4729d23a5ec037e98b"
+python-versions = "^3.10"
+content-hash = "2c7ecd00dbb859291e51f705c11bf9d95909701fd0ae4421c3c3654a8b95b5fe"
diff --git a/pyproject.toml b/pyproject.toml
index 7c00c8f..3dd0b84 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -32,7 +32,7 @@ packages = [
]
[tool.poetry.dependencies]
-python = "^3.9"
+python = "^3.10"
ipython = ">=7.0.0"
openai = "^1.2.2"
pydantic = "^2.4.2"
@@ -45,6 +45,7 @@ aiofiles = "^23.1.0"
types-aiofiles = "^23.2.0.0"
mypy = "^1.6.1"
spork = "^1.2.0"
+instructor = "^0.6.1"
[tool.poetry.group.dev.dependencies]
tox = "^4.4.11"
@@ -76,13 +77,18 @@ test = [
dev = ["tox", "pre-commit", "virtualenv", "pip", "twine", "toml", "bump2version"]
+[tool.setuptools.package-data]
+chatlab = ["py.typed"]
+
[[tool.mypy.overrides]]
module = [
"aiofiles",
"orjson",
"vdom",
"repr_llm.*",
- "deprecation"
+ "deprecation",
+ "instructor",
+ "instructor.*"
]
ignore_missing_imports = true