feat: Implement Trillium notes executor for searching and creating notes via ETAPI

- Added `trillium.py` for searching and creating notes with Trillium's ETAPI.
- Implemented `search_notes` and `create_note` functions with appropriate error handling and validation.

feat: Add web search functionality using DuckDuckGo

- Introduced `web_search.py` for performing web searches without API keys.
- Implemented `search_web` function with result handling and validation.

feat: Create provider-agnostic function caller for iterative tool calling

- Developed `function_caller.py` to manage LLM interactions with tools.
- Implemented iterative calling logic with error handling and tool execution.

feat: Establish a tool registry for managing available tools

- Created `registry.py` to define and manage tool availability and execution.
- Integrated feature flags for enabling/disabling tools based on environment variables.

feat: Implement event streaming for tool calling processes

- Added `stream_events.py` to manage Server-Sent Events (SSE) for tool calling.
- Enabled real-time updates during tool execution for enhanced user experience.

test: Add tests for tool calling system components

- Created `test_tools.py` to validate functionality of code execution, web search, and tool registry.
- Implemented asynchronous tests to ensure proper execution and result handling.

chore: Add Dockerfile for sandbox environment setup

- Created `Dockerfile` to set up a Python environment with necessary dependencies for code execution.

chore: Add debug regex script for testing XML parsing

- Introduced `debug_regex.py` to validate regex patterns against XML tool calls.

chore: Add HTML template for displaying thinking stream events

- Created `test_thinking_stream.html` for visualizing tool calling events in a user-friendly format.

test: Add tests for OllamaAdapter XML parsing

- Developed `test_ollama_parser.py` to validate XML parsing with various test cases, including malformed XML.
This commit is contained in:
serversdwn
2025-12-26 03:49:20 -05:00
parent f1471cde84
commit 64429b19e6
37 changed files with 3238 additions and 23 deletions

103
test_ollama_parser.py Normal file
View File

@@ -0,0 +1,103 @@
#!/usr/bin/env python3
"""
Test OllamaAdapter XML parsing with real malformed examples.
"""
import asyncio
import sys
sys.path.insert(0, '/home/serversdown/project-lyra/cortex')
from autonomy.tools.adapters.ollama_adapter import OllamaAdapter
async def test_parser():
adapter = OllamaAdapter()
# Test cases with actual malformed XML we've seen
test_cases = [
{
"name": "Malformed closing tag 1",
"xml": """<tool_call>
<name>execute_code</name>
<arguments>
<language>python</language>
<code>print(50 / 2)</code>
<reason>To calculate the result of dividing 50 by 2.</reason>
</arguments>
</olith>"""
},
{
"name": "Malformed closing tag 2",
"xml": """<tool_call>
<name>execute_code</name>
<arguments>
<language>python</language>
<code>print(60 / 4)</code>
</arguments>
<reason>To calculate 60 divided by 4 using Python.</reason>
</LTRB"""
},
{
"name": "Partial XML (missing opening)",
"xml": """<arguments>
<language>python</language>
<code>result = 35 / 7; result</code>
</arguments>
<reason>To calculate the division of 35 by 7 using Python.</reason>
</tool_call>"""
},
{
"name": "Correct XML",
"xml": """<tool_call>
<name>execute_code</name>
<arguments>
<language>python</language>
<code>print(100 / 4)</code>
<reason>Calculate division</reason>
</arguments>
</tool_call>"""
},
{
"name": "XML with surrounding text",
"xml": """Let me help you with that.
<tool_call>
<name>execute_code</name>
<arguments>
<language>python</language>
<code>print(20 / 4)</code>
<reason>Calculate the result</reason>
</arguments>
</tool_call>
The result will be shown above."""
}
]
print("=" * 80)
print("Testing OllamaAdapter XML Parsing")
print("=" * 80)
for test in test_cases:
print(f"\nTest: {test['name']}")
print("-" * 80)
print(f"Input XML:\n{test['xml'][:200]}{'...' if len(test['xml']) > 200 else ''}")
print("-" * 80)
try:
result = await adapter.parse_response(test['xml'])
print(f"✅ Parsed successfully!")
print(f" Content: {result.get('content', '')[:100]}")
print(f" Tool calls found: {len(result.get('tool_calls') or [])}")
if result.get('tool_calls'):
for idx, tc in enumerate(result['tool_calls']):
print(f" Tool {idx + 1}: {tc.get('name')} with args: {tc.get('arguments')}")
except Exception as e:
print(f"❌ Error: {e}")
print()
if __name__ == "__main__":
asyncio.run(test_parser())