Spaces:
Build error
Build error
Fix version-agnostic WorkflowHandler implementation
Browse files- Research-based solution using official LlamaIndex docs
- Auto-detect .chat() method (0.12.x) vs .run() method (0.14.x)
- Use proper `await handler` pattern for WorkflowHandler (0.14.x)
- Tested locally with 0.12.x - agent returns responses correctly
- Version bumped to 1.0.11
π€ Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- app/core/agent.py +50 -15
- debug_version.py +83 -1
- pyproject.toml +1 -1
app/core/agent.py
CHANGED
|
@@ -820,28 +820,63 @@ class ChatCalAgent:
|
|
| 820 |
print(f"π Debug: Agent type: {type(self.agent)}")
|
| 821 |
# Skip tools debug - ReActAgent doesn't expose tools attribute
|
| 822 |
|
| 823 |
-
#
|
| 824 |
-
# LlamaIndex 0.14.2 ReActAgent.run() should work synchronously
|
| 825 |
import time
|
|
|
|
| 826 |
start_time = time.time()
|
| 827 |
print(f"π Debug: Starting agent execution at {start_time}")
|
| 828 |
|
| 829 |
try:
|
| 830 |
-
|
| 831 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 832 |
|
| 833 |
-
|
| 834 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 835 |
|
| 836 |
-
|
| 837 |
-
|
| 838 |
-
|
| 839 |
-
print(f"π Debug: Result: {str(result)[:200]}...")
|
| 840 |
-
|
| 841 |
-
# Convert result to string response
|
| 842 |
-
response_content = str(result)
|
| 843 |
-
print(f"β
Debug: Returning agent result ({len(response_content)} chars)")
|
| 844 |
-
return response_content
|
| 845 |
|
| 846 |
except Exception as e:
|
| 847 |
execution_time = time.time() - start_time
|
|
|
|
| 820 |
print(f"π Debug: Agent type: {type(self.agent)}")
|
| 821 |
# Skip tools debug - ReActAgent doesn't expose tools attribute
|
| 822 |
|
| 823 |
+
# Handle both local (0.12.x with .chat) and HuggingFace (0.14.x with .run) versions
|
|
|
|
| 824 |
import time
|
| 825 |
+
import asyncio
|
| 826 |
start_time = time.time()
|
| 827 |
print(f"π Debug: Starting agent execution at {start_time}")
|
| 828 |
|
| 829 |
try:
|
| 830 |
+
# Check which method is available
|
| 831 |
+
if hasattr(self.agent, 'chat'):
|
| 832 |
+
print("π Debug: Using .chat() method (LlamaIndex 0.12.x)")
|
| 833 |
+
result = self.agent.chat(message)
|
| 834 |
+
response_content = str(result)
|
| 835 |
+
execution_time = time.time() - start_time
|
| 836 |
+
print(f"β
Debug: .chat() completed in {execution_time:.2f} seconds")
|
| 837 |
+
return response_content
|
| 838 |
+
|
| 839 |
+
elif hasattr(self.agent, 'run'):
|
| 840 |
+
print("π Debug: Using .run() method (LlamaIndex 0.14.x) - returns WorkflowHandler")
|
| 841 |
+
|
| 842 |
+
# Use async approach for WorkflowHandler
|
| 843 |
+
async def get_workflow_result():
|
| 844 |
+
workflow_handler = self.agent.run(user_msg=message, max_iterations=15)
|
| 845 |
+
print(f"π Debug: WorkflowHandler type: {type(workflow_handler)}")
|
| 846 |
+
|
| 847 |
+
# Use await handler pattern from docs
|
| 848 |
+
print("π Debug: Awaiting final response from WorkflowHandler")
|
| 849 |
+
final_response = await workflow_handler
|
| 850 |
+
print(f"π Debug: Final response type: {type(final_response)}")
|
| 851 |
+
|
| 852 |
+
# Extract response based on response format
|
| 853 |
+
if isinstance(final_response, dict) and "response" in final_response:
|
| 854 |
+
return final_response["response"]
|
| 855 |
+
elif hasattr(final_response, 'response'):
|
| 856 |
+
return str(final_response.response)
|
| 857 |
+
else:
|
| 858 |
+
return str(final_response)
|
| 859 |
|
| 860 |
+
# Run async function
|
| 861 |
+
try:
|
| 862 |
+
# Check if we're already in an event loop
|
| 863 |
+
loop = asyncio.get_running_loop()
|
| 864 |
+
# If in a loop, use a thread to run new event loop
|
| 865 |
+
import concurrent.futures
|
| 866 |
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
| 867 |
+
future = executor.submit(lambda: asyncio.run(get_workflow_result()))
|
| 868 |
+
response_content = future.result(timeout=60)
|
| 869 |
+
except RuntimeError:
|
| 870 |
+
# No event loop, can use asyncio.run directly
|
| 871 |
+
response_content = asyncio.run(get_workflow_result())
|
| 872 |
+
|
| 873 |
+
execution_time = time.time() - start_time
|
| 874 |
+
print(f"β
Debug: WorkflowHandler completed in {execution_time:.2f} seconds")
|
| 875 |
+
return response_content
|
| 876 |
|
| 877 |
+
else:
|
| 878 |
+
print("β Debug: Agent has neither .chat() nor .run() method")
|
| 879 |
+
return "I'm having trouble with the agent configuration. Please try again."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 880 |
|
| 881 |
except Exception as e:
|
| 882 |
execution_time = time.time() - start_time
|
debug_version.py
CHANGED
|
@@ -38,6 +38,88 @@ def check_react_agent_api():
|
|
| 38 |
except Exception as e:
|
| 39 |
print(f"Error checking ReActAgent API: {e}")
|
| 40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
if __name__ == "__main__":
|
| 42 |
check_llama_index_version()
|
| 43 |
-
check_react_agent_api()
|
|
|
|
|
|
| 38 |
except Exception as e:
|
| 39 |
print(f"Error checking ReActAgent API: {e}")
|
| 40 |
|
| 41 |
+
def test_workflow_handler():
|
| 42 |
+
"""Test what WorkflowHandler actually returns and what methods it has."""
|
| 43 |
+
try:
|
| 44 |
+
print("\n=== WORKFLOW HANDLER TEST ===")
|
| 45 |
+
|
| 46 |
+
# Import what we need
|
| 47 |
+
from llama_index.core.agent import ReActAgent
|
| 48 |
+
from llama_index.core.tools import BaseTool, FunctionTool
|
| 49 |
+
from llama_index.core.llms.mock import MockLLM
|
| 50 |
+
import inspect
|
| 51 |
+
|
| 52 |
+
# Create a simple mock tool
|
| 53 |
+
def mock_tool(query: str) -> str:
|
| 54 |
+
"""A simple mock tool."""
|
| 55 |
+
return f"Mock response for: {query}"
|
| 56 |
+
|
| 57 |
+
tool = FunctionTool.from_defaults(fn=mock_tool, name="mock_tool")
|
| 58 |
+
|
| 59 |
+
# Create a mock LLM
|
| 60 |
+
llm = MockLLM(max_tokens=100)
|
| 61 |
+
|
| 62 |
+
# Create ReActAgent
|
| 63 |
+
agent = ReActAgent(tools=[tool], llm=llm, verbose=True)
|
| 64 |
+
print(f"β
Created ReActAgent successfully")
|
| 65 |
+
|
| 66 |
+
# Test the run method
|
| 67 |
+
print("π Testing agent.run()...")
|
| 68 |
+
workflow_handler = agent.run(user_msg="Hello test")
|
| 69 |
+
|
| 70 |
+
print(f"π WorkflowHandler type: {type(workflow_handler)}")
|
| 71 |
+
print(f"π WorkflowHandler module: {type(workflow_handler).__module__}")
|
| 72 |
+
|
| 73 |
+
# Check WorkflowHandler methods
|
| 74 |
+
wh_methods = [m for m in dir(workflow_handler) if not m.startswith('_')]
|
| 75 |
+
print(f"π WorkflowHandler methods: {sorted(wh_methods)}")
|
| 76 |
+
|
| 77 |
+
# Check for specific methods we're interested in
|
| 78 |
+
for method_name in ['result', 'get_result', 'run', '__iter__', '__next__', 'wait', 'done']:
|
| 79 |
+
if hasattr(workflow_handler, method_name):
|
| 80 |
+
method = getattr(workflow_handler, method_name)
|
| 81 |
+
if callable(method):
|
| 82 |
+
try:
|
| 83 |
+
sig = inspect.signature(method)
|
| 84 |
+
is_async = inspect.iscoroutinefunction(method)
|
| 85 |
+
print(f"β
{method_name}: exists, callable, async={is_async}, sig={sig}")
|
| 86 |
+
except:
|
| 87 |
+
print(f"β
{method_name}: exists, callable (signature unavailable)")
|
| 88 |
+
else:
|
| 89 |
+
print(f"β
{method_name}: exists, not callable, value={method}")
|
| 90 |
+
else:
|
| 91 |
+
print(f"β {method_name}: NOT FOUND")
|
| 92 |
+
|
| 93 |
+
# Test iteration
|
| 94 |
+
print("\nπ Testing iteration...")
|
| 95 |
+
try:
|
| 96 |
+
step_count = 0
|
| 97 |
+
for step in workflow_handler:
|
| 98 |
+
step_count += 1
|
| 99 |
+
print(f" Step {step_count}: {type(step)} = {str(step)[:100]}...")
|
| 100 |
+
if step_count >= 3: # Limit to avoid infinite loops
|
| 101 |
+
break
|
| 102 |
+
print(f"β
Iteration completed with {step_count} steps")
|
| 103 |
+
except Exception as e:
|
| 104 |
+
print(f"β Iteration failed: {e}")
|
| 105 |
+
|
| 106 |
+
# Test result() method if it exists
|
| 107 |
+
print("\nπ Testing .result() method...")
|
| 108 |
+
try:
|
| 109 |
+
if hasattr(workflow_handler, 'result'):
|
| 110 |
+
result = workflow_handler.result()
|
| 111 |
+
print(f"β
.result() returned: {type(result)} = {str(result)[:100]}...")
|
| 112 |
+
else:
|
| 113 |
+
print("β No .result() method")
|
| 114 |
+
except Exception as e:
|
| 115 |
+
print(f"β .result() failed: {e}")
|
| 116 |
+
|
| 117 |
+
except Exception as e:
|
| 118 |
+
print(f"β WorkflowHandler test failed: {e}")
|
| 119 |
+
import traceback
|
| 120 |
+
traceback.print_exc()
|
| 121 |
+
|
| 122 |
if __name__ == "__main__":
|
| 123 |
check_llama_index_version()
|
| 124 |
+
check_react_agent_api()
|
| 125 |
+
test_workflow_handler()
|
pyproject.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
[tool.poetry]
|
| 2 |
name = "voicecal-ai"
|
| 3 |
-
version = "1.0.
|
| 4 |
description = "A friendly AI chatbot for booking Google Calendar appointments"
|
| 5 |
authors = ["Peter <pgits.job@gmail.com>"]
|
| 6 |
|
|
|
|
| 1 |
[tool.poetry]
|
| 2 |
name = "voicecal-ai"
|
| 3 |
+
version = "1.0.11"
|
| 4 |
description = "A friendly AI chatbot for booking Google Calendar appointments"
|
| 5 |
authors = ["Peter <pgits.job@gmail.com>"]
|
| 6 |
|