More robust log step class, and new examples
This commit is contained in:
parent
146ee3dd32
commit
a830b1721a
|
@ -156,7 +156,7 @@ class AgentImage(AgentType, ImageType):
|
||||||
directory = tempfile.mkdtemp()
|
directory = tempfile.mkdtemp()
|
||||||
self._path = os.path.join(directory, str(uuid.uuid4()) + ".png")
|
self._path = os.path.join(directory, str(uuid.uuid4()) + ".png")
|
||||||
|
|
||||||
img.save(self._path)
|
img.save(self._path, format="png")
|
||||||
|
|
||||||
return self._path
|
return self._path
|
||||||
|
|
||||||
|
|
377
agents/agents.py
377
agents/agents.py
|
@ -15,16 +15,14 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
import json
|
import json
|
||||||
import logging
|
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
||||||
import rich
|
from dataclasses import dataclass
|
||||||
from rich import markdown as rich_markdown
|
|
||||||
|
|
||||||
from transformers.utils import is_torch_available
|
from transformers.utils import is_torch_available
|
||||||
import logging
|
import logging
|
||||||
from .utils import console
|
from .utils import console, parse_code_blob, parse_json_tool_call
|
||||||
from .agent_types import AgentAudio, AgentImage
|
from .agent_types import AgentAudio, AgentImage
|
||||||
from .default_tools import BASE_PYTHON_TOOLS, FinalAnswerTool, setup_default_tools
|
from .default_tools import BASE_PYTHON_TOOLS, FinalAnswerTool, setup_default_tools
|
||||||
from .llm_engine import HfApiEngine, MessageRole
|
from .llm_engine import HfApiEngine, MessageRole
|
||||||
|
@ -47,200 +45,15 @@ from .tools import (
|
||||||
Tool,
|
Tool,
|
||||||
get_tool_description_with_args,
|
get_tool_description_with_args,
|
||||||
load_tool,
|
load_tool,
|
||||||
|
Toolbox,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
LENGTH_TRUNCATE_REPORTS = 10000
|
||||||
def parse_json_blob(json_blob: str) -> Dict[str, str]:
|
|
||||||
try:
|
|
||||||
first_accolade_index = json_blob.find("{")
|
|
||||||
last_accolade_index = [a.start() for a in list(re.finditer("}", json_blob))][-1]
|
|
||||||
json_blob = json_blob[first_accolade_index : last_accolade_index + 1].replace('\\"', "'")
|
|
||||||
json_data = json.loads(json_blob, strict=False)
|
|
||||||
return json_data
|
|
||||||
except json.JSONDecodeError as e:
|
|
||||||
place = e.pos
|
|
||||||
if json_blob[place - 1 : place + 2] == "},\n":
|
|
||||||
raise ValueError(
|
|
||||||
"JSON is invalid: you probably tried to provide multiple tool calls in one action. PROVIDE ONLY ONE TOOL CALL."
|
|
||||||
)
|
|
||||||
raise ValueError(
|
|
||||||
f"The JSON blob you used is invalid due to the following error: {e}.\n"
|
|
||||||
f"JSON blob was: {json_blob}, decoding failed on that specific part of the blob:\n"
|
|
||||||
f"'{json_blob[place-4:place+5]}'."
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
raise ValueError(f"Error in parsing the JSON blob: {e}")
|
|
||||||
|
|
||||||
|
|
||||||
def parse_code_blob(code_blob: str) -> str:
|
|
||||||
try:
|
|
||||||
pattern = r"```(?:py|python)?\n(.*?)\n```"
|
|
||||||
match = re.search(pattern, code_blob, re.DOTALL)
|
|
||||||
return match.group(1).strip()
|
|
||||||
except Exception as e:
|
|
||||||
raise ValueError(
|
|
||||||
f"""
|
|
||||||
The code blob you used is invalid: due to the following error: {e}
|
|
||||||
This means that the regex pattern {pattern} was not respected: make sure to include code with the correct pattern, for instance:
|
|
||||||
Thoughts: Your thoughts
|
|
||||||
Code:
|
|
||||||
```py
|
|
||||||
# Your python code here
|
|
||||||
```<end_action>"""
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_json_tool_call(json_blob: str) -> Tuple[str, Dict[str, str]]:
|
|
||||||
json_blob = json_blob.replace("```json", "").replace("```", "")
|
|
||||||
tool_call = parse_json_blob(json_blob)
|
|
||||||
if "action" in tool_call and "action_input" in tool_call:
|
|
||||||
return tool_call["action"], tool_call["action_input"]
|
|
||||||
elif "action" in tool_call:
|
|
||||||
return tool_call["action"], None
|
|
||||||
else:
|
|
||||||
missing_keys = [key for key in ['action', 'action_input'] if key not in tool_call]
|
|
||||||
error_msg = f"Missing keys: {missing_keys} in blob {tool_call}"
|
|
||||||
console.print(f"[bold red]{error_msg}[/bold red]")
|
|
||||||
raise ValueError(error_msg)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_text_tool_call(text: str) -> Tuple[str, Union[str, Dict[str, str]]]:
|
|
||||||
"""
|
|
||||||
Expects a text in the format: 'Action:', 'Action input:', 'Observation:'. 'Action input:' contains a json string with input arguments.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
if "Observation:" in text:
|
|
||||||
text = text.split("Observation:")[0]
|
|
||||||
if "Action:" in text:
|
|
||||||
text = text.split("Action:")[1]
|
|
||||||
tool_name, tool_input = text.split("Action input:")
|
|
||||||
if "{" in tool_input:
|
|
||||||
tool_input = parse_json_blob(tool_input)
|
|
||||||
else:
|
|
||||||
tool_input = tool_input.strip().replace('"', "")
|
|
||||||
return tool_name.strip().replace('"', "").replace("\\", ""), tool_input
|
|
||||||
except Exception as e:
|
|
||||||
raise ValueError(
|
|
||||||
f"Error in parsing the text tool call: {e}. Be sure to provide the correct format. DO NOT repeat your previous incorrect tool call."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def to_text(input: Union[List[Dict[str, str]], Dict[str, str], str]) -> str:
|
|
||||||
if isinstance(input, list):
|
|
||||||
return "\n".join([m["content"] for m in input])
|
|
||||||
elif isinstance(input, dict):
|
|
||||||
return input["content"]
|
|
||||||
else:
|
|
||||||
return input
|
|
||||||
|
|
||||||
|
|
||||||
HUGGINGFACE_DEFAULT_TOOLS = {}
|
HUGGINGFACE_DEFAULT_TOOLS = {}
|
||||||
_tools_are_initialized = False
|
_tools_are_initialized = False
|
||||||
|
|
||||||
|
|
||||||
class Toolbox:
|
|
||||||
"""
|
|
||||||
The toolbox contains all tools that the agent can perform operations with, as well as a few methods to
|
|
||||||
manage them.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
tools (`List[Tool]`):
|
|
||||||
The list of tools to instantiate the toolbox with
|
|
||||||
add_base_tools (`bool`, defaults to `False`, *optional*, defaults to `False`):
|
|
||||||
Whether to add the tools available within `transformers` to the toolbox.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, tools: List[Tool], add_base_tools: bool = False):
|
|
||||||
self._tools = {tool.name: tool for tool in tools}
|
|
||||||
if add_base_tools:
|
|
||||||
self.add_base_tools()
|
|
||||||
# self._load_tools_if_needed()
|
|
||||||
|
|
||||||
def add_base_tools(self, add_python_interpreter: bool = False):
|
|
||||||
global _tools_are_initialized
|
|
||||||
global HUGGINGFACE_DEFAULT_TOOLS
|
|
||||||
if not _tools_are_initialized:
|
|
||||||
HUGGINGFACE_DEFAULT_TOOLS = setup_default_tools()
|
|
||||||
_tools_are_initialized = True
|
|
||||||
for tool in HUGGINGFACE_DEFAULT_TOOLS.values():
|
|
||||||
if tool.name != "python_interpreter" or add_python_interpreter:
|
|
||||||
self.add_tool(tool)
|
|
||||||
# self._load_tools_if_needed()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def tools(self) -> Dict[str, Tool]:
|
|
||||||
"""Get all tools currently in the toolbox"""
|
|
||||||
return self._tools
|
|
||||||
|
|
||||||
def show_tool_descriptions(self, tool_description_template: str = None) -> str:
|
|
||||||
"""
|
|
||||||
Returns the description of all tools in the toolbox
|
|
||||||
|
|
||||||
Args:
|
|
||||||
tool_description_template (`str`, *optional*):
|
|
||||||
The template to use to describe the tools. If not provided, the default template will be used.
|
|
||||||
"""
|
|
||||||
return "\n".join(
|
|
||||||
[get_tool_description_with_args(tool, tool_description_template) for tool in self._tools.values()]
|
|
||||||
)
|
|
||||||
|
|
||||||
def add_tool(self, tool: Tool):
|
|
||||||
"""
|
|
||||||
Adds a tool to the toolbox
|
|
||||||
|
|
||||||
Args:
|
|
||||||
tool (`Tool`):
|
|
||||||
The tool to add to the toolbox.
|
|
||||||
"""
|
|
||||||
if tool.name in self._tools:
|
|
||||||
raise KeyError(f"Error: tool '{tool.name}' already exists in the toolbox.")
|
|
||||||
self._tools[tool.name] = tool
|
|
||||||
|
|
||||||
def remove_tool(self, tool_name: str):
|
|
||||||
"""
|
|
||||||
Removes a tool from the toolbox
|
|
||||||
|
|
||||||
Args:
|
|
||||||
tool_name (`str`):
|
|
||||||
The tool to remove from the toolbox.
|
|
||||||
"""
|
|
||||||
if tool_name not in self._tools:
|
|
||||||
raise KeyError(
|
|
||||||
f"Error: tool {tool_name} not found in toolbox for removal, should be instead one of {list(self._tools.keys())}."
|
|
||||||
)
|
|
||||||
del self._tools[tool_name]
|
|
||||||
|
|
||||||
def update_tool(self, tool: Tool):
|
|
||||||
"""
|
|
||||||
Updates a tool in the toolbox according to its name.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
tool (`Tool`):
|
|
||||||
The tool to update to the toolbox.
|
|
||||||
"""
|
|
||||||
if tool.name not in self._tools:
|
|
||||||
raise KeyError(
|
|
||||||
f"Error: tool {tool.name} not found in toolbox for update, should be instead one of {list(self._tools.keys())}."
|
|
||||||
)
|
|
||||||
self._tools[tool.name] = tool
|
|
||||||
|
|
||||||
def clear_toolbox(self):
|
|
||||||
"""Clears the toolbox"""
|
|
||||||
self._tools = {}
|
|
||||||
|
|
||||||
# def _load_tools_if_needed(self):
|
|
||||||
# for name, tool in self._tools.items():
|
|
||||||
# if not isinstance(tool, Tool):
|
|
||||||
# task_or_repo_id = tool.task if tool.repo_id is None else tool.repo_id
|
|
||||||
# self._tools[name] = load_tool(task_or_repo_id)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
toolbox_description = "Toolbox contents:\n"
|
|
||||||
for tool in self._tools.values():
|
|
||||||
toolbox_description += f"\t{tool.name}: {tool.description}\n"
|
|
||||||
return toolbox_description
|
|
||||||
|
|
||||||
|
|
||||||
class AgentError(Exception):
|
class AgentError(Exception):
|
||||||
"""Base class for other agent-related exceptions"""
|
"""Base class for other agent-related exceptions"""
|
||||||
|
|
||||||
|
@ -274,6 +87,25 @@ class AgentGenerationError(AgentError):
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ActionStep:
|
||||||
|
tool_call: str | None = None
|
||||||
|
start_time: float | None = None
|
||||||
|
end_time: float | None = None
|
||||||
|
iteration: int | None = None
|
||||||
|
final_answer: Any = None
|
||||||
|
error: AgentError | None = None
|
||||||
|
step_duration: float | None = None
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class PlanningStep:
|
||||||
|
plan: str
|
||||||
|
facts: str
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TaskStep:
|
||||||
|
system_prompt: str
|
||||||
|
task: str
|
||||||
|
|
||||||
def format_prompt_with_tools(toolbox: Toolbox, prompt_template: str, tool_description_template: str) -> str:
|
def format_prompt_with_tools(toolbox: Toolbox, prompt_template: str, tool_description_template: str) -> str:
|
||||||
tool_descriptions = toolbox.show_tool_descriptions(tool_description_template)
|
tool_descriptions = toolbox.show_tool_descriptions(tool_description_template)
|
||||||
|
@ -392,7 +224,7 @@ class Agent:
|
||||||
self.system_prompt = format_prompt_with_imports(
|
self.system_prompt = format_prompt_with_imports(
|
||||||
self.system_prompt, list(set(LIST_SAFE_MODULES) | set(self.authorized_imports))
|
self.system_prompt, list(set(LIST_SAFE_MODULES) | set(self.authorized_imports))
|
||||||
)
|
)
|
||||||
self.logs = [{"system_prompt": self.system_prompt, "task": self.task}]
|
self.logs = [TaskStep(system_prompt=self.system_prompt, task=self.task)]
|
||||||
console.rule("New task", characters='=')
|
console.rule("New task", characters='=')
|
||||||
console.print(self.task)
|
console.print(self.task)
|
||||||
|
|
||||||
|
@ -401,55 +233,58 @@ class Agent:
|
||||||
Reads past llm_outputs, actions, and observations or errors from the logs into a series of messages
|
Reads past llm_outputs, actions, and observations or errors from the logs into a series of messages
|
||||||
that can be used as input to the LLM.
|
that can be used as input to the LLM.
|
||||||
"""
|
"""
|
||||||
prompt_message = {"role": MessageRole.SYSTEM, "content": self.logs[0]["system_prompt"]}
|
prompt_message = {"role": MessageRole.SYSTEM, "content": self.logs[0].system_prompt}
|
||||||
task_message = {
|
task_message = {
|
||||||
"role": MessageRole.USER,
|
"role": MessageRole.USER,
|
||||||
"content": "Task: " + self.logs[0]["task"],
|
"content": "Task: " + self.logs[0].task,
|
||||||
}
|
}
|
||||||
if summary_mode:
|
if summary_mode:
|
||||||
memory = [task_message]
|
memory = [task_message]
|
||||||
else:
|
else:
|
||||||
memory = [prompt_message, task_message]
|
memory = [prompt_message, task_message]
|
||||||
for i, step_log in enumerate(self.logs[1:]):
|
for i, step_log in enumerate(self.logs[1:]):
|
||||||
if "llm_output" in step_log and not summary_mode:
|
|
||||||
thought_message = {"role": MessageRole.ASSISTANT, "content": step_log["llm_output"].strip()}
|
if isinstance(step_log, PlanningStep):
|
||||||
memory.append(thought_message)
|
|
||||||
if "facts" in step_log:
|
|
||||||
thought_message = {
|
thought_message = {
|
||||||
"role": MessageRole.ASSISTANT,
|
"role": MessageRole.ASSISTANT,
|
||||||
"content": "[FACTS LIST]:\n" + step_log["facts"].strip(),
|
"content": "[FACTS LIST]:\n" + step_log.facts.strip(),
|
||||||
}
|
}
|
||||||
memory.append(thought_message)
|
memory.append(thought_message)
|
||||||
|
|
||||||
if "plan" in step_log and not summary_mode:
|
if not summary_mode:
|
||||||
thought_message = {"role": MessageRole.ASSISTANT, "content": "[PLAN]:\n" + step_log["plan"].strip()}
|
thought_message = {"role": MessageRole.ASSISTANT, "content": "[PLAN]:\n" + step_log.plan.strip()}
|
||||||
memory.append(thought_message)
|
memory.append(thought_message)
|
||||||
|
|
||||||
if "tool_call" in step_log and summary_mode:
|
elif isinstance(step_log, TaskStep):
|
||||||
tool_call_message = {
|
task_message = {
|
||||||
"role": MessageRole.ASSISTANT,
|
|
||||||
"content": f"[STEP {i} TOOL CALL]: " + str(step_log["tool_call"]).strip(),
|
|
||||||
}
|
|
||||||
memory.append(tool_call_message)
|
|
||||||
|
|
||||||
if "task" in step_log:
|
|
||||||
tool_call_message = {
|
|
||||||
"role": MessageRole.USER,
|
"role": MessageRole.USER,
|
||||||
"content": "New task:\n" + step_log["task"],
|
"content": "New task:\n" + step_log.task,
|
||||||
}
|
}
|
||||||
memory.append(tool_call_message)
|
memory.append(task_message)
|
||||||
|
|
||||||
if "error" in step_log or "observation" in step_log:
|
elif isinstance(step_log, ActionStep):
|
||||||
if "error" in step_log:
|
if step_log.llm_output is not None and not summary_mode:
|
||||||
message_content = (
|
thought_message = {"role": MessageRole.ASSISTANT, "content": step_log.llm_output.strip()}
|
||||||
f"[OUTPUT OF STEP {i}] -> Error:\n"
|
memory.append(thought_message)
|
||||||
+ str(step_log["error"])
|
|
||||||
+ "\nNow let's retry: take care not to repeat previous errors! If you have retried several times, try a completely different approach.\n"
|
if step_log.tool_call is not None and summary_mode:
|
||||||
)
|
tool_call_message = {
|
||||||
elif "observation" in step_log:
|
"role": MessageRole.ASSISTANT,
|
||||||
message_content = f"[OUTPUT OF STEP {i}] -> Observation:\n{step_log['observation']}"
|
"content": f"[STEP {i} TOOL CALL]: " + str(step_log.tool_call).strip(),
|
||||||
tool_response_message = {"role": MessageRole.TOOL_RESPONSE, "content": message_content}
|
}
|
||||||
memory.append(tool_response_message)
|
memory.append(tool_call_message)
|
||||||
|
|
||||||
|
if step_log.error is not None or step_log.observation is not None:
|
||||||
|
if step_log.error is not None:
|
||||||
|
message_content = (
|
||||||
|
f"[OUTPUT OF STEP {i}] -> Error:\n"
|
||||||
|
+ str(step_log.error)
|
||||||
|
+ "\nNow let's retry: take care not to repeat previous errors! If you have retried several times, try a completely different approach.\n"
|
||||||
|
)
|
||||||
|
elif step_log.observation is not None:
|
||||||
|
message_content = f"[OUTPUT OF STEP {i}] -> Observation:\n{step_log.observation}"
|
||||||
|
tool_response_message = {"role": MessageRole.TOOL_RESPONSE, "content": message_content}
|
||||||
|
memory.append(tool_response_message)
|
||||||
|
|
||||||
return memory
|
return memory
|
||||||
|
|
||||||
|
@ -742,7 +577,7 @@ class ReactAgent(Agent):
|
||||||
if reset:
|
if reset:
|
||||||
self.initialize_for_run()
|
self.initialize_for_run()
|
||||||
else:
|
else:
|
||||||
self.logs.append({"task": task})
|
self.logs.append(TaskStep(task=task))
|
||||||
if stream:
|
if stream:
|
||||||
return self.stream_run(task)
|
return self.stream_run(task)
|
||||||
else:
|
else:
|
||||||
|
@ -756,31 +591,31 @@ class ReactAgent(Agent):
|
||||||
iteration = 0
|
iteration = 0
|
||||||
while final_answer is None and iteration < self.max_iterations:
|
while final_answer is None and iteration < self.max_iterations:
|
||||||
step_start_time = time.time()
|
step_start_time = time.time()
|
||||||
step_log_entry = {"iteration": iteration, "start_time": step_start_time}
|
step_log = ActionStep(iteration=iteration, start_time=step_start_time)
|
||||||
try:
|
try:
|
||||||
self.step(step_log_entry)
|
self.step(step_log)
|
||||||
if "final_answer" in step_log_entry:
|
if step_log.final_answer is not None:
|
||||||
final_answer = step_log_entry["final_answer"]
|
final_answer = step_log.final_answer
|
||||||
except AgentError as e:
|
except AgentError as e:
|
||||||
step_log_entry["error"] = e
|
step_log.error = e
|
||||||
finally:
|
finally:
|
||||||
step_end_time = time.time()
|
step_log.step_end_time = time.time()
|
||||||
step_log_entry["step_end_time"] = step_end_time
|
step_log.step_duration = step_log.step_end_time - step_start_time
|
||||||
step_log_entry["step_duration"] = step_end_time - step_start_time
|
self.logs.append(step_log)
|
||||||
self.logs.append(step_log_entry)
|
|
||||||
for callback in self.step_callbacks:
|
for callback in self.step_callbacks:
|
||||||
callback(step_log_entry)
|
callback(step_log)
|
||||||
iteration += 1
|
iteration += 1
|
||||||
yield step_log_entry
|
yield step_log
|
||||||
|
|
||||||
if final_answer is None and iteration == self.max_iterations:
|
if final_answer is None and iteration == self.max_iterations:
|
||||||
error_message = "Reached max iterations."
|
error_message = "Reached max iterations."
|
||||||
final_step_log = {"error": AgentMaxIterationsError(error_message)}
|
|
||||||
self.logs.append(final_step_log)
|
|
||||||
console.print(f"[bold red]{error_message}")
|
console.print(f"[bold red]{error_message}")
|
||||||
|
final_step_log = ActionStep(error=AgentMaxIterationsError(error_message))
|
||||||
|
self.logs.append(final_step_log)
|
||||||
final_answer = self.provide_final_answer(task)
|
final_answer = self.provide_final_answer(task)
|
||||||
final_step_log["final_answer"] = final_answer
|
final_step_log.final_answer = final_answer
|
||||||
final_step_log["step_duration"] = 0
|
final_step_log.step_end_time = time.time()
|
||||||
|
final_step_log.step_duration = step_log.step_end_time - step_start_time
|
||||||
for callback in self.step_callbacks:
|
for callback in self.step_callbacks:
|
||||||
callback(final_step_log)
|
callback(final_step_log)
|
||||||
yield final_step_log
|
yield final_step_log
|
||||||
|
@ -795,32 +630,32 @@ class ReactAgent(Agent):
|
||||||
iteration = 0
|
iteration = 0
|
||||||
while final_answer is None and iteration < self.max_iterations:
|
while final_answer is None and iteration < self.max_iterations:
|
||||||
step_start_time = time.time()
|
step_start_time = time.time()
|
||||||
step_log_entry = {"iteration": iteration, "start_time": step_start_time}
|
step_log = ActionStep(iteration=iteration, start_time=step_start_time)
|
||||||
try:
|
try:
|
||||||
if self.planning_interval is not None and iteration % self.planning_interval == 0:
|
if self.planning_interval is not None and iteration % self.planning_interval == 0:
|
||||||
self.planning_step(task, is_first_step=(iteration == 0), iteration=iteration)
|
self.planning_step(task, is_first_step=(iteration == 0), iteration=iteration)
|
||||||
self.step(step_log_entry)
|
self.step(step_log)
|
||||||
if "final_answer" in step_log_entry:
|
if step_log.final_answer is not None:
|
||||||
final_answer = step_log_entry["final_answer"]
|
final_answer = step_log.final_answer
|
||||||
except AgentError as e:
|
except AgentError as e:
|
||||||
step_log_entry["error"] = e
|
step_log.error = e
|
||||||
finally:
|
finally:
|
||||||
step_end_time = time.time()
|
step_end_time = time.time()
|
||||||
step_log_entry["step_end_time"] = step_end_time
|
step_log.step_end_time = step_end_time
|
||||||
step_log_entry["step_duration"] = step_end_time - step_start_time
|
step_log.step_duration = step_end_time - step_start_time
|
||||||
self.logs.append(step_log_entry)
|
self.logs.append(step_log)
|
||||||
for callback in self.step_callbacks:
|
for callback in self.step_callbacks:
|
||||||
callback(step_log_entry)
|
callback(step_log)
|
||||||
iteration += 1
|
iteration += 1
|
||||||
|
|
||||||
if final_answer is None and iteration == self.max_iterations:
|
if final_answer is None and iteration == self.max_iterations:
|
||||||
error_message = "Reached max iterations."
|
error_message = "Reached max iterations."
|
||||||
final_step_log = {"error": AgentMaxIterationsError(error_message)}
|
final_step_log = ActionStep(error=AgentMaxIterationsError(error_message))
|
||||||
self.logs.append(final_step_log)
|
self.logs.append(final_step_log)
|
||||||
console.print(f"[bold red]{error_message}")
|
console.print(f"[bold red]{error_message}")
|
||||||
final_answer = self.provide_final_answer(task)
|
final_answer = self.provide_final_answer(task)
|
||||||
final_step_log["final_answer"] = final_answer
|
final_step_log.final_answer = final_answer
|
||||||
final_step_log["step_duration"] = 0
|
final_step_log.step_duration = 0
|
||||||
for callback in self.step_callbacks:
|
for callback in self.step_callbacks:
|
||||||
callback(final_step_log)
|
callback(final_step_log)
|
||||||
|
|
||||||
|
@ -875,7 +710,7 @@ Now begin!""",
|
||||||
```
|
```
|
||||||
{answer_facts}
|
{answer_facts}
|
||||||
```""".strip()
|
```""".strip()
|
||||||
self.logs.append({"plan": final_plan_redaction, "facts": final_facts_redaction})
|
self.logs.append(PlanningStep(plan=final_plan_redaction, facts=final_facts_redaction))
|
||||||
console.rule("[orange]Initial plan")
|
console.rule("[orange]Initial plan")
|
||||||
console.print(final_plan_redaction)
|
console.print(final_plan_redaction)
|
||||||
else: # update plan
|
else: # update plan
|
||||||
|
@ -921,8 +756,8 @@ Now begin!""",
|
||||||
```
|
```
|
||||||
{facts_update}
|
{facts_update}
|
||||||
```"""
|
```"""
|
||||||
self.logs.append({"plan": final_plan_redaction, "facts": final_facts_redaction})
|
self.logs.append(PlanningStep(plan=final_plan_redaction, facts=final_facts_redaction))
|
||||||
console.rule("Updated plan")
|
console.rule("[orange]Updated plan")
|
||||||
console.print(final_plan_redaction)
|
console.print(final_plan_redaction)
|
||||||
|
|
||||||
|
|
||||||
|
@ -959,7 +794,7 @@ class ReactJsonAgent(ReactAgent):
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
def step(self, log_entry: Dict[str, Any]):
|
def step(self, log_entry: ActionStep):
|
||||||
"""
|
"""
|
||||||
Perform one step in the ReAct framework: the agent thinks, acts, and observes the result.
|
Perform one step in the ReAct framework: the agent thinks, acts, and observes the result.
|
||||||
The errors are raised here, they are caught and logged in the run() method.
|
The errors are raised here, they are caught and logged in the run() method.
|
||||||
|
@ -970,7 +805,7 @@ class ReactJsonAgent(ReactAgent):
|
||||||
console.rule("New step")
|
console.rule("New step")
|
||||||
|
|
||||||
# Add new step in logs
|
# Add new step in logs
|
||||||
log_entry["agent_memory"] = agent_memory.copy()
|
log_entry.agent_memory = agent_memory.copy()
|
||||||
|
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
console.rule("Calling LLM with this last message:")
|
console.rule("Calling LLM with this last message:")
|
||||||
|
@ -985,7 +820,7 @@ class ReactJsonAgent(ReactAgent):
|
||||||
raise AgentGenerationError(f"Error in generating llm output: {e}.")
|
raise AgentGenerationError(f"Error in generating llm output: {e}.")
|
||||||
console.rule("===== Output message of the LLM: =====")
|
console.rule("===== Output message of the LLM: =====")
|
||||||
console.print(llm_output)
|
console.print(llm_output)
|
||||||
log_entry["llm_output"] = llm_output
|
log_entry.llm_output = llm_output
|
||||||
|
|
||||||
# Parse
|
# Parse
|
||||||
console.rule("===== Extracting action =====")
|
console.rule("===== Extracting action =====")
|
||||||
|
@ -996,8 +831,8 @@ class ReactJsonAgent(ReactAgent):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise AgentParsingError(f"Could not parse the given action: {e}.")
|
raise AgentParsingError(f"Could not parse the given action: {e}.")
|
||||||
|
|
||||||
log_entry["rationale"] = rationale
|
log_entry.rationale = rationale
|
||||||
log_entry["tool_call"] = {"tool_name": tool_name, "tool_arguments": arguments}
|
log_entry.tool_call = {"tool_name": tool_name, "tool_arguments": arguments}
|
||||||
|
|
||||||
# Execute
|
# Execute
|
||||||
console.print("=== Agent thoughts:")
|
console.print("=== Agent thoughts:")
|
||||||
|
@ -1015,7 +850,7 @@ class ReactJsonAgent(ReactAgent):
|
||||||
answer = arguments
|
answer = arguments
|
||||||
else:
|
else:
|
||||||
answer = arguments
|
answer = arguments
|
||||||
log_entry["final_answer"] = answer
|
log_entry.final_answer = answer
|
||||||
return answer
|
return answer
|
||||||
else:
|
else:
|
||||||
if arguments is None:
|
if arguments is None:
|
||||||
|
@ -1033,7 +868,7 @@ class ReactJsonAgent(ReactAgent):
|
||||||
updated_information = f"Stored '{observation_name}' in memory."
|
updated_information = f"Stored '{observation_name}' in memory."
|
||||||
else:
|
else:
|
||||||
updated_information = str(observation).strip()
|
updated_information = str(observation).strip()
|
||||||
log_entry["observation"] = updated_information
|
log_entry.observation = updated_information
|
||||||
return log_entry
|
return log_entry
|
||||||
|
|
||||||
|
|
||||||
|
@ -1088,7 +923,7 @@ class ReactCodeAgent(ReactAgent):
|
||||||
console.rule("New step")
|
console.rule("New step")
|
||||||
|
|
||||||
# Add new step in logs
|
# Add new step in logs
|
||||||
log_entry["agent_memory"] = agent_memory.copy()
|
log_entry.agent_memory = agent_memory.copy()
|
||||||
|
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
console.print("===== Calling LLM with these last messages: =====")
|
console.print("===== Calling LLM with these last messages: =====")
|
||||||
|
@ -1105,7 +940,7 @@ class ReactCodeAgent(ReactAgent):
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
console.rule("Output message of the LLM:")
|
console.rule("Output message of the LLM:")
|
||||||
console.print(llm_output)
|
console.print(llm_output)
|
||||||
log_entry["llm_output"] = llm_output
|
log_entry.llm_output = llm_output
|
||||||
|
|
||||||
# Parse
|
# Parse
|
||||||
try:
|
try:
|
||||||
|
@ -1120,8 +955,8 @@ class ReactCodeAgent(ReactAgent):
|
||||||
error_msg = f"Error in code parsing: {e}. Make sure to provide correct code"
|
error_msg = f"Error in code parsing: {e}. Make sure to provide correct code"
|
||||||
raise AgentParsingError(error_msg)
|
raise AgentParsingError(error_msg)
|
||||||
|
|
||||||
log_entry["rationale"] = rationale
|
log_entry.rationale = rationale
|
||||||
log_entry["tool_call"] = {"tool_name": "code interpreter", "tool_arguments": code_action}
|
log_entry.tool_call = {"tool_name": "code interpreter", "tool_arguments": code_action}
|
||||||
|
|
||||||
# Execute
|
# Execute
|
||||||
self.log_rationale_code_action(rationale, code_action)
|
self.log_rationale_code_action(rationale, code_action)
|
||||||
|
@ -1145,8 +980,8 @@ class ReactCodeAgent(ReactAgent):
|
||||||
if result is not None:
|
if result is not None:
|
||||||
console.print("Last output from code snippet:")
|
console.print("Last output from code snippet:")
|
||||||
console.print(str(result))
|
console.print(str(result))
|
||||||
observation += "Last output from code snippet:\n" + str(result)[:100000]
|
observation += "Last output from code snippet:\n" + str(result)[:LENGTH_TRUNCATE_REPORTS]
|
||||||
log_entry["observation"] = observation
|
log_entry.observation = observation
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_msg = f"Code execution failed due to the following error:\n{str(e)}"
|
error_msg = f"Code execution failed due to the following error:\n{str(e)}"
|
||||||
if "'dict' object has no attribute 'read'" in str(e):
|
if "'dict' object has no attribute 'read'" in str(e):
|
||||||
|
@ -1156,13 +991,9 @@ class ReactCodeAgent(ReactAgent):
|
||||||
if line[: len("final_answer")] == "final_answer":
|
if line[: len("final_answer")] == "final_answer":
|
||||||
console.print("Final answer:")
|
console.print("Final answer:")
|
||||||
console.print(f"[bold]{result}")
|
console.print(f"[bold]{result}")
|
||||||
log_entry["final_answer"] = result
|
log_entry.final_answer = result
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
LENGTH_TRUNCATE_REPORTS = 1000
|
|
||||||
|
|
||||||
|
|
||||||
class ManagedAgent:
|
class ManagedAgent:
|
||||||
def __init__(self, agent, name, description, additional_prompting=None, provide_run_summary=False):
|
def __init__(self, agent, name, description, additional_prompting=None, provide_run_summary=False):
|
||||||
self.agent = agent
|
self.agent = agent
|
||||||
|
|
|
@ -102,7 +102,7 @@ class Monitor:
|
||||||
self.total_output_token_count = 0
|
self.total_output_token_count = 0
|
||||||
|
|
||||||
def update_metrics(self, step_log):
|
def update_metrics(self, step_log):
|
||||||
step_duration = step_log["step_duration"]
|
step_duration = step_log.step_duration
|
||||||
self.step_durations.append(step_duration)
|
self.step_durations.append(step_duration)
|
||||||
console.print(f"Step {len(self.step_durations)}:")
|
console.print(f"Step {len(self.step_durations)}:")
|
||||||
console.print(f"- Time taken: {step_duration:.2f} seconds")
|
console.print(f"- Time taken: {step_duration:.2f} seconds")
|
||||||
|
@ -110,6 +110,6 @@ class Monitor:
|
||||||
if getattr(self.tracked_llm_engine, "last_input_token_count", None) is not None:
|
if getattr(self.tracked_llm_engine, "last_input_token_count", None) is not None:
|
||||||
self.total_input_token_count += self.tracked_llm_engine.last_input_token_count
|
self.total_input_token_count += self.tracked_llm_engine.last_input_token_count
|
||||||
self.total_output_token_count += self.tracked_llm_engine.last_output_token_count
|
self.total_output_token_count += self.tracked_llm_engine.last_output_token_count
|
||||||
console.print(f"- Input tokens: {self.total_input_token_count}")
|
console.print(f"- Input tokens: {self.total_input_token_count:,}")
|
||||||
console.print(f"- Output tokens: {self.total_output_token_count}")
|
console.print(f"- Output tokens: {self.total_output_token_count:,}")
|
||||||
|
|
||||||
|
|
103
agents/tools.py
103
agents/tools.py
|
@ -1000,3 +1000,106 @@ def tool(tool_function: Callable) -> Tool:
|
||||||
|
|
||||||
SpecificTool.__name__ = class_name
|
SpecificTool.__name__ = class_name
|
||||||
return SpecificTool()
|
return SpecificTool()
|
||||||
|
|
||||||
|
|
||||||
|
class Toolbox:
|
||||||
|
"""
|
||||||
|
The toolbox contains all tools that the agent can perform operations with, as well as a few methods to
|
||||||
|
manage them.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tools (`List[Tool]`):
|
||||||
|
The list of tools to instantiate the toolbox with
|
||||||
|
add_base_tools (`bool`, defaults to `False`, *optional*, defaults to `False`):
|
||||||
|
Whether to add the tools available within `transformers` to the toolbox.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, tools: List[Tool], add_base_tools: bool = False):
|
||||||
|
self._tools = {tool.name: tool for tool in tools}
|
||||||
|
if add_base_tools:
|
||||||
|
self.add_base_tools()
|
||||||
|
# self._load_tools_if_needed()
|
||||||
|
|
||||||
|
def add_base_tools(self, add_python_interpreter: bool = False):
|
||||||
|
global _tools_are_initialized
|
||||||
|
global HUGGINGFACE_DEFAULT_TOOLS
|
||||||
|
if not _tools_are_initialized:
|
||||||
|
HUGGINGFACE_DEFAULT_TOOLS = setup_default_tools()
|
||||||
|
_tools_are_initialized = True
|
||||||
|
for tool in HUGGINGFACE_DEFAULT_TOOLS.values():
|
||||||
|
if tool.name != "python_interpreter" or add_python_interpreter:
|
||||||
|
self.add_tool(tool)
|
||||||
|
# self._load_tools_if_needed()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tools(self) -> Dict[str, Tool]:
|
||||||
|
"""Get all tools currently in the toolbox"""
|
||||||
|
return self._tools
|
||||||
|
|
||||||
|
def show_tool_descriptions(self, tool_description_template: str = None) -> str:
|
||||||
|
"""
|
||||||
|
Returns the description of all tools in the toolbox
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tool_description_template (`str`, *optional*):
|
||||||
|
The template to use to describe the tools. If not provided, the default template will be used.
|
||||||
|
"""
|
||||||
|
return "\n".join(
|
||||||
|
[get_tool_description_with_args(tool, tool_description_template) for tool in self._tools.values()]
|
||||||
|
)
|
||||||
|
|
||||||
|
def add_tool(self, tool: Tool):
|
||||||
|
"""
|
||||||
|
Adds a tool to the toolbox
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tool (`Tool`):
|
||||||
|
The tool to add to the toolbox.
|
||||||
|
"""
|
||||||
|
if tool.name in self._tools:
|
||||||
|
raise KeyError(f"Error: tool '{tool.name}' already exists in the toolbox.")
|
||||||
|
self._tools[tool.name] = tool
|
||||||
|
|
||||||
|
def remove_tool(self, tool_name: str):
|
||||||
|
"""
|
||||||
|
Removes a tool from the toolbox
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tool_name (`str`):
|
||||||
|
The tool to remove from the toolbox.
|
||||||
|
"""
|
||||||
|
if tool_name not in self._tools:
|
||||||
|
raise KeyError(
|
||||||
|
f"Error: tool {tool_name} not found in toolbox for removal, should be instead one of {list(self._tools.keys())}."
|
||||||
|
)
|
||||||
|
del self._tools[tool_name]
|
||||||
|
|
||||||
|
def update_tool(self, tool: Tool):
|
||||||
|
"""
|
||||||
|
Updates a tool in the toolbox according to its name.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tool (`Tool`):
|
||||||
|
The tool to update to the toolbox.
|
||||||
|
"""
|
||||||
|
if tool.name not in self._tools:
|
||||||
|
raise KeyError(
|
||||||
|
f"Error: tool {tool.name} not found in toolbox for update, should be instead one of {list(self._tools.keys())}."
|
||||||
|
)
|
||||||
|
self._tools[tool.name] = tool
|
||||||
|
|
||||||
|
def clear_toolbox(self):
|
||||||
|
"""Clears the toolbox"""
|
||||||
|
self._tools = {}
|
||||||
|
|
||||||
|
# def _load_tools_if_needed(self):
|
||||||
|
# for name, tool in self._tools.items():
|
||||||
|
# if not isinstance(tool, Tool):
|
||||||
|
# task_or_repo_id = tool.task if tool.repo_id is None else tool.repo_id
|
||||||
|
# self._tools[name] = load_tool(task_or_repo_id)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
toolbox_description = "Toolbox contents:\n"
|
||||||
|
for tool in self._tools.values():
|
||||||
|
toolbox_description += f"\t{tool.name}: {tool.description}\n"
|
||||||
|
return toolbox_description
|
||||||
|
|
|
@ -1,3 +1,22 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
# Copyright 2023 The HuggingFace Inc. team. All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
from typing import Tuple, Dict
|
||||||
|
|
||||||
from transformers.utils.import_utils import _is_package_available
|
from transformers.utils.import_utils import _is_package_available
|
||||||
|
|
||||||
|
@ -8,3 +27,57 @@ def is_pygments_available():
|
||||||
|
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
console = Console()
|
console = Console()
|
||||||
|
|
||||||
|
|
||||||
|
def parse_json_blob(json_blob: str) -> Dict[str, str]:
|
||||||
|
try:
|
||||||
|
first_accolade_index = json_blob.find("{")
|
||||||
|
last_accolade_index = [a.start() for a in list(re.finditer("}", json_blob))][-1]
|
||||||
|
json_blob = json_blob[first_accolade_index : last_accolade_index + 1].replace('\\"', "'")
|
||||||
|
json_data = json.loads(json_blob, strict=False)
|
||||||
|
return json_data
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
place = e.pos
|
||||||
|
if json_blob[place - 1 : place + 2] == "},\n":
|
||||||
|
raise ValueError(
|
||||||
|
"JSON is invalid: you probably tried to provide multiple tool calls in one action. PROVIDE ONLY ONE TOOL CALL."
|
||||||
|
)
|
||||||
|
raise ValueError(
|
||||||
|
f"The JSON blob you used is invalid due to the following error: {e}.\n"
|
||||||
|
f"JSON blob was: {json_blob}, decoding failed on that specific part of the blob:\n"
|
||||||
|
f"'{json_blob[place-4:place+5]}'."
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
raise ValueError(f"Error in parsing the JSON blob: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
def parse_code_blob(code_blob: str) -> str:
|
||||||
|
try:
|
||||||
|
pattern = r"```(?:py|python)?\n(.*?)\n```"
|
||||||
|
match = re.search(pattern, code_blob, re.DOTALL)
|
||||||
|
return match.group(1).strip()
|
||||||
|
except Exception as e:
|
||||||
|
raise ValueError(
|
||||||
|
f"""
|
||||||
|
The code blob you used is invalid: due to the following error: {e}
|
||||||
|
This means that the regex pattern {pattern} was not respected: make sure to include code with the correct pattern, for instance:
|
||||||
|
Thoughts: Your thoughts
|
||||||
|
Code:
|
||||||
|
```py
|
||||||
|
# Your python code here
|
||||||
|
```<end_action>"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_json_tool_call(json_blob: str) -> Tuple[str, Dict[str, str]]:
|
||||||
|
json_blob = json_blob.replace("```json", "").replace("```", "")
|
||||||
|
tool_call = parse_json_blob(json_blob)
|
||||||
|
if "action" in tool_call and "action_input" in tool_call:
|
||||||
|
return tool_call["action"], tool_call["action_input"]
|
||||||
|
elif "action" in tool_call:
|
||||||
|
return tool_call["action"], None
|
||||||
|
else:
|
||||||
|
missing_keys = [key for key in ['action', 'action_input'] if key not in tool_call]
|
||||||
|
error_msg = f"Missing keys: {missing_keys} in blob {tool_call}"
|
||||||
|
console.print(f"[bold red]{error_msg}[/bold red]")
|
||||||
|
raise ValueError(error_msg)
|
|
@ -0,0 +1,36 @@
|
||||||
|
from agents import load_tool, ReactCodeAgent, ReactJsonAgent, HfApiEngine
|
||||||
|
from agents.default_tools import PythonInterpreterTool
|
||||||
|
|
||||||
|
# Import tool from Hub
|
||||||
|
image_generation_tool = load_tool("m-ric/text-to-image", cache=False)
|
||||||
|
|
||||||
|
from agents.search import DuckDuckGoSearchTool
|
||||||
|
|
||||||
|
search_tool = DuckDuckGoSearchTool()
|
||||||
|
|
||||||
|
llm_engine = HfApiEngine("Qwen/Qwen2.5-72B-Instruct")
|
||||||
|
|
||||||
|
agent = ReactCodeAgent(tools=[search_tool], llm_engine=llm_engine, planning_interval=3)
|
||||||
|
|
||||||
|
# Run it!
|
||||||
|
print("Let's run the Code agent:")
|
||||||
|
|
||||||
|
result = agent.run(
|
||||||
|
"How long would a cheetah at full speed take to run the length of Pont Alexandre III?",
|
||||||
|
)
|
||||||
|
|
||||||
|
print("RESULT:", result)
|
||||||
|
|
||||||
|
|
||||||
|
code_tool = PythonInterpreterTool()
|
||||||
|
|
||||||
|
agent = ReactJsonAgent(tools=[search_tool, code_tool], llm_engine=llm_engine, planning_interval=3)
|
||||||
|
|
||||||
|
print("====================")
|
||||||
|
print("====================")
|
||||||
|
print("Now let's run the JSON agent:")
|
||||||
|
result = agent.run(
|
||||||
|
"How long would a cheetah at full speed take to run the length of Pont Alexandre III?",
|
||||||
|
)
|
||||||
|
|
||||||
|
print("RESULT:", result)
|
|
@ -1,11 +1,9 @@
|
||||||
from agents import load_tool, ReactCodeAgent, HfApiEngine
|
from agents import load_tool, ReactCodeAgent, HfApiEngine
|
||||||
|
from agents.search import DuckDuckGoSearchTool
|
||||||
|
|
||||||
# Import tool from Hub
|
# Import tool from Hub
|
||||||
image_generation_tool = load_tool("m-ric/text-to-image", cache=False)
|
image_generation_tool = load_tool("m-ric/text-to-image", cache=False)
|
||||||
|
|
||||||
# Import tool from LangChain
|
|
||||||
from agents.search import DuckDuckGoSearchTool
|
|
||||||
|
|
||||||
search_tool = DuckDuckGoSearchTool()
|
search_tool = DuckDuckGoSearchTool()
|
||||||
|
|
||||||
llm_engine = HfApiEngine("Qwen/Qwen2.5-72B-Instruct")
|
llm_engine = HfApiEngine("Qwen/Qwen2.5-72B-Instruct")
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
from agents.llm_engine import TransformersEngine
|
||||||
|
from agents import CodeAgent, ReactJsonAgent
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
model_repo="andito/SmolLM2-1.7B-Instruct-F16-GGUF"
|
||||||
|
model_filename="smollm2-1.7b-8k-dpo-f16.gguf"
|
||||||
|
|
||||||
|
import random
|
||||||
|
from llama_cpp import Llama
|
||||||
|
|
||||||
|
model = Llama.from_pretrained(
|
||||||
|
repo_id=model_repo,
|
||||||
|
filename=model_filename,
|
||||||
|
n_ctx=8192,
|
||||||
|
verbose=False
|
||||||
|
)
|
||||||
|
print("Model initialized")
|
||||||
|
|
||||||
|
def llm_engine(messages, stop_sequences=["Task", "<|endoftext|>"]) -> str:
|
||||||
|
output = ""
|
||||||
|
for chunk in model.create_chat_completion(
|
||||||
|
messages=messages,
|
||||||
|
max_tokens=2048,
|
||||||
|
temperature=0.0,
|
||||||
|
top_p=1.0,
|
||||||
|
top_k=50,
|
||||||
|
repeat_penalty=1.0,
|
||||||
|
stream=True
|
||||||
|
):
|
||||||
|
content = chunk['choices'][0]['delta'].get('content')
|
||||||
|
if content:
|
||||||
|
if content in ["<end_action>", "<|endoftext|>"]:
|
||||||
|
break
|
||||||
|
output += content
|
||||||
|
return output
|
||||||
|
|
||||||
|
system_prompt = """You are an expert in composing functions. You are given a question and a set of possible functions.
|
||||||
|
Based on the question, you will need to make one or more function/tool calls to achieve the purpose.
|
||||||
|
If none of the functions can be used, point it out and refuse to answer.
|
||||||
|
If the given question lacks the parameters required by the function, also point it out.
|
||||||
|
|
||||||
|
You have access to the following tools:
|
||||||
|
<<tool_descriptions>>
|
||||||
|
|
||||||
|
<<managed_agents_descriptions>>
|
||||||
|
|
||||||
|
You can use imports in your code, but only from the following list of modules: <<authorized_imports>>
|
||||||
|
|
||||||
|
The output MUST strictly adhere to the following format, and NO other text MUST be included.
|
||||||
|
The example format is as follows. Please make sure the parameter type is correct. If no function call is needed, please make the tool calls an empty list '[]'.
|
||||||
|
<tool_call>[
|
||||||
|
{"name": "func_name1", "arguments": {"argument1": "value1", "argument2": "value2"}},
|
||||||
|
... (more tool calls as required)
|
||||||
|
]</tool_call>"""
|
||||||
|
|
||||||
|
|
||||||
|
from agents import tool
|
||||||
|
import webbrowser
|
||||||
|
|
||||||
|
@tool
|
||||||
|
def get_random_number_between(min: int, max: int) -> int:
|
||||||
|
"""
|
||||||
|
Gets a random number between min and max.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
min: The minimum number.
|
||||||
|
max: The maximum number.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A random number between min and max.
|
||||||
|
"""
|
||||||
|
return random.randint(min, max)
|
||||||
|
|
||||||
|
|
||||||
|
@tool
|
||||||
|
def get_weather(city: str) -> str:
|
||||||
|
"""
|
||||||
|
Returns the weather forecast for a given city.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
city: The name of the city.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string with a mock weather forecast.
|
||||||
|
"""
|
||||||
|
url = 'https://wttr.in/{}?format=+%C,+%t'.format(city)
|
||||||
|
res = requests.get(url).text
|
||||||
|
|
||||||
|
return f"The weather in {city} is {res.split(',')[0]} with a high of {res.split(',')[1][:-2]} degrees Celsius."
|
||||||
|
|
||||||
|
@tool
|
||||||
|
def get_current_time() -> str:
|
||||||
|
"""
|
||||||
|
This is a tool that returns the current time.
|
||||||
|
It returns the current time as HH:MM.
|
||||||
|
"""
|
||||||
|
return f"The current time is {datetime.now().hour}:{datetime.now().minute}."
|
||||||
|
|
||||||
|
@tool
|
||||||
|
def open_webbrowser(url: str) -> str:
|
||||||
|
"""
|
||||||
|
This is a tool that opens a web browser to the given website.
|
||||||
|
If the user asks to open a website or a browser, you should use this tool.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
url: The url to open.
|
||||||
|
"""
|
||||||
|
webbrowser.open(url)
|
||||||
|
return f"I opened {url.replace('https://', '').replace('www.', '')} in the browser."
|
||||||
|
|
||||||
|
|
||||||
|
agent = ReactJsonAgent(llm_engine = llm_engine, tools=[get_current_time, open_webbrowser, get_random_number_between, get_weather])
|
||||||
|
print("Agent initialized!")
|
||||||
|
agent.run("What's the weather like in London?")
|
|
@ -136,6 +136,17 @@ files = [
|
||||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diskcache"
|
||||||
|
version = "5.6.3"
|
||||||
|
description = "Disk Cache -- Disk and file backed persistent cache."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3"
|
||||||
|
files = [
|
||||||
|
{file = "diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19"},
|
||||||
|
{file = "diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "exceptiongroup"
|
name = "exceptiongroup"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
|
@ -264,6 +275,45 @@ files = [
|
||||||
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jinja2"
|
||||||
|
version = "3.1.4"
|
||||||
|
description = "A very fast and expressive template engine."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
|
||||||
|
{file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
MarkupSafe = ">=2.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
i18n = ["Babel (>=2.7)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "llama-cpp-python"
|
||||||
|
version = "0.3.4"
|
||||||
|
description = "Python bindings for the llama.cpp library"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "llama_cpp_python-0.3.4.tar.gz", hash = "sha256:52b37129c282753edf89213e852b8b46664b059116ae2213da9cb4a45374d23d"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
diskcache = ">=5.6.1"
|
||||||
|
jinja2 = ">=2.11.3"
|
||||||
|
numpy = ">=1.20.0"
|
||||||
|
typing-extensions = ">=4.5.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
all = ["llama_cpp_python[dev,server,test]"]
|
||||||
|
dev = ["black (>=23.3.0)", "httpx (>=0.24.1)", "mkdocs (>=1.4.3)", "mkdocs-material (>=9.1.18)", "mkdocstrings[python] (>=0.22.0)", "pytest (>=7.4.0)", "twine (>=4.0.2)"]
|
||||||
|
server = ["PyYAML (>=5.1)", "fastapi (>=0.100.0)", "pydantic-settings (>=2.0.1)", "sse-starlette (>=1.6.1)", "starlette-context (>=0.3.6,<0.4)", "uvicorn (>=0.22.0)"]
|
||||||
|
test = ["fastapi (>=0.100.0)", "httpx (>=0.24.1)", "huggingface-hub (>=0.23.0)", "pydantic-settings (>=2.0.1)", "pytest (>=7.4.0)", "scipy (>=1.10)", "sse-starlette (>=1.6.1)", "starlette-context (>=0.3.6,<0.4)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "markdown-it-py"
|
name = "markdown-it-py"
|
||||||
version = "3.0.0"
|
version = "3.0.0"
|
||||||
|
@ -288,6 +338,76 @@ profiling = ["gprof2dot"]
|
||||||
rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
|
rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
|
||||||
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
|
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "markupsafe"
|
||||||
|
version = "3.0.2"
|
||||||
|
description = "Safely add untrusted strings to HTML/XML markup."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"},
|
||||||
|
{file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"},
|
||||||
|
{file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mdurl"
|
name = "mdurl"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -374,6 +494,184 @@ files = [
|
||||||
{file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
|
{file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pandas"
|
||||||
|
version = "2.2.3"
|
||||||
|
description = "Powerful data structures for data analysis, time series, and statistics"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5"},
|
||||||
|
{file = "pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348"},
|
||||||
|
{file = "pandas-2.2.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed"},
|
||||||
|
{file = "pandas-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57"},
|
||||||
|
{file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42"},
|
||||||
|
{file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f"},
|
||||||
|
{file = "pandas-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645"},
|
||||||
|
{file = "pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039"},
|
||||||
|
{file = "pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd"},
|
||||||
|
{file = "pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698"},
|
||||||
|
{file = "pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc"},
|
||||||
|
{file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3"},
|
||||||
|
{file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32"},
|
||||||
|
{file = "pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5"},
|
||||||
|
{file = "pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9"},
|
||||||
|
{file = "pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4"},
|
||||||
|
{file = "pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3"},
|
||||||
|
{file = "pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319"},
|
||||||
|
{file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8"},
|
||||||
|
{file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a"},
|
||||||
|
{file = "pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13"},
|
||||||
|
{file = "pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015"},
|
||||||
|
{file = "pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28"},
|
||||||
|
{file = "pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0"},
|
||||||
|
{file = "pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24"},
|
||||||
|
{file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659"},
|
||||||
|
{file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb"},
|
||||||
|
{file = "pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d"},
|
||||||
|
{file = "pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468"},
|
||||||
|
{file = "pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18"},
|
||||||
|
{file = "pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2"},
|
||||||
|
{file = "pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4"},
|
||||||
|
{file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d"},
|
||||||
|
{file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a"},
|
||||||
|
{file = "pandas-2.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39"},
|
||||||
|
{file = "pandas-2.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5dbca4c1acd72e8eeef4753eeca07de9b1db4f398669d5994086f788a5d7cc30"},
|
||||||
|
{file = "pandas-2.2.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8cd6d7cc958a3910f934ea8dbdf17b2364827bb4dafc38ce6eef6bb3d65ff09c"},
|
||||||
|
{file = "pandas-2.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c"},
|
||||||
|
{file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31d0ced62d4ea3e231a9f228366919a5ea0b07440d9d4dac345376fd8e1477ea"},
|
||||||
|
{file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761"},
|
||||||
|
{file = "pandas-2.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e"},
|
||||||
|
{file = "pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
numpy = [
|
||||||
|
{version = ">=1.22.4", markers = "python_version < \"3.11\""},
|
||||||
|
{version = ">=1.23.2", markers = "python_version == \"3.11\""},
|
||||||
|
{version = ">=1.26.0", markers = "python_version >= \"3.12\""},
|
||||||
|
]
|
||||||
|
python-dateutil = ">=2.8.2"
|
||||||
|
pytz = ">=2020.1"
|
||||||
|
tzdata = ">=2022.7"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"]
|
||||||
|
aws = ["s3fs (>=2022.11.0)"]
|
||||||
|
clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"]
|
||||||
|
compression = ["zstandard (>=0.19.0)"]
|
||||||
|
computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"]
|
||||||
|
consortium-standard = ["dataframe-api-compat (>=0.1.7)"]
|
||||||
|
excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"]
|
||||||
|
feather = ["pyarrow (>=10.0.1)"]
|
||||||
|
fss = ["fsspec (>=2022.11.0)"]
|
||||||
|
gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"]
|
||||||
|
hdf5 = ["tables (>=3.8.0)"]
|
||||||
|
html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"]
|
||||||
|
mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"]
|
||||||
|
output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"]
|
||||||
|
parquet = ["pyarrow (>=10.0.1)"]
|
||||||
|
performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"]
|
||||||
|
plot = ["matplotlib (>=3.6.3)"]
|
||||||
|
postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"]
|
||||||
|
pyarrow = ["pyarrow (>=10.0.1)"]
|
||||||
|
spss = ["pyreadstat (>=1.2.0)"]
|
||||||
|
sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"]
|
||||||
|
test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"]
|
||||||
|
xml = ["lxml (>=4.9.2)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pillow"
|
||||||
|
version = "11.0.0"
|
||||||
|
description = "Python Imaging Library (Fork)"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "pillow-11.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6619654954dc4936fcff82db8eb6401d3159ec6be81e33c6000dfd76ae189947"},
|
||||||
|
{file = "pillow-11.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b3c5ac4bed7519088103d9450a1107f76308ecf91d6dabc8a33a2fcfb18d0fba"},
|
||||||
|
{file = "pillow-11.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a65149d8ada1055029fcb665452b2814fe7d7082fcb0c5bed6db851cb69b2086"},
|
||||||
|
{file = "pillow-11.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88a58d8ac0cc0e7f3a014509f0455248a76629ca9b604eca7dc5927cc593c5e9"},
|
||||||
|
{file = "pillow-11.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:c26845094b1af3c91852745ae78e3ea47abf3dbcd1cf962f16b9a5fbe3ee8488"},
|
||||||
|
{file = "pillow-11.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:1a61b54f87ab5786b8479f81c4b11f4d61702830354520837f8cc791ebba0f5f"},
|
||||||
|
{file = "pillow-11.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:674629ff60030d144b7bca2b8330225a9b11c482ed408813924619c6f302fdbb"},
|
||||||
|
{file = "pillow-11.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:598b4e238f13276e0008299bd2482003f48158e2b11826862b1eb2ad7c768b97"},
|
||||||
|
{file = "pillow-11.0.0-cp310-cp310-win32.whl", hash = "sha256:9a0f748eaa434a41fccf8e1ee7a3eed68af1b690e75328fd7a60af123c193b50"},
|
||||||
|
{file = "pillow-11.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:a5629742881bcbc1f42e840af185fd4d83a5edeb96475a575f4da50d6ede337c"},
|
||||||
|
{file = "pillow-11.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:ee217c198f2e41f184f3869f3e485557296d505b5195c513b2bfe0062dc537f1"},
|
||||||
|
{file = "pillow-11.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1c1d72714f429a521d8d2d018badc42414c3077eb187a59579f28e4270b4b0fc"},
|
||||||
|
{file = "pillow-11.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:499c3a1b0d6fc8213519e193796eb1a86a1be4b1877d678b30f83fd979811d1a"},
|
||||||
|
{file = "pillow-11.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8b2351c85d855293a299038e1f89db92a2f35e8d2f783489c6f0b2b5f3fe8a3"},
|
||||||
|
{file = "pillow-11.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f4dba50cfa56f910241eb7f883c20f1e7b1d8f7d91c750cd0b318bad443f4d5"},
|
||||||
|
{file = "pillow-11.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:5ddbfd761ee00c12ee1be86c9c0683ecf5bb14c9772ddbd782085779a63dd55b"},
|
||||||
|
{file = "pillow-11.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:45c566eb10b8967d71bf1ab8e4a525e5a93519e29ea071459ce517f6b903d7fa"},
|
||||||
|
{file = "pillow-11.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b4fd7bd29610a83a8c9b564d457cf5bd92b4e11e79a4ee4716a63c959699b306"},
|
||||||
|
{file = "pillow-11.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:cb929ca942d0ec4fac404cbf520ee6cac37bf35be479b970c4ffadf2b6a1cad9"},
|
||||||
|
{file = "pillow-11.0.0-cp311-cp311-win32.whl", hash = "sha256:006bcdd307cc47ba43e924099a038cbf9591062e6c50e570819743f5607404f5"},
|
||||||
|
{file = "pillow-11.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:52a2d8323a465f84faaba5236567d212c3668f2ab53e1c74c15583cf507a0291"},
|
||||||
|
{file = "pillow-11.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:16095692a253047fe3ec028e951fa4221a1f3ed3d80c397e83541a3037ff67c9"},
|
||||||
|
{file = "pillow-11.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2c0a187a92a1cb5ef2c8ed5412dd8d4334272617f532d4ad4de31e0495bd923"},
|
||||||
|
{file = "pillow-11.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:084a07ef0821cfe4858fe86652fffac8e187b6ae677e9906e192aafcc1b69903"},
|
||||||
|
{file = "pillow-11.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8069c5179902dcdce0be9bfc8235347fdbac249d23bd90514b7a47a72d9fecf4"},
|
||||||
|
{file = "pillow-11.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f02541ef64077f22bf4924f225c0fd1248c168f86e4b7abdedd87d6ebaceab0f"},
|
||||||
|
{file = "pillow-11.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:fcb4621042ac4b7865c179bb972ed0da0218a076dc1820ffc48b1d74c1e37fe9"},
|
||||||
|
{file = "pillow-11.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:00177a63030d612148e659b55ba99527803288cea7c75fb05766ab7981a8c1b7"},
|
||||||
|
{file = "pillow-11.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8853a3bf12afddfdf15f57c4b02d7ded92c7a75a5d7331d19f4f9572a89c17e6"},
|
||||||
|
{file = "pillow-11.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3107c66e43bda25359d5ef446f59c497de2b5ed4c7fdba0894f8d6cf3822dafc"},
|
||||||
|
{file = "pillow-11.0.0-cp312-cp312-win32.whl", hash = "sha256:86510e3f5eca0ab87429dd77fafc04693195eec7fd6a137c389c3eeb4cfb77c6"},
|
||||||
|
{file = "pillow-11.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:8ec4a89295cd6cd4d1058a5e6aec6bf51e0eaaf9714774e1bfac7cfc9051db47"},
|
||||||
|
{file = "pillow-11.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:27a7860107500d813fcd203b4ea19b04babe79448268403172782754870dac25"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcd1fb5bb7b07f64c15618c89efcc2cfa3e95f0e3bcdbaf4642509de1942a699"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0e038b0745997c7dcaae350d35859c9715c71e92ffb7e0f4a8e8a16732150f38"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ae08bd8ffc41aebf578c2af2f9d8749d91f448b3bfd41d7d9ff573d74f2a6b2"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d69bfd8ec3219ae71bcde1f942b728903cad25fafe3100ba2258b973bd2bc1b2"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:61b887f9ddba63ddf62fd02a3ba7add935d053b6dd7d58998c630e6dbade8527"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:c6a660307ca9d4867caa8d9ca2c2658ab685de83792d1876274991adec7b93fa"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:73e3a0200cdda995c7e43dd47436c1548f87a30bb27fb871f352a22ab8dcf45f"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fba162b8872d30fea8c52b258a542c5dfd7b235fb5cb352240c8d63b414013eb"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313-win32.whl", hash = "sha256:f1b82c27e89fffc6da125d5eb0ca6e68017faf5efc078128cfaa42cf5cb38798"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ba470552b48e5835f1d23ecb936bb7f71d206f9dfeee64245f30c3270b994de"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:846e193e103b41e984ac921b335df59195356ce3f71dcfd155aa79c603873b84"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4ad70c4214f67d7466bea6a08061eba35c01b1b89eaa098040a35272a8efb22b"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6ec0d5af64f2e3d64a165f490d96368bb5dea8b8f9ad04487f9ab60dc4bb6003"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c809a70e43c7977c4a42aefd62f0131823ebf7dd73556fa5d5950f5b354087e2"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:4b60c9520f7207aaf2e1d94de026682fc227806c6e1f55bba7606d1c94dd623a"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1e2688958a840c822279fda0086fec1fdab2f95bf2b717b66871c4ad9859d7e8"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313t-win32.whl", hash = "sha256:607bbe123c74e272e381a8d1957083a9463401f7bd01287f50521ecb05a313f8"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5c39ed17edea3bc69c743a8dd3e9853b7509625c2462532e62baa0732163a904"},
|
||||||
|
{file = "pillow-11.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:75acbbeb05b86bc53cbe7b7e6fe00fbcf82ad7c684b3ad82e3d711da9ba287d3"},
|
||||||
|
{file = "pillow-11.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2e46773dc9f35a1dd28bd6981332fd7f27bec001a918a72a79b4133cf5291dba"},
|
||||||
|
{file = "pillow-11.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2679d2258b7f1192b378e2893a8a0a0ca472234d4c2c0e6bdd3380e8dfa21b6a"},
|
||||||
|
{file = "pillow-11.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda2616eb2313cbb3eebbe51f19362eb434b18e3bb599466a1ffa76a033fb916"},
|
||||||
|
{file = "pillow-11.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ec184af98a121fb2da42642dea8a29ec80fc3efbaefb86d8fdd2606619045d"},
|
||||||
|
{file = "pillow-11.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:8594f42df584e5b4bb9281799698403f7af489fba84c34d53d1c4bfb71b7c4e7"},
|
||||||
|
{file = "pillow-11.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:c12b5ae868897c7338519c03049a806af85b9b8c237b7d675b8c5e089e4a618e"},
|
||||||
|
{file = "pillow-11.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:70fbbdacd1d271b77b7721fe3cdd2d537bbbd75d29e6300c672ec6bb38d9672f"},
|
||||||
|
{file = "pillow-11.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5178952973e588b3f1360868847334e9e3bf49d19e169bbbdfaf8398002419ae"},
|
||||||
|
{file = "pillow-11.0.0-cp39-cp39-win32.whl", hash = "sha256:8c676b587da5673d3c75bd67dd2a8cdfeb282ca38a30f37950511766b26858c4"},
|
||||||
|
{file = "pillow-11.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:94f3e1780abb45062287b4614a5bc0874519c86a777d4a7ad34978e86428b8dd"},
|
||||||
|
{file = "pillow-11.0.0-cp39-cp39-win_arm64.whl", hash = "sha256:290f2cc809f9da7d6d622550bbf4c1e57518212da51b6a30fe8e0a270a5b78bd"},
|
||||||
|
{file = "pillow-11.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1187739620f2b365de756ce086fdb3604573337cc28a0d3ac4a01ab6b2d2a6d2"},
|
||||||
|
{file = "pillow-11.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fbbcb7b57dc9c794843e3d1258c0fbf0f48656d46ffe9e09b63bbd6e8cd5d0a2"},
|
||||||
|
{file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d203af30149ae339ad1b4f710d9844ed8796e97fda23ffbc4cc472968a47d0b"},
|
||||||
|
{file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a0d3b115009ebb8ac3d2ebec5c2982cc693da935f4ab7bb5c8ebe2f47d36f2"},
|
||||||
|
{file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:73853108f56df97baf2bb8b522f3578221e56f646ba345a372c78326710d3830"},
|
||||||
|
{file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e58876c91f97b0952eb766123bfef372792ab3f4e3e1f1a2267834c2ab131734"},
|
||||||
|
{file = "pillow-11.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:224aaa38177597bb179f3ec87eeefcce8e4f85e608025e9cfac60de237ba6316"},
|
||||||
|
{file = "pillow-11.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5bd2d3bdb846d757055910f0a59792d33b555800813c3b39ada1829c372ccb06"},
|
||||||
|
{file = "pillow-11.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:375b8dd15a1f5d2feafff536d47e22f69625c1aa92f12b339ec0b2ca40263273"},
|
||||||
|
{file = "pillow-11.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:daffdf51ee5db69a82dd127eabecce20729e21f7a3680cf7cbb23f0829189790"},
|
||||||
|
{file = "pillow-11.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7326a1787e3c7b0429659e0a944725e1b03eeaa10edd945a86dead1913383944"},
|
||||||
|
{file = "pillow-11.0.0.tar.gz", hash = "sha256:72bacbaf24ac003fea9bff9837d1eedb6088758d41e100c1552930151f677739"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["furo", "olefile", "sphinx (>=8.1)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"]
|
||||||
|
fpx = ["olefile"]
|
||||||
|
mic = ["olefile"]
|
||||||
|
tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
|
||||||
|
typing = ["typing-extensions"]
|
||||||
|
xmp = ["defusedxml"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pluggy"
|
name = "pluggy"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
@ -425,6 +723,31 @@ tomli = {version = ">=1", markers = "python_version < \"3.11\""}
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python-dateutil"
|
||||||
|
version = "2.9.0.post0"
|
||||||
|
description = "Extensions to the standard Python datetime module"
|
||||||
|
optional = false
|
||||||
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
||||||
|
files = [
|
||||||
|
{file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"},
|
||||||
|
{file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
six = ">=1.5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytz"
|
||||||
|
version = "2024.2"
|
||||||
|
description = "World timezone definitions, modern and historical"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"},
|
||||||
|
{file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyyaml"
|
name = "pyyaml"
|
||||||
version = "6.0.2"
|
version = "6.0.2"
|
||||||
|
@ -762,6 +1085,17 @@ tensorflow = ["safetensors[numpy]", "tensorflow (>=2.11.0)"]
|
||||||
testing = ["h5py (>=3.7.0)", "huggingface-hub (>=0.12.1)", "hypothesis (>=6.70.2)", "pytest (>=7.2.0)", "pytest-benchmark (>=4.0.0)", "safetensors[numpy]", "setuptools-rust (>=1.5.2)"]
|
testing = ["h5py (>=3.7.0)", "huggingface-hub (>=0.12.1)", "hypothesis (>=6.70.2)", "pytest (>=7.2.0)", "pytest-benchmark (>=4.0.0)", "safetensors[numpy]", "setuptools-rust (>=1.5.2)"]
|
||||||
torch = ["safetensors[numpy]", "torch (>=1.10)"]
|
torch = ["safetensors[numpy]", "torch (>=1.10)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "six"
|
||||||
|
version = "1.17.0"
|
||||||
|
description = "Python 2 and 3 compatibility utilities"
|
||||||
|
optional = false
|
||||||
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
||||||
|
files = [
|
||||||
|
{file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"},
|
||||||
|
{file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokenizers"
|
name = "tokenizers"
|
||||||
version = "0.21.0"
|
version = "0.21.0"
|
||||||
|
@ -936,6 +1270,17 @@ files = [
|
||||||
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tzdata"
|
||||||
|
version = "2024.2"
|
||||||
|
description = "Provider of IANA time zone data"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2"
|
||||||
|
files = [
|
||||||
|
{file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"},
|
||||||
|
{file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "urllib3"
|
name = "urllib3"
|
||||||
version = "2.2.3"
|
version = "2.2.3"
|
||||||
|
@ -956,4 +1301,4 @@ zstd = ["zstandard (>=0.18.0)"]
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = ">=3.10,<3.13"
|
python-versions = ">=3.10,<3.13"
|
||||||
content-hash = "985797a96ac1b58e4892479d96bbd1c696b452d760fa421a28b91ea8b3dbf977"
|
content-hash = "6c3841968936d66bf70e11c6c8e0a16fec6c2f4d88d79cd8ac5a412225e7cf56"
|
||||||
|
|
|
@ -63,6 +63,10 @@ transformers = ">=4.0.0"
|
||||||
pytest = {version = ">=8.1.0", optional = true}
|
pytest = {version = ">=8.1.0", optional = true}
|
||||||
requests = "^2.32.3"
|
requests = "^2.32.3"
|
||||||
rich = "^13.9.4"
|
rich = "^13.9.4"
|
||||||
|
pandas = "^2.2.3"
|
||||||
|
jinja2 = "^3.1.4"
|
||||||
|
pillow = "^11.0.0"
|
||||||
|
llama-cpp-python = "^0.3.4"
|
||||||
|
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
|
|
Loading…
Reference in New Issue