Spaces:
Paused
Paused
| """ | |
| Simple tool-calling chat with ExCom AI | |
| Works around vLLM's tool_choice requirements | |
| """ | |
| from openai import OpenAI | |
| import json | |
| from datetime import datetime | |
| import math | |
| # Configure OpenAI client for your vLLM endpoint | |
| client = OpenAI( | |
| base_url="https://plarnholt-excom-ai-demo.hf.space/v1", | |
| api_key="not-needed" | |
| ) | |
| # Define tools | |
| tools = [ | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "calculator", | |
| "description": "Evaluates a mathematical expression", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "expression": { | |
| "type": "string", | |
| "description": "Math expression to evaluate, e.g., '2 + 2 * 3'" | |
| } | |
| }, | |
| "required": ["expression"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "get_current_time", | |
| "description": "Returns the current date and time", | |
| "parameters": { | |
| "type": "object", | |
| "properties": {} | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "get_weather", | |
| "description": "Gets the weather for a city (simulated)", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "city": { | |
| "type": "string", | |
| "description": "City name" | |
| } | |
| }, | |
| "required": ["city"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "word_counter", | |
| "description": "Counts the number of words in the given text", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": { | |
| "type": "string", | |
| "description": "Text to count words in" | |
| } | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "reverse_text", | |
| "description": "Reverses the given text", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": { | |
| "type": "string", | |
| "description": "Text to reverse" | |
| } | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| } | |
| ] | |
| # Tool implementations | |
| def calculator(expression: str) -> str: | |
| """Evaluates a mathematical expression""" | |
| try: | |
| result = eval(expression, {"__builtins__": {}, "math": math}) | |
| return str(result) | |
| except Exception as e: | |
| return f"Error: {str(e)}" | |
| def get_current_time() -> str: | |
| """Returns the current date and time""" | |
| return datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
| def get_weather(city: str) -> str: | |
| """Gets simulated weather for a city""" | |
| weather_data = { | |
| "paris": "18°C, sunny", | |
| "london": "15°C, cloudy", | |
| "new york": "22°C, partly cloudy", | |
| "tokyo": "25°C, clear", | |
| "berlin": "16°C, rainy", | |
| "sydney": "23°C, sunny", | |
| "mumbai": "30°C, hot and humid", | |
| "toronto": "12°C, cool", | |
| } | |
| return weather_data.get(city.lower(), f"Weather data not available for {city}") | |
| def word_counter(text: str) -> str: | |
| """Counts words in text""" | |
| words = text.split() | |
| return f"Word count: {len(words)}" | |
| def reverse_text(text: str) -> str: | |
| """Reverses text""" | |
| return text[::-1] | |
| # Function dispatcher | |
| def execute_tool(tool_name: str, arguments: dict) -> str: | |
| """Execute a tool by name with given arguments""" | |
| if tool_name == "calculator": | |
| return calculator(arguments["expression"]) | |
| elif tool_name == "get_current_time": | |
| return get_current_time() | |
| elif tool_name == "get_weather": | |
| return get_weather(arguments["city"]) | |
| elif tool_name == "word_counter": | |
| return word_counter(arguments["text"]) | |
| elif tool_name == "reverse_text": | |
| return reverse_text(arguments["text"]) | |
| else: | |
| return f"Unknown tool: {tool_name}" | |
| def chat(user_message: str, messages: list = None): | |
| """Send a message and handle tool calls""" | |
| if messages is None: | |
| messages = [] | |
| # Add user message | |
| messages.append({"role": "user", "content": user_message}) | |
| try: | |
| # Call the model with tools (no tool_choice parameter) | |
| response = client.chat.completions.create( | |
| model="excom-ai", | |
| messages=messages, | |
| tools=tools, | |
| temperature=0.4 | |
| ) | |
| assistant_message = response.choices[0].message | |
| # Check if model wants to use tools | |
| if assistant_message.tool_calls: | |
| # Add assistant's tool call request to messages | |
| messages.append({ | |
| "role": "assistant", | |
| "content": assistant_message.content, | |
| "tool_calls": [ | |
| { | |
| "id": tc.id, | |
| "type": "function", | |
| "function": { | |
| "name": tc.function.name, | |
| "arguments": tc.function.arguments | |
| } | |
| } | |
| for tc in assistant_message.tool_calls | |
| ] | |
| }) | |
| # Execute each tool call | |
| for tool_call in assistant_message.tool_calls: | |
| function_name = tool_call.function.name | |
| function_args = json.loads(tool_call.function.arguments) | |
| print(f"🔧 Calling tool: {function_name}({function_args})") | |
| # Execute the tool | |
| tool_result = execute_tool(function_name, function_args) | |
| # Add tool result to messages | |
| messages.append({ | |
| "role": "tool", | |
| "tool_call_id": tool_call.id, | |
| "name": function_name, | |
| "content": tool_result | |
| }) | |
| # Get final response from model | |
| final_response = client.chat.completions.create( | |
| model="excom-ai", | |
| messages=messages, | |
| temperature=0.4 | |
| ) | |
| return final_response.choices[0].message.content, messages | |
| else: | |
| # No tools needed, return direct response | |
| return assistant_message.content, messages | |
| except Exception as e: | |
| return f"Error: {e}", messages | |
| def main(): | |
| print("=" * 60) | |
| print("ExCom AI - Simple Tool Calling Chat") | |
| print("=" * 60) | |
| print("Available tools:") | |
| print(" • calculator - Evaluate math expressions") | |
| print(" • get_current_time - Get current date/time") | |
| print(" • get_weather - Get weather for cities") | |
| print(" • word_counter - Count words in text") | |
| print(" • reverse_text - Reverse text") | |
| print("\nType 'quit', 'exit', or 'q' to end.") | |
| print("Type 'reset' to clear conversation history.") | |
| print("=" * 60) | |
| print() | |
| messages = [] | |
| while True: | |
| try: | |
| user_input = input("You: ").strip() | |
| if user_input.lower() in ['quit', 'exit', 'q']: | |
| print("Goodbye!") | |
| break | |
| if user_input.lower() == 'reset': | |
| messages = [] | |
| print("🔄 Conversation history cleared.\n") | |
| continue | |
| if not user_input: | |
| continue | |
| response, messages = chat(user_input, messages) | |
| print(f"Assistant: {response}\n") | |
| except KeyboardInterrupt: | |
| print("\n\nGoodbye!") | |
| break | |
| except Exception as e: | |
| print(f"❌ Error: {e}\n") | |
| # Reset messages on unexpected error | |
| messages = [] | |
| if __name__ == "__main__": | |
| main() | |