|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import os |
|
import logging |
|
import json |
|
|
|
from dotenv import load_dotenv |
|
from camel.models import ModelFactory |
|
from camel.types import ModelPlatformType |
|
|
|
from camel.toolkits import ( |
|
SearchToolkit, |
|
BrowserToolkit, |
|
) |
|
from camel.societies import RolePlaying |
|
from camel.logger import set_log_level, get_logger |
|
|
|
import pathlib |
|
|
|
base_dir = pathlib.Path(__file__).parent.parent |
|
env_path = base_dir / "owl" / ".env" |
|
load_dotenv(dotenv_path=str(env_path)) |
|
|
|
set_log_level(level="DEBUG") |
|
logger = get_logger(__name__) |
|
file_handler = logging.FileHandler("learning_journey.log") |
|
file_handler.setLevel(logging.DEBUG) |
|
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") |
|
file_handler.setFormatter(formatter) |
|
logger.addHandler(file_handler) |
|
|
|
root_logger = logging.getLogger() |
|
root_logger.addHandler(file_handler) |
|
|
|
|
|
def construct_learning_society(task: str) -> RolePlaying: |
|
"""Construct a society of agents for the learning journey companion. |
|
|
|
Args: |
|
task (str): The learning task description including what the user wants to learn and what they already know. |
|
|
|
Returns: |
|
RolePlaying: A configured society of agents for the learning companion. |
|
""" |
|
models = { |
|
"user": ModelFactory.create( |
|
model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL, |
|
model_type="gpt-4o", |
|
api_key=os.getenv("OPENAI_API_KEY"), |
|
model_config_dict={"temperature": 0.4}, |
|
), |
|
"assistant": ModelFactory.create( |
|
model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL, |
|
model_type="gpt-4o", |
|
api_key=os.getenv("OPENAI_API_KEY"), |
|
model_config_dict={"temperature": 0.4}, |
|
), |
|
"content_researcher": ModelFactory.create( |
|
model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL, |
|
model_type="gpt-4o", |
|
api_key=os.getenv("OPENAI_API_KEY"), |
|
model_config_dict={"temperature": 0.2}, |
|
), |
|
"planning": ModelFactory.create( |
|
model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL, |
|
model_type="gpt-4o", |
|
api_key=os.getenv("OPENAI_API_KEY"), |
|
model_config_dict={"temperature": 0.3}, |
|
), |
|
} |
|
|
|
browser_toolkit = BrowserToolkit( |
|
headless=False, |
|
web_agent_model=models["content_researcher"], |
|
planning_agent_model=models["planning"], |
|
) |
|
|
|
tools = [ |
|
*browser_toolkit.get_tools(), |
|
SearchToolkit().search_duckduckgo, |
|
] |
|
|
|
user_agent_kwargs = { |
|
"model": models["user"], |
|
} |
|
|
|
assistant_agent_kwargs = { |
|
"model": models["assistant"], |
|
"tools": tools, |
|
} |
|
|
|
task_kwargs = { |
|
"task_prompt": task, |
|
"with_task_specify": False, |
|
} |
|
|
|
society = RolePlaying( |
|
**task_kwargs, |
|
user_role_name="learner", |
|
user_agent_kwargs=user_agent_kwargs, |
|
assistant_role_name="learning_companion", |
|
assistant_agent_kwargs=assistant_agent_kwargs, |
|
) |
|
|
|
return society |
|
|
|
|
|
def analyze_chat_history(chat_history): |
|
"""Analyze chat history and extract tool call information.""" |
|
print("\n============ Tool Call Analysis ============") |
|
logger.info("========== Starting tool call analysis ==========") |
|
|
|
tool_calls = [] |
|
for i, message in enumerate(chat_history): |
|
if message.get("role") == "assistant" and "tool_calls" in message: |
|
for tool_call in message.get("tool_calls", []): |
|
if tool_call.get("type") == "function": |
|
function = tool_call.get("function", {}) |
|
tool_info = { |
|
"call_id": tool_call.get("id"), |
|
"name": function.get("name"), |
|
"arguments": function.get("arguments"), |
|
"message_index": i, |
|
} |
|
tool_calls.append(tool_info) |
|
print( |
|
f"Tool Call: {function.get('name')} Args: {function.get('arguments')}" |
|
) |
|
logger.info( |
|
f"Tool Call: {function.get('name')} Args: {function.get('arguments')}" |
|
) |
|
|
|
elif message.get("role") == "tool" and "tool_call_id" in message: |
|
for tool_call in tool_calls: |
|
if tool_call.get("call_id") == message.get("tool_call_id"): |
|
result = message.get("content", "") |
|
result_summary = ( |
|
result[:100] + "..." if len(result) > 100 else result |
|
) |
|
print( |
|
f"Tool Result: {tool_call.get('name')} Return: {result_summary}" |
|
) |
|
logger.info( |
|
f"Tool Result: {tool_call.get('name')} Return: {result_summary}" |
|
) |
|
|
|
print(f"Total tool calls found: {len(tool_calls)}") |
|
logger.info(f"Total tool calls found: {len(tool_calls)}") |
|
logger.info("========== Finished tool call analysis ==========") |
|
|
|
with open("learning_journey_history.json", "w", encoding="utf-8") as f: |
|
json.dump(chat_history, f, ensure_ascii=False, indent=2) |
|
|
|
print("Records saved to learning_journey_history.json") |
|
print("============ Analysis Complete ============\n") |
|
|
|
|
|
def run_learning_companion(task: str = None): |
|
"""Run the learning companion with the given task. |
|
|
|
Args: |
|
task (str, optional): The learning task description. Defaults to an example task. |
|
""" |
|
task = """ |
|
I want to learn about the transformers architecture in an llm. |
|
I've also taken a basic statistics course. |
|
I have about 10 hours per week to dedicate to learning. Devise a roadmap for me . |
|
""" |
|
|
|
society = construct_learning_society(task) |
|
|
|
from owl.utils import run_society |
|
|
|
answer, chat_history, token_count = run_society(society, round_limit=5) |
|
|
|
|
|
analyze_chat_history(chat_history) |
|
print(f"\033[94mAnswer: {answer}\033[0m") |
|
|
|
|
|
if __name__ == "__main__": |
|
run_learning_companion() |
|
|