This commit is contained in:
marko-kraemer 2025-04-07 12:08:58 +01:00
parent 3c0634f6bc
commit cfb3e561ed
3 changed files with 220 additions and 332 deletions

View File

@ -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 - idle: A special tool to indicate you have completed all tasks and are entering idle state
</available_tools> </available_tools>
"""
RESPONSE_FORMAT = """
<response_format> <response_format>
RESPONSE FORMAT STRICTLY Output XML tags for tool calling 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. Returns the system prompt with XML tool usage instructions.
''' '''
return SYSTEM_PROMPT return SYSTEM_PROMPT + RESPONSE_FORMAT

View File

@ -1,331 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Portfolio</title>
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
</head>
<body>
<header>
<div class="container">
<h1 class="logo">My Portfolio</h1>
<nav>
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#skills">Skills</a></li>
<li><a href="#projects">Projects</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
<div class="hamburger">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>
</div>
</header>
<section id="home" class="hero">
<div class="container">
<div class="hero-content">
<h1>Hello, I'm <span class="highlight">Your Name</span></h1>
<p class="tagline">Web Developer & Designer</p>
<div class="cta-buttons">
<a href="#projects" class="btn primary-btn">View My Work</a>
<a href="#contact" class="btn secondary-btn">Contact Me</a>
</div>
</div>
</div>
</section>
<section id="about" class="about">
<div class="container">
<h2 class="section-title">About Me</h2>
<div class="about-content">
<div class="about-image">
<div class="image-placeholder">
<i class="fas fa-user"></i>
</div>
</div>
<div class="about-text">
<p>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.</p>
<p>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].</p>
<div class="about-details">
<div class="detail">
<i class="fas fa-graduation-cap"></i>
<span>Education: [Your Education]</span>
</div>
<div class="detail">
<i class="fas fa-briefcase"></i>
<span>Experience: [Years] years</span>
</div>
<div class="detail">
<i class="fas fa-map-marker-alt"></i>
<span>Location: [Your Location]</span>
</div>
</div>
<a href="#" class="btn primary-btn">Download Resume</a>
</div>
</div>
</div>
</section>
<section id="skills" class="skills">
<div class="container">
<h2 class="section-title">My Skills</h2>
<div class="skills-content">
<div class="skill-category">
<h3>Frontend Development</h3>
<div class="skills-grid">
<div class="skill-item">
<div class="skill-icon"><i class="fab fa-html5"></i></div>
<h4>HTML5</h4>
<div class="skill-bar">
<div class="skill-level" style="width: 90%"></div>
</div>
</div>
<div class="skill-item">
<div class="skill-icon"><i class="fab fa-css3-alt"></i></div>
<h4>CSS3</h4>
<div class="skill-bar">
<div class="skill-level" style="width: 85%"></div>
</div>
</div>
<div class="skill-item">
<div class="skill-icon"><i class="fab fa-js"></i></div>
<h4>JavaScript</h4>
<div class="skill-bar">
<div class="skill-level" style="width: 80%"></div>
</div>
</div>
<div class="skill-item">
<div class="skill-icon"><i class="fab fa-react"></i></div>
<h4>React</h4>
<div class="skill-bar">
<div class="skill-level" style="width: 75%"></div>
</div>
</div>
</div>
</div>
<div class="skill-category">
<h3>Other Skills</h3>
<div class="skills-grid">
<div class="skill-item">
<div class="skill-icon"><i class="fas fa-database"></i></div>
<h4>SQL</h4>
<div class="skill-bar">
<div class="skill-level" style="width: 70%"></div>
</div>
</div>
<div class="skill-item">
<div class="skill-icon"><i class="fab fa-git-alt"></i></div>
<h4>Git</h4>
<div class="skill-bar">
<div class="skill-level" style="width: 85%"></div>
</div>
</div>
<div class="skill-item">
<div class="skill-icon"><i class="fas fa-mobile-alt"></i></div>
<h4>Responsive Design</h4>
<div class="skill-bar">
<div class="skill-level" style="width: 90%"></div>
</div>
</div>
<div class="skill-item">
<div class="skill-icon"><i class="fas fa-paint-brush"></i></div>
<h4>UI/UX</h4>
<div class="skill-bar">
<div class="skill-level" style="width: 75%"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section id="projects" class="projects">
<div class="container">
<h2 class="section-title">My Projects</h2>
<div class="project-filters">
<button class="filter-btn active" data-filter="all">All</button>
<button class="filter-btn" data-filter="web">Web Development</button>
<button class="filter-btn" data-filter="design">Design</button>
<button class="filter-btn" data-filter="other">Other</button>
</div>
<div class="projects-grid">
<div class="project-card" data-category="web">
<div class="project-image">
<div class="image-placeholder">
<i class="fas fa-laptop-code"></i>
</div>
</div>
<div class="project-info">
<h3>Project Title 1</h3>
<p>A brief description of the project and your role in it. Explain the technologies used and the problems solved.</p>
<div class="project-tags">
<span>HTML</span>
<span>CSS</span>
<span>JavaScript</span>
</div>
<div class="project-links">
<a href="#" class="btn small-btn"><i class="fas fa-eye"></i> Live Demo</a>
<a href="#" class="btn small-btn"><i class="fab fa-github"></i> Source Code</a>
</div>
</div>
</div>
<div class="project-card" data-category="design">
<div class="project-image">
<div class="image-placeholder">
<i class="fas fa-paint-brush"></i>
</div>
</div>
<div class="project-info">
<h3>Project Title 2</h3>
<p>A brief description of the project and your role in it. Explain the technologies used and the problems solved.</p>
<div class="project-tags">
<span>Figma</span>
<span>UI/UX</span>
<span>Prototyping</span>
</div>
<div class="project-links">
<a href="#" class="btn small-btn"><i class="fas fa-eye"></i> Live Demo</a>
<a href="#" class="btn small-btn"><i class="fab fa-github"></i> Source Code</a>
</div>
</div>
</div>
<div class="project-card" data-category="web">
<div class="project-image">
<div class="image-placeholder">
<i class="fas fa-mobile-alt"></i>
</div>
</div>
<div class="project-info">
<h3>Project Title 3</h3>
<p>A brief description of the project and your role in it. Explain the technologies used and the problems solved.</p>
<div class="project-tags">
<span>React</span>
<span>Node.js</span>
<span>MongoDB</span>
</div>
<div class="project-links">
<a href="#" class="btn small-btn"><i class="fas fa-eye"></i> Live Demo</a>
<a href="#" class="btn small-btn"><i class="fab fa-github"></i> Source Code</a>
</div>
</div>
</div>
<div class="project-card" data-category="other">
<div class="project-image">
<div class="image-placeholder">
<i class="fas fa-cogs"></i>
</div>
</div>
<div class="project-info">
<h3>Project Title 4</h3>
<p>A brief description of the project and your role in it. Explain the technologies used and the problems solved.</p>
<div class="project-tags">
<span>Python</span>
<span>Data Analysis</span>
<span>Visualization</span>
</div>
<div class="project-links">
<a href="#" class="btn small-btn"><i class="fas fa-eye"></i> Live Demo</a>
<a href="#" class="btn small-btn"><i class="fab fa-github"></i> Source Code</a>
</div>
</div>
</div>
</div>
</div>
</section>
<section id="contact" class="contact">
<div class="container">
<h2 class="section-title">Get In Touch</h2>
<div class="contact-content">
<div class="contact-info">
<div class="contact-item">
<div class="contact-icon">
<i class="fas fa-envelope"></i>
</div>
<div class="contact-details">
<h3>Email</h3>
<p>your.email@example.com</p>
</div>
</div>
<div class="contact-item">
<div class="contact-icon">
<i class="fas fa-phone"></i>
</div>
<div class="contact-details">
<h3>Phone</h3>
<p>+1 (123) 456-7890</p>
</div>
</div>
<div class="contact-item">
<div class="contact-icon">
<i class="fas fa-map-marker-alt"></i>
</div>
<div class="contact-details">
<h3>Location</h3>
<p>City, Country</p>
</div>
</div>
<div class="social-links">
<a href="#" class="social-link"><i class="fab fa-linkedin"></i></a>
<a href="#" class="social-link"><i class="fab fa-github"></i></a>
<a href="#" class="social-link"><i class="fab fa-twitter"></i></a>
<a href="#" class="social-link"><i class="fab fa-instagram"></i></a>
</div>
</div>
<div class="contact-form">
<form id="contactForm">
<div class="form-group">
<label for="name">Name</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="subject">Subject</label>
<input type="text" id="subject" name="subject" required>
</div>
<div class="form-group">
<label for="message">Message</label>
<textarea id="message" name="message" rows="5" required></textarea>
</div>
<button type="submit" class="btn primary-btn">Send Message</button>
</form>
</div>
</div>
</div>
</section>
<footer>
<div class="container">
<p>&copy; 2023 My Portfolio. All Rights Reserved.</p>
<div class="footer-links">
<a href="#home">Home</a>
<a href="#about">About</a>
<a href="#skills">Skills</a>
<a href="#projects">Projects</a>
<a href="#contact">Contact</a>
</div>
</div>
</footer>
<div class="scroll-to-top">
<i class="fas fa-arrow-up"></i>
</div>
<script src="script.js"></script>
</body>
</html>

View File

@ -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())