Spaces:
Build error
Build error
| import os | |
| import httpx | |
| from dotenv import load_dotenv | |
| from typing import Dict, Any, Optional, List, Iterable | |
| from datetime import datetime | |
| import logging | |
| import asyncio | |
| import json | |
| import google.generativeai as genai | |
| import PIL.Image | |
| # Import custom modules | |
| from app.utils.load_env import ACCESS_TOKEN, WHATSAPP_API_URL, GEMNI_API, OPENAI_API | |
| from app.utils.system_prompt import system_prompt, agentic_prompt | |
| from google.generativeai.types import content_types | |
| from testtool import ToolCallParser, FunctionExecutor | |
| from app.services.search_engine import google_search, set_light_values | |
| # Load environment variables | |
| load_dotenv() | |
| # Set up logging | |
| logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") | |
| logger = logging.getLogger(__name__) | |
| def tool_config_from_mode(mode: str, fns: Iterable[str] = ()): | |
| """ | |
| Create a tool config with the specified function calling mode. | |
| """ | |
| return content_types.to_tool_config( | |
| {"function_calling_config": {"mode": mode, "allowed_function_names": fns}} | |
| ) | |
| def transform_result_to_response(results: List[Dict[str, Any]]) -> Dict[str, Any]: | |
| """ | |
| Transform a list of result objects into a structured response dictionary. | |
| """ | |
| response = {} | |
| for res in results: | |
| if res.get("status") == "success": | |
| function_name = res.get("function") | |
| function_result = res.get("result") | |
| response[function_name] = function_result | |
| else: | |
| # Handle individual failures if necessary | |
| response[res.get("function", "unknown_function")] = { | |
| "error": "Function execution failed." | |
| } | |
| return response | |
| async def process_tool_calls(input_string: str) -> List[Dict[str, Any]]: | |
| """ | |
| Processes all tool calls extracted from the input string and executes them. | |
| """ | |
| tool_calls = ToolCallParser.extract_tool_calls(input_string) | |
| logger.info(f"Extracted tool_calls: {tool_calls}") | |
| results = [] | |
| for tool_call in tool_calls: | |
| result = await FunctionExecutor.call_function(tool_call) | |
| results.append(result) | |
| return results | |
| async def main(): | |
| # Define available functions and tool configuration | |
| available_functions = ["google_search", "set_light_values"] | |
| config = tool_config_from_mode("any", fns=available_functions) | |
| # Define chat history | |
| history = [{"role": "user", "parts": "This is the chat history so far"}] | |
| # Configure the Gemini API | |
| genai.configure(api_key=GEMNI_API) | |
| model = genai.GenerativeModel( | |
| "gemini-1.5-pro-002", | |
| system_instruction=agentic_prompt, | |
| tools=[google_search, set_light_values] | |
| ) | |
| # Start chat with history | |
| chat = model.start_chat(history=history) | |
| # Send the user's message and await the response | |
| try: | |
| response = chat.send_message( | |
| "find the cheapest flight price from Medan to Jakarta on 1st January 2025", | |
| tool_config=config | |
| ) | |
| except Exception as e: | |
| logger.error(f"Error sending message: {e}") | |
| return | |
| # Ensure that response.parts exists and is iterable | |
| if not hasattr(response, 'parts') or not isinstance(response.parts, Iterable): | |
| logger.error("Invalid response format: 'parts' attribute is missing or not iterable.") | |
| return | |
| # Convert response parts to a single input string | |
| input_string = "\n".join(str(part) for part in response.parts) | |
| logger.info(f"Input string for tool processing: {input_string}") | |
| # Process tool calls | |
| try: | |
| results = await process_tool_calls(input_string) | |
| except Exception as e: | |
| logger.error(f"Error processing tool calls: {e}") | |
| return | |
| # Log and print the results | |
| logger.info("Results from tool calls:") | |
| for result in results: | |
| logger.info(json.dumps(result, indent=4)) | |
| print(json.dumps(result, indent=4)) | |
| # Transform the results into the desired response format | |
| responses = transform_result_to_response(results) | |
| # Build the response parts for the chat | |
| try: | |
| response_parts = [ | |
| genai.protos.Part( | |
| function_response=genai.protos.FunctionResponse( | |
| name=fn, | |
| response={"result": val} | |
| ) | |
| ) | |
| for fn, val in responses.items() | |
| ] | |
| except Exception as e: | |
| logger.error(f"Error building response parts: {e}") | |
| return | |
| # Send the function responses back to the chat | |
| try: | |
| final_response = chat.send_message(response_parts) | |
| print(final_response.text) | |
| except Exception as e: | |
| logger.error(f"Error sending final response: {e}") | |
| if __name__ == "__main__": | |
| asyncio.run(main()) | |