diff --git a/backend/agent/prompt.py b/backend/agent/prompt.py index 599e635c..b63dd451 100644 --- a/backend/agent/prompt.py +++ b/backend/agent/prompt.py @@ -36,6 +36,9 @@ You have access to these tools through XML-based tool calling: - idle: A special tool to indicate you have completed all tasks and are entering idle state +""" + +RESPONSE_FORMAT = """ RESPONSE FORMAT – STRICTLY Output XML tags for tool calling @@ -79,4 +82,4 @@ def get_system_prompt(): ''' Returns the system prompt with XML tool usage instructions. ''' - return SYSTEM_PROMPT \ No newline at end of file + return SYSTEM_PROMPT + RESPONSE_FORMAT \ No newline at end of file diff --git a/backend/agent/workspace/index.html b/backend/agent/workspace/index.html deleted file mode 100644 index dd334f3e..00000000 --- a/backend/agent/workspace/index.html +++ /dev/null @@ -1,331 +0,0 @@ - - - - - - My Portfolio - - - - -
-
-

My Portfolio

- -
-
-
-
-
-
-
- -
-
-
-

Hello, I'm Your Name

-

Web Developer & Designer

- -
-
-
- -
-
-

About Me

-
-
-
- -
-
-
-

Hello! I'm a passionate web developer with a keen eye for design and a love for creating seamless user experiences. With a background in [Your Background], I bring a unique perspective to every project I work on.

-

I enjoy solving complex problems and turning ideas into reality through clean and efficient code. When I'm not coding, you can find me [Your Hobbies/Interests].

-
-
- - Education: [Your Education] -
-
- - Experience: [Years] years -
-
- - Location: [Your Location] -
-
- Download Resume -
-
-
-
- -
-
-

My Skills

-
-
-

Frontend Development

-
-
-
-

HTML5

-
-
-
-
-
-
-

CSS3

-
-
-
-
-
-
-

JavaScript

-
-
-
-
-
-
-

React

-
-
-
-
-
-
- -
-

Other Skills

-
-
-
-

SQL

-
-
-
-
-
-
-

Git

-
-
-
-
-
-
-

Responsive Design

-
-
-
-
-
-
-

UI/UX

-
-
-
-
-
-
-
-
-
- -
-
-

My Projects

-
- - - - -
-
-
-
-
- -
-
-
-

Project Title 1

-

A brief description of the project and your role in it. Explain the technologies used and the problems solved.

-
- HTML - CSS - JavaScript -
- -
-
- -
-
-
- -
-
-
-

Project Title 2

-

A brief description of the project and your role in it. Explain the technologies used and the problems solved.

-
- Figma - UI/UX - Prototyping -
- -
-
- -
-
-
- -
-
-
-

Project Title 3

-

A brief description of the project and your role in it. Explain the technologies used and the problems solved.

-
- React - Node.js - MongoDB -
- -
-
- -
-
-
- -
-
-
-

Project Title 4

-

A brief description of the project and your role in it. Explain the technologies used and the problems solved.

-
- Python - Data Analysis - Visualization -
- -
-
-
-
-
- -
-
-

Get In Touch

-
-
-
-
- -
-
-

Email

-

your.email@example.com

-
-
-
-
- -
-
-

Phone

-

+1 (123) 456-7890

-
-
-
-
- -
-
-

Location

-

City, Country

-
-
- -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
- -
-
-
-
-
- - - -
- -
- - - - \ No newline at end of file diff --git a/backend/tests/test_simple_tools.py b/backend/tests/test_simple_tools.py new file mode 100644 index 00000000..e776792d --- /dev/null +++ b/backend/tests/test_simple_tools.py @@ -0,0 +1,216 @@ +""" +Simple test script for LLM API with tool calling functionality. + +This script tests basic tool calling with both streaming and non-streaming to verify functionality. +""" + +import asyncio +import json +from typing import Dict, Any + +from services.llm import make_llm_api_call +from utils.logger import logger + +# Example tool schema from files_tool.py +CREATE_FILE_SCHEMA = { + "type": "function", + "function": { + "name": "create_file", + "description": "Create a new file with the provided contents at a given path in the workspace", + "parameters": { + "type": "object", + "properties": { + "file_path": { + "type": "string", + "description": "Path to the file to be created" + }, + "file_contents": { + "type": "string", + "description": "The content to write to the file" + } + }, + "required": ["file_path", "file_contents"] + } + } +} + +async def test_simple_tool_call(): + """Test a simple non-streaming tool call to verify functionality.""" + # Setup conversation + messages = [ + {"role": "system", "content": "You are a helpful assistant with access to file management tools."}, + {"role": "user", "content": "Create an HTML file named hello.html with a simple Hello World message."} + ] + + print("\n=== Testing non-streaming tool call ===\n") + + try: + # Make API call with tool + response = await make_llm_api_call( + messages=messages, + model_name="gpt-4o", + temperature=0.0, + tools=[CREATE_FILE_SCHEMA], + tool_choice={"type": "function", "function": {"name": "create_file"}} + ) + + # Print basic response info + print(f"Response model: {response.model}") + print(f"Response type: {type(response)}") + + # Check if the response has tool calls + assistant_message = response.choices[0].message + print(f"\nAssistant message content: {assistant_message.content}") + + if hasattr(assistant_message, 'tool_calls') and assistant_message.tool_calls: + print("\nTool calls detected:") + + for i, tool_call in enumerate(assistant_message.tool_calls): + print(f"\nTool call {i+1}:") + print(f" ID: {tool_call.id}") + print(f" Type: {tool_call.type}") + print(f" Function: {tool_call.function.name}") + print(f" Arguments:") + + try: + args = json.loads(tool_call.function.arguments) + print(json.dumps(args, indent=4)) + + # Access and print specific arguments + if tool_call.function.name == "create_file": + print(f"\nFile path: {args.get('file_path')}") + print(f"File contents length: {len(args.get('file_contents', ''))}") + print(f"File contents preview: {args.get('file_contents', '')[:100]}...") + except Exception as e: + print(f"Error parsing arguments: {e}") + else: + print("\nNo tool calls found in the response.") + print(f"Full response: {response}") + + except Exception as e: + logger.error(f"Error in test: {str(e)}", exc_info=True) + +async def test_streaming_tool_call(): + """Test tool calling with streaming to observe behavior.""" + # Setup conversation + messages = [ + {"role": "system", "content": "You are a helpful assistant with access to file management tools."}, + {"role": "user", "content": "Create an HTML file named hello.html with a simple Hello World message."} + ] + + print("\n=== Testing streaming tool call ===\n") + + try: + # Make API call with tool in streaming mode + print("Sending streaming request...") + stream_response = await make_llm_api_call( + messages=messages, + model_name="gpt-4o", + temperature=0.0, + tools=[CREATE_FILE_SCHEMA], + tool_choice={"type": "function", "function": {"name": "create_file"}}, + stream=True + ) + + # Process streaming response + print("\nResponse stream started. Processing chunks:\n") + + # Stream statistics + chunk_count = 0 + content_chunks = 0 + tool_call_chunks = 0 + accumulated_content = "" + + # Storage for accumulated tool calls + tool_calls = [] + + # Process each chunk + async for chunk in stream_response: + chunk_count += 1 + + # Print chunk number and type + print(f"\n--- Chunk {chunk_count} ---") + print(f"Chunk type: {type(chunk)}") + + if not hasattr(chunk, 'choices') or not chunk.choices: + print("No choices in chunk") + continue + + delta = chunk.choices[0].delta + + # Process content if present + if hasattr(delta, 'content') and delta.content is not None: + content_chunks += 1 + accumulated_content += delta.content + print(f"Content: {delta.content}") + + # Look for tool calls + if hasattr(delta, 'tool_calls') and delta.tool_calls: + tool_call_chunks += 1 + print("Tool call detected in chunk!") + + for tool_call in delta.tool_calls: + print(f"Tool call: {tool_call.model_dump()}") + + # Track tool call parts + tool_call_index = tool_call.index if hasattr(tool_call, 'index') else 0 + + # Initialize tool call if new + while len(tool_calls) <= tool_call_index: + tool_calls.append({ + "id": "", + "type": "function", + "function": {"name": "", "arguments": ""} + }) + + # Update tool call ID if present + if hasattr(tool_call, 'id') and tool_call.id: + tool_calls[tool_call_index]["id"] = tool_call.id + + # Update function name if present + if hasattr(tool_call, 'function'): + if hasattr(tool_call.function, 'name') and tool_call.function.name: + tool_calls[tool_call_index]["function"]["name"] = tool_call.function.name + + # Update function arguments if present + if hasattr(tool_call.function, 'arguments') and tool_call.function.arguments: + tool_calls[tool_call_index]["function"]["arguments"] += tool_call.function.arguments + + # Summary after all chunks processed + print("\n=== Streaming Summary ===") + print(f"Total chunks: {chunk_count}") + print(f"Content chunks: {content_chunks}") + print(f"Tool call chunks: {tool_call_chunks}") + + if accumulated_content: + print(f"\nAccumulated content: {accumulated_content}") + + if tool_calls: + print("\nAccumulated tool calls:") + for i, tool_call in enumerate(tool_calls): + print(f"\nTool call {i+1}:") + print(f" ID: {tool_call['id']}") + print(f" Type: {tool_call['type']}") + print(f" Function: {tool_call['function']['name']}") + print(f" Arguments: {tool_call['function']['arguments']}") + + # Try to parse arguments + try: + args = json.loads(tool_call['function']['arguments']) + print("\nParsed arguments:") + print(json.dumps(args, indent=4)) + except Exception as e: + print(f"Error parsing arguments: {str(e)}") + else: + print("\nNo tool calls accumulated from streaming response.") + + except Exception as e: + logger.error(f"Error in streaming test: {str(e)}", exc_info=True) + +async def main(): + """Run both tests for comparison.""" + # await test_simple_tool_call() + await test_streaming_tool_call() + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file