mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-07 17:33:33 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d278f2d2b2 | ||
|
|
df4596a699 | ||
|
|
dd0f47ec81 | ||
|
|
e53017a2fe | ||
|
|
fe034ba8f4 | ||
|
|
063e5780d6 | ||
|
|
904e21ca87 | ||
|
|
526665ea11 | ||
|
|
c2e97d2432 | ||
|
|
60be6a1f99 | ||
|
|
0ba7d2e834 | ||
|
|
184b241395 |
No files matched your search
+1
-1
@@ -1,6 +1,6 @@
|
||||
FROM python:3.11-slim
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN pip install flask praisonai==2.0.76 gunicorn markdown
|
||||
RUN pip install flask praisonai==2.0.80 gunicorn markdown
|
||||
EXPOSE 8080
|
||||
CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]
|
||||
@@ -110,7 +110,7 @@ Loads environment variables from .env file or system and sets them.</p>
|
||||
file.write("FROM python:3.11-slim\n")
|
||||
file.write("WORKDIR /app\n")
|
||||
file.write("COPY . .\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.76 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.80 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ class Praisonai < Formula
|
||||
|
||||
desc "AI tools for various AI applications"
|
||||
homepage "https://github.com/MervinPraison/PraisonAI"
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/2.0.76.tar.gz"
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/2.0.80.tar.gz"
|
||||
sha256 "1828fb9227d10f991522c3f24f061943a254b667196b40b1a3e4a54a8d30ce32" # Replace with actual SHA256 checksum
|
||||
license "MIT"
|
||||
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ class CloudDeployer:
|
||||
file.write("FROM python:3.11-slim\n")
|
||||
file.write("WORKDIR /app\n")
|
||||
file.write("COPY . .\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.76 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.80 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
@@ -240,6 +240,32 @@ class TrainVisionModel:
|
||||
quantization_method="q4_k_m"
|
||||
)
|
||||
|
||||
def prepare_modelfile_content(self):
|
||||
output_model = self.config["hf_model_name"]
|
||||
|
||||
template = '''{{- range $index, $_ := .Messages }}<|start_header_id|>{{ .Role }}<|end_header_id|>
|
||||
|
||||
{{ .Content }}
|
||||
{{- if gt (len (slice $.Messages $index)) 1 }}<|eot_id|>
|
||||
{{- else if ne .Role "assistant" }}<|eot_id|><|start_header_id|>assistant<|end_header_id|>
|
||||
|
||||
{{ end }}
|
||||
{{- end }}'''
|
||||
|
||||
return f"""FROM {output_model}
|
||||
TEMPLATE {template}
|
||||
PARAMETER temperature 0.6
|
||||
PARAMETER top_p 0.9
|
||||
"""
|
||||
|
||||
def create_and_push_ollama_model(self):
|
||||
modelfile_content = self.prepare_modelfile_content()
|
||||
with open("Modelfile", "w") as file:
|
||||
file.write(modelfile_content)
|
||||
subprocess.run(["ollama", "serve"])
|
||||
subprocess.run(["ollama", "create", f"{self.config['ollama_model']}:{self.config['model_parameters']}", "-f", "Modelfile"])
|
||||
subprocess.run(["ollama", "push", f"{self.config['ollama_model']}:{self.config['model_parameters']}"])
|
||||
|
||||
def run(self):
|
||||
self.print_system_info()
|
||||
self.check_gpu()
|
||||
@@ -247,6 +273,12 @@ class TrainVisionModel:
|
||||
if self.config.get("train", "true").lower() == "true":
|
||||
self.prepare_model()
|
||||
self.train_model()
|
||||
if self.config.get("huggingface_save", "true").lower() == "true":
|
||||
self.save_model_merged()
|
||||
if self.config.get("huggingface_save_gguf", "true").lower() == "true":
|
||||
self.push_model_gguf()
|
||||
if self.config.get("ollama_save", "true").lower() == "true":
|
||||
self.create_and_push_ollama_model()
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
This script handles uploading trained vision models to Hugging Face and Ollama.
|
||||
It reads configuration from config.yaml and provides options to upload in different formats.
|
||||
"""
|
||||
|
||||
import os
|
||||
import yaml
|
||||
import torch
|
||||
import shutil
|
||||
import subprocess
|
||||
from unsloth import FastVisionModel
|
||||
|
||||
class UploadVisionModel:
|
||||
def __init__(self, config_path="config.yaml"):
|
||||
self.load_config(config_path)
|
||||
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||
self.model = None
|
||||
self.hf_tokenizer = None
|
||||
|
||||
def load_config(self, path):
|
||||
"""Load configuration from yaml file."""
|
||||
with open(path, "r") as file:
|
||||
self.config = yaml.safe_load(file)
|
||||
print("DEBUG: Loaded config:", self.config)
|
||||
|
||||
def prepare_model(self):
|
||||
"""Load the trained model for uploading."""
|
||||
print("DEBUG: Loading trained model and tokenizer...")
|
||||
self.model, original_tokenizer = FastVisionModel.from_pretrained(
|
||||
model_name=self.config.get("output_dir", "lora_model"),
|
||||
load_in_4bit=self.config.get("load_in_4bit", True)
|
||||
)
|
||||
self.hf_tokenizer = original_tokenizer
|
||||
print("DEBUG: Model and tokenizer loaded successfully.")
|
||||
|
||||
def save_model_merged(self):
|
||||
"""Save merged model to Hugging Face Hub."""
|
||||
print(f"DEBUG: Saving merged model to Hugging Face Hub: {self.config['hf_model_name']}")
|
||||
if os.path.exists(self.config["hf_model_name"]):
|
||||
shutil.rmtree(self.config["hf_model_name"])
|
||||
self.model.push_to_hub_merged(
|
||||
self.config["hf_model_name"],
|
||||
self.hf_tokenizer,
|
||||
save_method="merged_16bit",
|
||||
token=os.getenv("HF_TOKEN")
|
||||
)
|
||||
print("DEBUG: Model saved to Hugging Face Hub successfully.")
|
||||
|
||||
def push_model_gguf(self):
|
||||
"""Push model in GGUF format to Hugging Face Hub."""
|
||||
print(f"DEBUG: Pushing GGUF model to Hugging Face Hub: {self.config['hf_model_name']}")
|
||||
self.model.push_to_hub_gguf(
|
||||
self.config["hf_model_name"],
|
||||
self.hf_tokenizer,
|
||||
quantization_method=self.config.get("quantization_method", "q4_k_m"),
|
||||
token=os.getenv("HF_TOKEN")
|
||||
)
|
||||
print("DEBUG: GGUF model pushed to Hugging Face Hub successfully.")
|
||||
|
||||
def prepare_modelfile_content(self):
|
||||
"""Prepare Ollama modelfile content using Llama 3.2 vision template."""
|
||||
output_model = self.config["hf_model_name"]
|
||||
|
||||
# Using Llama 3.2 vision template format
|
||||
template = """{{- range $index, $_ := .Messages }}<|start_header_id|>{{ .Role }}<|end_header_id|>
|
||||
|
||||
{{ .Content }}
|
||||
{{- if gt (len (slice $.Messages $index)) 1 }}<|eot_id|>
|
||||
{{- else if ne .Role "assistant" }}<|eot_id|><|start_header_id|>assistant<|end_header_id|>
|
||||
|
||||
{{ end }}
|
||||
{{- end }}"""
|
||||
|
||||
# Assemble the modelfile content with Llama 3.2 vision parameters
|
||||
modelfile = f"FROM {output_model}\n"
|
||||
modelfile += "TEMPLATE \"""" + template + "\"""\n"
|
||||
modelfile += "PARAMETER temperature 0.6\n"
|
||||
modelfile += "PARAMETER top_p 0.9\n"
|
||||
return modelfile
|
||||
|
||||
def create_and_push_ollama_model(self):
|
||||
"""Create and push model to Ollama."""
|
||||
print(f"DEBUG: Creating Ollama model: {self.config['ollama_model']}:{self.config['model_parameters']}")
|
||||
modelfile_content = self.prepare_modelfile_content()
|
||||
with open("Modelfile", "w") as file:
|
||||
file.write(modelfile_content)
|
||||
|
||||
print("DEBUG: Starting Ollama server...")
|
||||
subprocess.run(["ollama", "serve"])
|
||||
|
||||
print("DEBUG: Creating Ollama model...")
|
||||
subprocess.run([
|
||||
"ollama", "create",
|
||||
f"{self.config['ollama_model']}:{self.config['model_parameters']}",
|
||||
"-f", "Modelfile"
|
||||
])
|
||||
|
||||
print("DEBUG: Pushing model to Ollama...")
|
||||
subprocess.run([
|
||||
"ollama", "push",
|
||||
f"{self.config['ollama_model']}:{self.config['model_parameters']}"
|
||||
])
|
||||
print("DEBUG: Model pushed to Ollama successfully.")
|
||||
|
||||
def upload(self, target="all"):
|
||||
"""
|
||||
Upload the model to specified targets.
|
||||
Args:
|
||||
target (str): One of 'all', 'huggingface', 'huggingface_gguf', or 'ollama'
|
||||
"""
|
||||
self.prepare_model()
|
||||
|
||||
if target in ["all", "huggingface"]:
|
||||
self.save_model_merged()
|
||||
|
||||
if target in ["all", "huggingface_gguf"]:
|
||||
self.push_model_gguf()
|
||||
|
||||
if target in ["all", "ollama"]:
|
||||
self.create_and_push_ollama_model()
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description="Upload Vision Model to Various Platforms")
|
||||
parser.add_argument("--config", default="config.yaml", help="Path to configuration file")
|
||||
parser.add_argument(
|
||||
"--target",
|
||||
choices=["all", "huggingface", "huggingface_gguf", "ollama"],
|
||||
default="all",
|
||||
help="Target platform to upload to"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
uploader = UploadVisionModel(config_path=args.config)
|
||||
uploader.upload(target=args.target)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "PraisonAI"
|
||||
version = "2.0.76"
|
||||
version = "2.0.80"
|
||||
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration."
|
||||
readme = "README.md"
|
||||
license = ""
|
||||
@@ -12,7 +12,7 @@ dependencies = [
|
||||
"rich>=13.7",
|
||||
"markdown>=3.5",
|
||||
"pyparsing>=3.0.0",
|
||||
"praisonaiagents>=0.0.61",
|
||||
"praisonaiagents>=0.0.65",
|
||||
"python-dotenv>=0.19.0",
|
||||
"instructor>=1.3.3",
|
||||
"PyYAML>=6.0",
|
||||
@@ -84,7 +84,7 @@ autogen = ["pyautogen>=0.2.19", "praisonai-tools>=0.0.7", "crewai"]
|
||||
|
||||
[tool.poetry]
|
||||
name = "PraisonAI"
|
||||
version = "2.0.76"
|
||||
version = "2.0.80"
|
||||
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human–agent collaboration."
|
||||
authors = ["Mervin Praison"]
|
||||
license = ""
|
||||
@@ -102,7 +102,7 @@ python = ">=3.10,<3.13"
|
||||
rich = ">=13.7"
|
||||
markdown = ">=3.5"
|
||||
pyparsing = ">=3.0.0"
|
||||
praisonaiagents = ">=0.0.61"
|
||||
praisonaiagents = ">=0.0.65"
|
||||
python-dotenv = ">=0.19.0"
|
||||
instructor = ">=1.3.3"
|
||||
PyYAML = ">=6.0"
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a Wikipedia Agent",
|
||||
llm="anthropic/claude-3-7-sonnet-20250219"
|
||||
)
|
||||
result = agent.start("Why Sky is Blue?")
|
||||
print(result)
|
||||
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.tools import internet_search
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a Wikipedia Agent",
|
||||
tools=[internet_search],
|
||||
llm="anthropic/claude-3-7-sonnet-20250219"
|
||||
)
|
||||
agent.start("What is Praison AI?")
|
||||
|
||||
from praisonaiagents import Agent, PraisonAIAgents
|
||||
from praisonaiagents.tools import internet_search
|
||||
|
||||
|
||||
research_agent = Agent(
|
||||
instructions="Search Information about Claude Sonnet 3.7",
|
||||
tools=[internet_search],
|
||||
llm="anthropic/claude-3-7-sonnet-20250219"
|
||||
)
|
||||
|
||||
editor_agent = Agent(
|
||||
instructions="Write a Blog Post with the provided information about Claude Sonnet 3.7",
|
||||
llm="anthropic/claude-3-7-sonnet-20250219"
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(agents=[research_agent, editor_agent])
|
||||
result = agents.start()
|
||||
print(result)
|
||||
@@ -1,10 +1,10 @@
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.tools import internet_search
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm="gemini/gemini-1.5-flash-8b",
|
||||
self_reflect=True,
|
||||
verbose=True
|
||||
tools=[internet_search],
|
||||
llm="gemini/gemini-1.5-flash-8b"
|
||||
)
|
||||
|
||||
agent.start("Why sky is Blue?")
|
||||
agent.start("What is Praison AI?")
|
||||
@@ -0,0 +1,18 @@
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.tools import wiki_search, wiki_summary, wiki_page, wiki_random, wiki_language
|
||||
|
||||
agent1 = Agent(
|
||||
instructions="You are a Wikipedia Agent",
|
||||
tools=[wiki_search, wiki_summary, wiki_page, wiki_random, wiki_language],
|
||||
llm="openai/gpt-4o-mini",
|
||||
verbose=10
|
||||
)
|
||||
agent1.start("history of AI in 1 line")
|
||||
|
||||
agent2 = Agent(
|
||||
instructions="You are a Wikipedia Agent",
|
||||
tools=[wiki_search, wiki_summary, wiki_page, wiki_random, wiki_language],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=10
|
||||
)
|
||||
agent2.start("history of AI in 1 line")
|
||||
@@ -714,6 +714,22 @@ Your Goal: {self.goal}
|
||||
return None
|
||||
|
||||
def chat(self, prompt, temperature=0.2, tools=None, output_json=None, output_pydantic=None, reasoning_steps=False):
|
||||
# Log all parameter values when in debug mode
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
param_info = {
|
||||
"prompt": str(prompt)[:100] + "..." if isinstance(prompt, str) and len(str(prompt)) > 100 else str(prompt),
|
||||
"temperature": temperature,
|
||||
"tools": [t.__name__ if hasattr(t, "__name__") else str(t) for t in tools] if tools else None,
|
||||
"output_json": str(output_json.__class__.__name__) if output_json else None,
|
||||
"output_pydantic": str(output_pydantic.__class__.__name__) if output_pydantic else None,
|
||||
"reasoning_steps": reasoning_steps,
|
||||
"agent_name": self.name,
|
||||
"agent_role": self.role,
|
||||
"agent_goal": self.goal
|
||||
}
|
||||
logging.debug(f"Agent.chat parameters: {json.dumps(param_info, indent=2, default=str)}")
|
||||
|
||||
start_time = time.time()
|
||||
reasoning_steps = reasoning_steps or self.reasoning_steps
|
||||
# Search for existing knowledge if any knowledge is provided
|
||||
if self.knowledge:
|
||||
@@ -738,7 +754,7 @@ Your Goal: {self.goal}
|
||||
system_prompt=f"{self.backstory}\n\nYour Role: {self.role}\n\nYour Goal: {self.goal}" if self.use_system_prompt else None,
|
||||
chat_history=self.chat_history,
|
||||
temperature=temperature,
|
||||
tools=tools,
|
||||
tools=self.tools if tools is None else tools,
|
||||
output_json=output_json,
|
||||
output_pydantic=output_pydantic,
|
||||
verbose=self.verbose,
|
||||
@@ -749,7 +765,7 @@ Your Goal: {self.goal}
|
||||
console=self.console,
|
||||
agent_name=self.name,
|
||||
agent_role=self.role,
|
||||
agent_tools=[t.__name__ if hasattr(t, '__name__') else str(t) for t in self.tools],
|
||||
agent_tools=[t.__name__ if hasattr(t, '__name__') else str(t) for t in (tools if tools is not None else self.tools)],
|
||||
execute_tool_fn=self.execute_tool, # Pass tool execution function
|
||||
reasoning_steps=reasoning_steps
|
||||
)
|
||||
@@ -757,6 +773,11 @@ Your Goal: {self.goal}
|
||||
self.chat_history.append({"role": "user", "content": prompt})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
|
||||
# Log completion time if in debug mode
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
total_time = time.time() - start_time
|
||||
logging.debug(f"Agent.chat completed in {total_time:.2f} seconds")
|
||||
|
||||
return response_text
|
||||
except Exception as e:
|
||||
display_error(f"Error in LLM chat: {e}")
|
||||
@@ -944,6 +965,13 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
display_error(f"Error in chat: {e}", console=self.console)
|
||||
return None
|
||||
|
||||
# Log completion time if in debug mode
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
total_time = time.time() - start_time
|
||||
logging.debug(f"Agent.chat completed in {total_time:.2f} seconds")
|
||||
|
||||
return response_text
|
||||
|
||||
def clean_json_output(self, output: str) -> str:
|
||||
"""Clean and extract JSON from response text."""
|
||||
cleaned = output.strip()
|
||||
@@ -958,6 +986,22 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
|
||||
async def achat(self, prompt: str, temperature=0.2, tools=None, output_json=None, output_pydantic=None, reasoning_steps=False):
|
||||
"""Async version of chat method. TODO: Requires Syncing with chat method."""
|
||||
# Log all parameter values when in debug mode
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
param_info = {
|
||||
"prompt": str(prompt)[:100] + "..." if isinstance(prompt, str) and len(str(prompt)) > 100 else str(prompt),
|
||||
"temperature": temperature,
|
||||
"tools": [t.__name__ if hasattr(t, "__name__") else str(t) for t in tools] if tools else None,
|
||||
"output_json": str(output_json.__class__.__name__) if output_json else None,
|
||||
"output_pydantic": str(output_pydantic.__class__.__name__) if output_pydantic else None,
|
||||
"reasoning_steps": reasoning_steps,
|
||||
"agent_name": self.name,
|
||||
"agent_role": self.role,
|
||||
"agent_goal": self.goal
|
||||
}
|
||||
logging.debug(f"Agent.achat parameters: {json.dumps(param_info, indent=2, default=str)}")
|
||||
|
||||
start_time = time.time()
|
||||
reasoning_steps = reasoning_steps or self.reasoning_steps
|
||||
try:
|
||||
# Search for existing knowledge if any knowledge is provided
|
||||
@@ -996,9 +1040,15 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
self.chat_history.append({"role": "user", "content": prompt})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
total_time = time.time() - start_time
|
||||
logging.debug(f"Agent.achat completed in {total_time:.2f} seconds")
|
||||
return response_text
|
||||
except Exception as e:
|
||||
display_error(f"Error in LLM chat: {e}")
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
total_time = time.time() - start_time
|
||||
logging.debug(f"Agent.achat failed in {total_time:.2f} seconds: {str(e)}")
|
||||
return None
|
||||
|
||||
# For OpenAI client
|
||||
@@ -1081,7 +1131,11 @@ Your Goal: {self.goal}
|
||||
temperature=temperature,
|
||||
tools=formatted_tools
|
||||
)
|
||||
return await self._achat_completion(response, tools)
|
||||
result = await self._achat_completion(response, tools)
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
total_time = time.time() - start_time
|
||||
logging.debug(f"Agent.achat completed in {total_time:.2f} seconds")
|
||||
return result
|
||||
elif output_json or output_pydantic:
|
||||
response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
@@ -1090,6 +1144,9 @@ Your Goal: {self.goal}
|
||||
response_format={"type": "json_object"}
|
||||
)
|
||||
# Return the raw response
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
total_time = time.time() - start_time
|
||||
logging.debug(f"Agent.achat completed in {total_time:.2f} seconds")
|
||||
return response.choices[0].message.content
|
||||
else:
|
||||
response = await async_client.chat.completions.create(
|
||||
@@ -1097,12 +1154,21 @@ Your Goal: {self.goal}
|
||||
messages=messages,
|
||||
temperature=temperature
|
||||
)
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
total_time = time.time() - start_time
|
||||
logging.debug(f"Agent.achat completed in {total_time:.2f} seconds")
|
||||
return response.choices[0].message.content
|
||||
except Exception as e:
|
||||
display_error(f"Error in chat completion: {e}")
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
total_time = time.time() - start_time
|
||||
logging.debug(f"Agent.achat failed in {total_time:.2f} seconds: {str(e)}")
|
||||
return None
|
||||
except Exception as e:
|
||||
display_error(f"Error in achat: {e}")
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
total_time = time.time() - start_time
|
||||
logging.debug(f"Agent.achat failed in {total_time:.2f} seconds: {str(e)}")
|
||||
return None
|
||||
|
||||
async def _achat_completion(self, response, tools, reasoning_steps=False):
|
||||
|
||||
@@ -477,8 +477,14 @@ Context:
|
||||
else:
|
||||
self.run_task(task_id)
|
||||
|
||||
async def astart(self, content=None, **kwargs):
|
||||
"""Async version of start method"""
|
||||
async def astart(self, content=None, return_dict=False, **kwargs):
|
||||
"""Async version of start method
|
||||
|
||||
Args:
|
||||
content: Optional content to add to all tasks' context
|
||||
return_dict: If True, returns the full results dictionary instead of only the final response
|
||||
**kwargs: Additional arguments
|
||||
"""
|
||||
if content:
|
||||
# Add content to context of all tasks
|
||||
for task in self.tasks.values():
|
||||
@@ -488,10 +494,25 @@ Context:
|
||||
task.context.append(content)
|
||||
|
||||
await self.arun_all_tasks()
|
||||
return {
|
||||
|
||||
# Get results
|
||||
results = {
|
||||
"task_status": self.get_all_tasks_status(),
|
||||
"task_results": {task_id: self.get_task_result(task_id) for task_id in self.tasks}
|
||||
}
|
||||
|
||||
# By default, return only the final agent's response
|
||||
if not return_dict:
|
||||
# Get the last task (assuming sequential processing)
|
||||
task_ids = list(self.tasks.keys())
|
||||
if task_ids:
|
||||
last_task_id = task_ids[-1]
|
||||
last_result = self.get_task_result(last_task_id)
|
||||
if last_result:
|
||||
return last_result.raw
|
||||
|
||||
# Return full results dict if return_dict is True or if no final result was found
|
||||
return results
|
||||
|
||||
def save_output_to_file(self, task, task_output):
|
||||
if task.output_file:
|
||||
@@ -801,8 +822,14 @@ Context:
|
||||
return str(agent[0])
|
||||
return None
|
||||
|
||||
def start(self, content=None, **kwargs):
|
||||
"""Start agent execution with optional content and config"""
|
||||
def start(self, content=None, return_dict=False, **kwargs):
|
||||
"""Start agent execution with optional content and config
|
||||
|
||||
Args:
|
||||
content: Optional content to add to all tasks' context
|
||||
return_dict: If True, returns the full results dictionary instead of only the final response
|
||||
**kwargs: Additional arguments
|
||||
"""
|
||||
if content:
|
||||
# Add content to context of all tasks
|
||||
for task in self.tasks.values():
|
||||
@@ -815,10 +842,25 @@ Context:
|
||||
|
||||
# Run tasks as before
|
||||
self.run_all_tasks()
|
||||
return {
|
||||
|
||||
# Get results
|
||||
results = {
|
||||
"task_status": self.get_all_tasks_status(),
|
||||
"task_results": {task_id: self.get_task_result(task_id) for task_id in self.tasks}
|
||||
}
|
||||
|
||||
# By default, return only the final agent's response
|
||||
if not return_dict:
|
||||
# Get the last task (assuming sequential processing)
|
||||
task_ids = list(self.tasks.keys())
|
||||
if task_ids:
|
||||
last_task_id = task_ids[-1]
|
||||
last_result = self.get_task_result(last_task_id)
|
||||
if last_result:
|
||||
return last_result.raw
|
||||
|
||||
# Return full results dict if return_dict is True or if no final result was found
|
||||
return results
|
||||
|
||||
def set_state(self, key: str, value: Any) -> None:
|
||||
"""Set a state value"""
|
||||
|
||||
@@ -171,7 +171,39 @@ class LLM:
|
||||
|
||||
# Enable error dropping for cleaner output
|
||||
litellm.drop_params = True
|
||||
# Enable parameter modification for providers like Anthropic
|
||||
litellm.modify_params = True
|
||||
self._setup_event_tracking(events)
|
||||
|
||||
# Log all initialization parameters when in debug mode
|
||||
if not isinstance(verbose, bool) and verbose >= 10:
|
||||
debug_info = {
|
||||
"model": self.model,
|
||||
"timeout": self.timeout,
|
||||
"temperature": self.temperature,
|
||||
"top_p": self.top_p,
|
||||
"n": self.n,
|
||||
"max_tokens": self.max_tokens,
|
||||
"presence_penalty": self.presence_penalty,
|
||||
"frequency_penalty": self.frequency_penalty,
|
||||
"logit_bias": self.logit_bias,
|
||||
"response_format": self.response_format,
|
||||
"seed": self.seed,
|
||||
"logprobs": self.logprobs,
|
||||
"top_logprobs": self.top_logprobs,
|
||||
"api_version": self.api_version,
|
||||
"stop_phrases": self.stop_phrases,
|
||||
"api_key": "***" if self.api_key else None, # Mask API key for security
|
||||
"base_url": self.base_url,
|
||||
"verbose": self.verbose,
|
||||
"markdown": self.markdown,
|
||||
"self_reflect": self.self_reflect,
|
||||
"max_reflect": self.max_reflect,
|
||||
"min_reflect": self.min_reflect,
|
||||
"reasoning_steps": self.reasoning_steps,
|
||||
"extra_settings": {k: v for k, v in self.extra_settings.items() if k not in ["api_key"]}
|
||||
}
|
||||
logging.debug(f"LLM instance initialized with: {json.dumps(debug_info, indent=2, default=str)}")
|
||||
|
||||
def get_response(
|
||||
self,
|
||||
@@ -195,6 +227,56 @@ class LLM:
|
||||
**kwargs
|
||||
) -> str:
|
||||
"""Enhanced get_response with all OpenAI-like features"""
|
||||
logging.info(f"Getting response from {self.model}")
|
||||
# Log all self values when in debug mode
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
debug_info = {
|
||||
"model": self.model,
|
||||
"timeout": self.timeout,
|
||||
"temperature": self.temperature,
|
||||
"top_p": self.top_p,
|
||||
"n": self.n,
|
||||
"max_tokens": self.max_tokens,
|
||||
"presence_penalty": self.presence_penalty,
|
||||
"frequency_penalty": self.frequency_penalty,
|
||||
"logit_bias": self.logit_bias,
|
||||
"response_format": self.response_format,
|
||||
"seed": self.seed,
|
||||
"logprobs": self.logprobs,
|
||||
"top_logprobs": self.top_logprobs,
|
||||
"api_version": self.api_version,
|
||||
"stop_phrases": self.stop_phrases,
|
||||
"api_key": "***" if self.api_key else None, # Mask API key for security
|
||||
"base_url": self.base_url,
|
||||
"verbose": self.verbose,
|
||||
"markdown": self.markdown,
|
||||
"self_reflect": self.self_reflect,
|
||||
"max_reflect": self.max_reflect,
|
||||
"min_reflect": self.min_reflect,
|
||||
"reasoning_steps": self.reasoning_steps
|
||||
}
|
||||
logging.debug(f"LLM instance configuration: {json.dumps(debug_info, indent=2, default=str)}")
|
||||
|
||||
# Log the parameter values passed to get_response
|
||||
param_info = {
|
||||
"prompt": str(prompt)[:100] + "..." if isinstance(prompt, str) and len(str(prompt)) > 100 else str(prompt),
|
||||
"system_prompt": system_prompt[:100] + "..." if system_prompt and len(system_prompt) > 100 else system_prompt,
|
||||
"chat_history": f"[{len(chat_history)} messages]" if chat_history else None,
|
||||
"temperature": temperature,
|
||||
"tools": [t.__name__ if hasattr(t, "__name__") else str(t) for t in tools] if tools else None,
|
||||
"output_json": str(output_json.__class__.__name__) if output_json else None,
|
||||
"output_pydantic": str(output_pydantic.__class__.__name__) if output_pydantic else None,
|
||||
"verbose": verbose,
|
||||
"markdown": markdown,
|
||||
"self_reflect": self_reflect,
|
||||
"max_reflect": max_reflect,
|
||||
"min_reflect": min_reflect,
|
||||
"agent_name": agent_name,
|
||||
"agent_role": agent_role,
|
||||
"agent_tools": agent_tools,
|
||||
"kwargs": str(kwargs)
|
||||
}
|
||||
logging.debug(f"get_response parameters: {json.dumps(param_info, indent=2, default=str)}")
|
||||
try:
|
||||
import litellm
|
||||
# This below **kwargs** is passed to .completion() directly. so reasoning_steps has to be popped. OR find alternate best way of handling this.
|
||||
@@ -202,6 +284,23 @@ class LLM:
|
||||
# Disable litellm debug messages
|
||||
litellm.set_verbose = False
|
||||
|
||||
# Format tools if provided
|
||||
formatted_tools = None
|
||||
if tools:
|
||||
formatted_tools = []
|
||||
for tool in tools:
|
||||
if callable(tool):
|
||||
tool_def = self._generate_tool_definition(tool.__name__)
|
||||
elif isinstance(tool, str):
|
||||
tool_def = self._generate_tool_definition(tool)
|
||||
else:
|
||||
continue
|
||||
|
||||
if tool_def:
|
||||
formatted_tools.append(tool_def)
|
||||
if not formatted_tools:
|
||||
formatted_tools = None
|
||||
|
||||
# Build messages list
|
||||
messages = []
|
||||
if system_prompt:
|
||||
@@ -260,6 +359,7 @@ class LLM:
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=False, # force non-streaming
|
||||
tools=formatted_tools,
|
||||
**{k:v for k,v in kwargs.items() if k != 'reasoning_steps'}
|
||||
)
|
||||
reasoning_content = resp["choices"][0]["message"].get("provider_specific_fields", {}).get("reasoning_content")
|
||||
@@ -291,6 +391,7 @@ class LLM:
|
||||
for chunk in litellm.completion(
|
||||
model=self.model,
|
||||
messages=messages,
|
||||
tools=formatted_tools,
|
||||
temperature=temperature,
|
||||
stream=True,
|
||||
**kwargs
|
||||
@@ -305,6 +406,7 @@ class LLM:
|
||||
for chunk in litellm.completion(
|
||||
model=self.model,
|
||||
messages=messages,
|
||||
tools=formatted_tools,
|
||||
temperature=temperature,
|
||||
stream=True,
|
||||
**kwargs
|
||||
@@ -318,6 +420,7 @@ class LLM:
|
||||
final_response = litellm.completion(
|
||||
model=self.model,
|
||||
messages=messages,
|
||||
tools=formatted_tools,
|
||||
temperature=temperature,
|
||||
stream=False, # No streaming for tool call check
|
||||
**kwargs
|
||||
@@ -337,20 +440,29 @@ class LLM:
|
||||
function_name = tool_call["function"]["name"]
|
||||
arguments = json.loads(tool_call["function"]["arguments"])
|
||||
|
||||
if verbose:
|
||||
display_tool_call(f"Agent {agent_name} is calling function '{function_name}' with arguments: {arguments}", console=console)
|
||||
|
||||
logging.debug(f"[TOOL_EXEC_DEBUG] About to execute tool {function_name} with args: {arguments}")
|
||||
tool_result = execute_tool_fn(function_name, arguments)
|
||||
logging.debug(f"[TOOL_EXEC_DEBUG] Tool execution result: {tool_result}")
|
||||
|
||||
if tool_result:
|
||||
if verbose:
|
||||
display_tool_call(f"Function '{function_name}' returned: {tool_result}", console=console)
|
||||
if verbose:
|
||||
display_message = f"Agent {agent_name} called function '{function_name}' with arguments: {arguments}\n"
|
||||
if tool_result:
|
||||
display_message += f"Function returned: {tool_result}"
|
||||
logging.debug(f"[TOOL_EXEC_DEBUG] Display message with result: {display_message}")
|
||||
else:
|
||||
display_message += "Function returned no output"
|
||||
logging.debug("[TOOL_EXEC_DEBUG] Tool returned no output")
|
||||
|
||||
logging.debug(f"[TOOL_EXEC_DEBUG] About to display tool call with message: {display_message}")
|
||||
display_tool_call(display_message, console=console)
|
||||
|
||||
messages.append({
|
||||
"role": "tool",
|
||||
"tool_call_id": tool_call["id"],
|
||||
"content": json.dumps(tool_result)
|
||||
})
|
||||
else:
|
||||
logging.debug("[TOOL_EXEC_DEBUG] Verbose mode off, not displaying tool call")
|
||||
messages.append({
|
||||
"role": "tool",
|
||||
"tool_call_id": tool_call["id"],
|
||||
@@ -552,6 +664,11 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
except Exception as error:
|
||||
display_error(f"Error in get_response: {str(error)}")
|
||||
raise
|
||||
|
||||
# Log completion time if in debug mode
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
total_time = time.time() - start_time
|
||||
logging.debug(f"get_response completed in {total_time:.2f} seconds")
|
||||
|
||||
async def get_response_async(
|
||||
self,
|
||||
@@ -577,6 +694,56 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
"""Async version of get_response with identical functionality."""
|
||||
try:
|
||||
import litellm
|
||||
logging.info(f"Getting async response from {self.model}")
|
||||
# Log all self values when in debug mode
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
debug_info = {
|
||||
"model": self.model,
|
||||
"timeout": self.timeout,
|
||||
"temperature": self.temperature,
|
||||
"top_p": self.top_p,
|
||||
"n": self.n,
|
||||
"max_tokens": self.max_tokens,
|
||||
"presence_penalty": self.presence_penalty,
|
||||
"frequency_penalty": self.frequency_penalty,
|
||||
"logit_bias": self.logit_bias,
|
||||
"response_format": self.response_format,
|
||||
"seed": self.seed,
|
||||
"logprobs": self.logprobs,
|
||||
"top_logprobs": self.top_logprobs,
|
||||
"api_version": self.api_version,
|
||||
"stop_phrases": self.stop_phrases,
|
||||
"api_key": "***" if self.api_key else None, # Mask API key for security
|
||||
"base_url": self.base_url,
|
||||
"verbose": self.verbose,
|
||||
"markdown": self.markdown,
|
||||
"self_reflect": self.self_reflect,
|
||||
"max_reflect": self.max_reflect,
|
||||
"min_reflect": self.min_reflect,
|
||||
"reasoning_steps": self.reasoning_steps
|
||||
}
|
||||
logging.debug(f"LLM async instance configuration: {json.dumps(debug_info, indent=2, default=str)}")
|
||||
|
||||
# Log the parameter values passed to get_response_async
|
||||
param_info = {
|
||||
"prompt": str(prompt)[:100] + "..." if isinstance(prompt, str) and len(str(prompt)) > 100 else str(prompt),
|
||||
"system_prompt": system_prompt[:100] + "..." if system_prompt and len(system_prompt) > 100 else system_prompt,
|
||||
"chat_history": f"[{len(chat_history)} messages]" if chat_history else None,
|
||||
"temperature": temperature,
|
||||
"tools": [t.__name__ if hasattr(t, "__name__") else str(t) for t in tools] if tools else None,
|
||||
"output_json": str(output_json.__class__.__name__) if output_json else None,
|
||||
"output_pydantic": str(output_pydantic.__class__.__name__) if output_pydantic else None,
|
||||
"verbose": verbose,
|
||||
"markdown": markdown,
|
||||
"self_reflect": self_reflect,
|
||||
"max_reflect": max_reflect,
|
||||
"min_reflect": min_reflect,
|
||||
"agent_name": agent_name,
|
||||
"agent_role": agent_role,
|
||||
"agent_tools": agent_tools,
|
||||
"kwargs": str(kwargs)
|
||||
}
|
||||
logging.debug(f"get_response_async parameters: {json.dumps(param_info, indent=2, default=str)}")
|
||||
reasoning_steps = kwargs.pop('reasoning_steps', self.reasoning_steps)
|
||||
litellm.set_verbose = False
|
||||
|
||||
@@ -767,14 +934,15 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
function_name = tool_call.function.name
|
||||
arguments = json.loads(tool_call.function.arguments)
|
||||
|
||||
if verbose:
|
||||
display_tool_call(f"Agent {agent_name} is calling function '{function_name}' with arguments: {arguments}", console=console)
|
||||
|
||||
tool_result = await execute_tool_fn(function_name, arguments)
|
||||
|
||||
if tool_result:
|
||||
if verbose:
|
||||
display_tool_call(f"Function '{function_name}' returned: {tool_result}", console=console)
|
||||
if verbose:
|
||||
display_message = f"Agent {agent_name} called function '{function_name}' with arguments: {arguments}\n"
|
||||
if tool_result:
|
||||
display_message += f"Function returned: {tool_result}"
|
||||
else:
|
||||
display_message += "Function returned no output"
|
||||
display_tool_call(display_message, console=console)
|
||||
messages.append({
|
||||
"role": "tool",
|
||||
"tool_call_id": tool_call.id,
|
||||
@@ -983,6 +1151,11 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
raise LLMContextLengthExceededException(str(error))
|
||||
display_error(f"Error in get_response_async: {str(error)}")
|
||||
raise
|
||||
|
||||
# Log completion time if in debug mode
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
total_time = time.time() - start_time
|
||||
logging.debug(f"get_response_async completed in {total_time:.2f} seconds")
|
||||
|
||||
def can_use_tools(self) -> bool:
|
||||
"""Check if this model can use tool functions"""
|
||||
@@ -1065,6 +1238,24 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
|
||||
logger.debug("Using synchronous response function")
|
||||
|
||||
# Log all self values when in debug mode
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
debug_info = {
|
||||
"model": self.model,
|
||||
"timeout": self.timeout,
|
||||
"temperature": temperature,
|
||||
"top_p": self.top_p,
|
||||
"n": self.n,
|
||||
"max_tokens": self.max_tokens,
|
||||
"presence_penalty": self.presence_penalty,
|
||||
"frequency_penalty": self.frequency_penalty,
|
||||
"stream": stream,
|
||||
"verbose": verbose,
|
||||
"markdown": markdown,
|
||||
"kwargs": str(kwargs)
|
||||
}
|
||||
logger.debug(f"Response method configuration: {json.dumps(debug_info, indent=2, default=str)}")
|
||||
|
||||
# Build messages list
|
||||
messages = []
|
||||
if system_prompt:
|
||||
@@ -1150,6 +1341,24 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
|
||||
logger.debug("Using asynchronous response function")
|
||||
|
||||
# Log all self values when in debug mode
|
||||
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
||||
debug_info = {
|
||||
"model": self.model,
|
||||
"timeout": self.timeout,
|
||||
"temperature": temperature,
|
||||
"top_p": self.top_p,
|
||||
"n": self.n,
|
||||
"max_tokens": self.max_tokens,
|
||||
"presence_penalty": self.presence_penalty,
|
||||
"frequency_penalty": self.frequency_penalty,
|
||||
"stream": stream,
|
||||
"verbose": verbose,
|
||||
"markdown": markdown,
|
||||
"kwargs": str(kwargs)
|
||||
}
|
||||
logger.debug(f"Async response method configuration: {json.dumps(debug_info, indent=2, default=str)}")
|
||||
|
||||
# Build messages list
|
||||
messages = []
|
||||
if system_prompt:
|
||||
@@ -1210,4 +1419,117 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
|
||||
except Exception as error:
|
||||
display_error(f"Error in response_async: {str(error)}")
|
||||
raise
|
||||
raise
|
||||
|
||||
def _generate_tool_definition(self, function_name: str) -> Optional[Dict]:
|
||||
"""Generate a tool definition from a function name."""
|
||||
logging.debug(f"Attempting to generate tool definition for: {function_name}")
|
||||
|
||||
# First try to get the tool definition if it exists
|
||||
tool_def_name = f"{function_name}_definition"
|
||||
tool_def = globals().get(tool_def_name)
|
||||
logging.debug(f"Looking for {tool_def_name} in globals: {tool_def is not None}")
|
||||
|
||||
if not tool_def:
|
||||
import __main__
|
||||
tool_def = getattr(__main__, tool_def_name, None)
|
||||
logging.debug(f"Looking for {tool_def_name} in __main__: {tool_def is not None}")
|
||||
|
||||
if tool_def:
|
||||
logging.debug(f"Found tool definition: {tool_def}")
|
||||
return tool_def
|
||||
|
||||
# Try to find the function
|
||||
func = globals().get(function_name)
|
||||
logging.debug(f"Looking for {function_name} in globals: {func is not None}")
|
||||
|
||||
if not func:
|
||||
import __main__
|
||||
func = getattr(__main__, function_name, None)
|
||||
logging.debug(f"Looking for {function_name} in __main__: {func is not None}")
|
||||
|
||||
if not func or not callable(func):
|
||||
logging.debug(f"Function {function_name} not found or not callable")
|
||||
return None
|
||||
|
||||
import inspect
|
||||
# Handle Langchain and CrewAI tools
|
||||
if inspect.isclass(func) and hasattr(func, 'run') and not hasattr(func, '_run'):
|
||||
original_func = func
|
||||
func = func.run
|
||||
function_name = original_func.__name__
|
||||
elif inspect.isclass(func) and hasattr(func, '_run'):
|
||||
original_func = func
|
||||
func = func._run
|
||||
function_name = original_func.__name__
|
||||
|
||||
sig = inspect.signature(func)
|
||||
logging.debug(f"Function signature: {sig}")
|
||||
|
||||
# Skip self, *args, **kwargs
|
||||
parameters_list = []
|
||||
for name, param in sig.parameters.items():
|
||||
if name == "self":
|
||||
continue
|
||||
if param.kind in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD):
|
||||
continue
|
||||
parameters_list.append((name, param))
|
||||
|
||||
parameters = {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"required": []
|
||||
}
|
||||
|
||||
# Parse docstring for parameter descriptions
|
||||
docstring = inspect.getdoc(func)
|
||||
logging.debug(f"Function docstring: {docstring}")
|
||||
|
||||
param_descriptions = {}
|
||||
if docstring:
|
||||
import re
|
||||
param_section = re.split(r'\s*Args:\s*', docstring)
|
||||
logging.debug(f"Param section split: {param_section}")
|
||||
if len(param_section) > 1:
|
||||
param_lines = param_section[1].split('\n')
|
||||
for line in param_lines:
|
||||
line = line.strip()
|
||||
if line and ':' in line:
|
||||
param_name, param_desc = line.split(':', 1)
|
||||
param_descriptions[param_name.strip()] = param_desc.strip()
|
||||
|
||||
logging.debug(f"Parameter descriptions: {param_descriptions}")
|
||||
|
||||
for name, param in parameters_list:
|
||||
param_type = "string" # Default type
|
||||
if param.annotation != inspect.Parameter.empty:
|
||||
if param.annotation == int:
|
||||
param_type = "integer"
|
||||
elif param.annotation == float:
|
||||
param_type = "number"
|
||||
elif param.annotation == bool:
|
||||
param_type = "boolean"
|
||||
elif param.annotation == list:
|
||||
param_type = "array"
|
||||
elif param.annotation == dict:
|
||||
param_type = "object"
|
||||
|
||||
parameters["properties"][name] = {
|
||||
"type": param_type,
|
||||
"description": param_descriptions.get(name, "Parameter description not available")
|
||||
}
|
||||
|
||||
if param.default == inspect.Parameter.empty:
|
||||
parameters["required"].append(name)
|
||||
|
||||
logging.debug(f"Generated parameters: {parameters}")
|
||||
tool_def = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": function_name,
|
||||
"description": docstring.split('\n\n')[0] if docstring else "No description available",
|
||||
"parameters": parameters
|
||||
}
|
||||
}
|
||||
logging.debug(f"Generated tool definition: {tool_def}")
|
||||
return tool_def
|
||||
@@ -86,6 +86,7 @@ async def execute_callback(display_type: str, **kwargs):
|
||||
def _clean_display_content(content: str, max_length: int = 20000) -> str:
|
||||
"""Helper function to clean and truncate content for display."""
|
||||
if not content or not str(content).strip():
|
||||
logging.debug(f"Empty content received in _clean_display_content: {repr(content)}")
|
||||
return ""
|
||||
|
||||
content = str(content)
|
||||
@@ -174,11 +175,14 @@ def display_instruction(message: str, console=None, agent_name: str = None, agen
|
||||
console.print(Panel.fit(Text(message, style="bold blue"), title="Instruction", border_style="cyan"))
|
||||
|
||||
def display_tool_call(message: str, console=None):
|
||||
logging.debug(f"display_tool_call called with message: {repr(message)}")
|
||||
if not message or not message.strip():
|
||||
logging.debug("Empty message in display_tool_call, returning early")
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
logging.debug(f"Cleaned message in display_tool_call: {repr(message)}")
|
||||
|
||||
# Execute callback if registered
|
||||
if 'tool_call' in sync_display_callbacks:
|
||||
@@ -202,7 +206,8 @@ def display_error(message: str, console=None):
|
||||
|
||||
def display_generating(content: str = "", start_time: Optional[float] = None):
|
||||
if not content or not str(content).strip():
|
||||
return Panel("", title="", border_style="green")
|
||||
logging.debug("Empty content in display_generating, returning early")
|
||||
return None
|
||||
|
||||
elapsed_str = ""
|
||||
if start_time is not None:
|
||||
@@ -293,11 +298,14 @@ async def adisplay_instruction(message: str, console=None, agent_name: str = Non
|
||||
|
||||
async def adisplay_tool_call(message: str, console=None):
|
||||
"""Async version of display_tool_call."""
|
||||
logging.debug(f"adisplay_tool_call called with message: {repr(message)}")
|
||||
if not message or not message.strip():
|
||||
logging.debug("Empty message in adisplay_tool_call, returning early")
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
logging.debug(f"Cleaned message in adisplay_tool_call: {repr(message)}")
|
||||
|
||||
if 'tool_call' in async_display_callbacks:
|
||||
await async_display_callbacks['tool_call'](message=message)
|
||||
@@ -321,7 +329,8 @@ async def adisplay_error(message: str, console=None):
|
||||
async def adisplay_generating(content: str = "", start_time: Optional[float] = None):
|
||||
"""Async version of display_generating."""
|
||||
if not content or not str(content).strip():
|
||||
return Panel("", title="", border_style="green")
|
||||
logging.debug("Empty content in adisplay_generating, returning early")
|
||||
return None
|
||||
|
||||
elapsed_str = ""
|
||||
if start_time is not None:
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.61"
|
||||
version = "0.0.65"
|
||||
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
|
||||
authors = [
|
||||
{ name="Mervin Praison" }
|
||||
|
||||
Generated
+1
-1
@@ -1868,7 +1868,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.61"
|
||||
version = "0.0.65"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "openai" },
|
||||
|
||||
@@ -3060,7 +3060,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonai"
|
||||
version = "2.0.76"
|
||||
version = "2.0.80"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "instructor" },
|
||||
@@ -3197,7 +3197,7 @@ requires-dist = [
|
||||
{ name = "plotly", marker = "extra == 'realtime'", specifier = ">=5.24.0" },
|
||||
{ name = "praisonai-tools", marker = "extra == 'autogen'", specifier = ">=0.0.7" },
|
||||
{ name = "praisonai-tools", marker = "extra == 'crewai'", specifier = ">=0.0.7" },
|
||||
{ name = "praisonaiagents", specifier = ">=0.0.61" },
|
||||
{ name = "praisonaiagents", specifier = ">=0.0.65" },
|
||||
{ name = "pyautogen", marker = "extra == 'autogen'", specifier = ">=0.2.19" },
|
||||
{ name = "pydantic", marker = "extra == 'chat'", specifier = "<=2.10.1" },
|
||||
{ name = "pydantic", marker = "extra == 'code'", specifier = "<=2.10.1" },
|
||||
@@ -3250,16 +3250,16 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.61"
|
||||
version = "0.0.65"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "openai" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "rich" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/50/be/09af17ea9eee5135c7b091bca77e1fc7a8ff732a6148497276ff5a06bd2e/praisonaiagents-0.0.61.tar.gz", hash = "sha256:9e178b99a1d2ffe23acd8413810e5d937d910a72fbd851e04d10b0bcb129b48a", size = 102057 }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9e/58/6e07c4abf57d78be642f1517fe0692a003dfc253ad91a03c70521d246b5e/praisonaiagents-0.0.65.tar.gz", hash = "sha256:16627166f1b42bd8d21759fbd67015fff0b4730ca224b4a566cffe2b5bb770e8", size = 105128 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/12/1b/5656b79ae6c9f4c4e9e7b22db6800841c3bbab7fbd73c6c7f3381c936e64/praisonaiagents-0.0.61-py3-none-any.whl", hash = "sha256:835ec8a6fb1b2805a150db3d38bd4a1fe88333f078ee00190b102a3a4b2687a6", size = 121044 },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/02/e4f2ef3c008a407d3b945256d1513bf0159989055e9462c691265be3d294/praisonaiagents-0.0.65-py3-none-any.whl", hash = "sha256:f53e9c3ddf31c575dd5f65315db70b35487adb0f9ae908596e74ed315c12afc5", size = 124306 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
Reference in new issue
Block a user