fixed issues history

This commit is contained in:
OwusuBlessing
2025-08-12 19:32:39 +01:00
parent 1905492f93
commit bab442e955
8 changed files with 94 additions and 8 deletions
Binary file not shown.
Binary file not shown.
+52 -3
View File
@@ -7,7 +7,7 @@ from api.dependencies.auth import get_api_key
from src.llm.orchestrator import DroneBot, Message # Adjust import as needed from src.llm.orchestrator import DroneBot, Message # Adjust import as needed
from src.llm.agent.flight_assesment import DroneAssessmentAgent from src.llm.agent.flight_assesment import DroneAssessmentAgent
import json import json
from logger import logger
router = APIRouter( router = APIRouter(
prefix="/chat", prefix="/chat",
tags=["chat"] tags=["chat"]
@@ -20,19 +20,68 @@ async def chat_ai(
): ):
"""Chat with DroneBot using query and history.""" """Chat with DroneBot using query and history."""
try: try:
logger.info(f"Starting chat request with query: {request.query}")
logger.info(f"History length: {len(request.history)}")
# Convert to internal Message format # Convert to internal Message format
history = [Message(role=msg.role, content=msg.content) for msg in request.history] history = [Message(role=msg.role, content=msg.content) for msg in request.history]
logger.info(f"Converted history to internal format: {len(history)} messages")
# Initialize DroneBot with history # Initialize DroneBot with history
logger.info("Initializing DroneBot...")
bot = DroneBot(history=history, use_openai_as_fallback=True) bot = DroneBot(history=history, use_openai_as_fallback=True)
logger.info("DroneBot initialized successfully")
# Get response from DroneBot
logger.info("Calling DroneBot.chat()...")
result = bot.chat(request.query) result = bot.chat(request.query)
message = json.loads(result["final_message"]) logger.info(f"DroneBot response received: {result}")
print(result)
# Validate result and final_message
if not result or "final_message" not in result:
logger.error(f"Invalid result from DroneBot: {result}")
raise HTTPException(
status_code=500,
detail="Invalid response from DroneBot: missing final_message"
)
final_message = result["final_message"]
logger.info(f"Final message extracted: {final_message}")
if not final_message or not isinstance(final_message, str):
logger.error(f"Final message is not a valid string: {type(final_message)} - {final_message}")
raise HTTPException(
status_code=500,
detail="Invalid response from DroneBot: final_message is not a valid string"
)
try:
logger.info("Attempting to parse final_message as JSON...")
message = json.loads(final_message)
logger.info("JSON parsing successful")
except json.JSONDecodeError as json_error:
logger.warning(f"JSON decode error: {json_error}")
logger.warning(f"Raw final_message: {final_message}")
# If JSON parsing fails, create a fallback structure
message = {
"message": final_message,
"options": None,
"requires_selection": False,
"end": "in_progress",
"form": {}
}
logger.info("Created fallback message structure")
logger.info(f"Final message to return: {message}")
return ChatResponse( return ChatResponse(
status="success", status="success",
message=message message=message
) )
except HTTPException:
logger.error("Re-raising HTTPException")
raise
except Exception as e: except Exception as e:
logger.error(f"Unexpected error in chat_ai: {str(e)}", exc_info=True)
raise HTTPException( raise HTTPException(
status_code=500, status_code=500,
detail=str(e) detail=str(e)
+1 -1
View File
@@ -37,4 +37,4 @@ async def root():
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn
uvicorn.run(app, host="0.0.0.0", port=5340) uvicorn.run(app, host="0.0.0.0", port=5120)
Binary file not shown.
+23 -2
View File
@@ -169,13 +169,31 @@ class DroneBot:
try: try:
# Case 1: Response has direct string content # Case 1: Response has direct string content
if hasattr(response, 'content') and isinstance(response.content, str) and response.content.strip(): if hasattr(response, 'content') and isinstance(response.content, str) and response.content.strip():
return response.content.strip() content = response.content.strip()
# Check if the content is valid JSON
try:
json_content = json.loads(content)
# If it's valid JSON, return the message field or the entire JSON
if isinstance(json_content, dict) and "message" in json_content:
return content # Return the full JSON string
else:
return content # Return the JSON string even if no message field
except json.JSONDecodeError:
# Not JSON, return as plain text
return content
# Case 2: Response has list content (complex format) # Case 2: Response has list content (complex format)
elif hasattr(response, 'content') and isinstance(response.content, list): elif hasattr(response, 'content') and isinstance(response.content, list):
for item in response.content: for item in response.content:
if isinstance(item, dict) and item.get('type') == 'text' and item.get('text'): if isinstance(item, dict) and item.get('type') == 'text' and item.get('text'):
return item['text'].strip() text_content = item['text'].strip()
# Check if it's JSON
try:
json.loads(text_content)
return text_content # Return JSON string
except json.JSONDecodeError:
return text_content # Return plain text
# Case 3: Response only has tool calls, no text content # Case 3: Response only has tool calls, no text content
elif hasattr(response, 'tool_calls') and response.tool_calls: elif hasattr(response, 'tool_calls') and response.tool_calls:
@@ -228,11 +246,14 @@ class DroneBot:
response = llm_with_tools.invoke(messages) response = llm_with_tools.invoke(messages)
print(f"DroneBot response: {type(response).__name__}") print(f"DroneBot response: {type(response).__name__}")
print(f"Response content type: {type(response.content)}")
print(f"Response content: {response.content}")
if hasattr(response, 'tool_calls'): if hasattr(response, 'tool_calls'):
print(f" Tool calls: {len(response.tool_calls) if response.tool_calls else 0}") print(f" Tool calls: {len(response.tool_calls) if response.tool_calls else 0}")
# Extract and store the final message content # Extract and store the final message content
final_message_content = self._extract_final_message_content(response) final_message_content = self._extract_final_message_content(response)
print(f"Extracted final message: {final_message_content}")
self.final_message = final_message_content self.final_message = final_message_content
# Update state # Update state
+18 -2
View File
@@ -2,6 +2,22 @@ def get_booking_prompt():
return f""" return f"""
## CRITICAL INSTRUCTION - YOU MUST FOLLOW THIS EXACTLY
**YOU MUST ALWAYS RESPOND WITH VALID JSON ONLY. NO OTHER TEXT, NO EXPLANATIONS, NO MARKDOWN FORMATTING.**
**EVERY SINGLE RESPONSE MUST BE A VALID JSON OBJECT WITH THIS EXACT STRUCTURE:**
{{
"message": "Your conversational response to the user",
"options": ["Option 1", "Option 2", "Option 3"] or null,
"requires_selection": true/false,
"end": "complete" | "in_progress" | "cancelled",
"form": {{}}
}}
**DO NOT ADD ANYTHING BEFORE OR AFTER THE JSON. NO ```json, NO ```, NO EXPLANATIONS.**
## System Instructions & Persona ## System Instructions & Persona
You are DroneBot, a professional and knowledgeable drone survey booking assistant working for a leading renewable energy inspection company. You have extensive experience in the renewable energy sector and understand the critical importance of regular asset inspections for solar farms, wind turbines, and other renewable energy installations. You are DroneBot, a professional and knowledgeable drone survey booking assistant working for a leading renewable energy inspection company. You have extensive experience in the renewable energy sector and understand the critical importance of regular asset inspections for solar farms, wind turbines, and other renewable energy installations.
@@ -16,7 +32,7 @@ Your primary function is to guide users through a comprehensive booking process,
You MUST ALWAYS respond with a structured JSON object containing exactly these fields: You MUST ALWAYS respond with a structured JSON object containing exactly these fields:
```json
{{ {{
"message": "Your conversational response to the user", "message": "Your conversational response to the user",
"options": ["Option 1", "Option 2", "Option 3"] or null, "options": ["Option 1", "Option 2", "Option 3"] or null,
@@ -24,7 +40,7 @@ You MUST ALWAYS respond with a structured JSON object containing exactly these f
"end": "complete" | "in_progress" | "cancelled", "end": "complete" | "in_progress" | "cancelled",
"form": {{}} "form": {{}}
}} }}
```
**Field Explanations:** **Field Explanations:**
- **message**: Your conversational response (friendly, professional tone) - **message**: Your conversational response (friendly, professional tone)