From 7921e148fa5c43c9998318b31fcf2d3f981ef2e7 Mon Sep 17 00:00:00 2001 From: JINO-ROHIT Date: Thu, 20 Mar 2025 09:50:16 +0530 Subject: [PATCH] cookign assistant --- community_usecase/cooking-assistant/README.md | 23 +++ .../cooking-assistant/run_gpt4o.py | 153 ++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 community_usecase/cooking-assistant/README.md create mode 100644 community_usecase/cooking-assistant/run_gpt4o.py diff --git a/community_usecase/cooking-assistant/README.md b/community_usecase/cooking-assistant/README.md new file mode 100644 index 0000000..67461a3 --- /dev/null +++ b/community_usecase/cooking-assistant/README.md @@ -0,0 +1,23 @@ +# Personal Dietician + +This code example searches for recipes on the internet based on the ingredients you have, refines the content based on a dieterary restriction and generates shopping lists. + +## How to use + +1. Set up the OPENAI api key in the .env file + +```bash +OPENAI_API_KEY = 'xxx' +``` + +2. Copy the python script to the owl/examples folder. + +3. Run the script + +```bash +python run_gpt4o.py +``` + +4. You can find the entire thought process of the agent within the log file. + +5. Demo Link - https://drive.google.com/drive/folders/10LnMEMf_xQGojHyTAS57vI7oOmjvuKPE?usp=sharing \ No newline at end of file diff --git a/community_usecase/cooking-assistant/run_gpt4o.py b/community_usecase/cooking-assistant/run_gpt4o.py new file mode 100644 index 0000000..c73911f --- /dev/null +++ b/community_usecase/cooking-assistant/run_gpt4o.py @@ -0,0 +1,153 @@ +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 + + +from owl.utils import run_society +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("cooking_companion.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_cooking_society(task: str) -> RolePlaying: + """Construct a society of agents for the cooking companion. + + Args: + task (str): The cooking-related task to be addressed. + + Returns: + RolePlaying: A configured society of agents for the cooking 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}, + ), + "recipe_analyst": 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["recipe_analyst"], + 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="user", + user_agent_kwargs=user_agent_kwargs, + assistant_role_name="cooking_assistant", + 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("cooking_chat_history.json", "w", encoding="utf-8") as f: + json.dump(chat_history, f, ensure_ascii=False, indent=2) + + print("Records saved to cooking_chat_history.json") + print("============ Analysis Complete ============\n") + + +def run_cooking_companion(): + task = "I have chicken breast, broccoli, garlic, and pasta. I'm looking for a quick dinner recipe that's healthy. I'm also trying to reduce my sodium intake. Search the internet for a recipe, modify it for low sodium, and create a shopping list for any additional ingredients I need?" + society = construct_cooking_society(task) + answer, chat_history, token_count = run_society(society) + + # Record tool usage history + analyze_chat_history(chat_history) + print(f"\033[94mAnswer: {answer}\033[0m") + + +if __name__ == "__main__": + run_cooking_companion() \ No newline at end of file