Spaces:
Running
Running
add followup-agent
Browse files
main.py
CHANGED
@@ -377,6 +377,95 @@ async def search_assistant(query: SearchQueryModel, api_key: str = Depends(verif
|
|
377 |
|
378 |
return StreamingResponse(process_response(), media_type="text/event-stream")
|
379 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
380 |
if __name__ == "__main__":
|
381 |
import uvicorn
|
382 |
logger.info("Starting the application")
|
|
|
377 |
|
378 |
return StreamingResponse(process_response(), media_type="text/event-stream")
|
379 |
|
380 |
+
|
381 |
+
from pydantic import BaseModel, Field
|
382 |
+
import yaml
|
383 |
+
import json
|
384 |
+
|
385 |
+
class FollowupQueryModel(BaseModel):
|
386 |
+
query: str = Field(..., description="User's query for the followup agent")
|
387 |
+
model_id: ModelID = Field(
|
388 |
+
default="openai/gpt-4o-mini",
|
389 |
+
description="ID of the model to use for response generation"
|
390 |
+
)
|
391 |
+
conversation_id: str = Field(default_factory=lambda: str(uuid4()), description="Unique identifier for the conversation")
|
392 |
+
user_id: str = Field(..., description="Unique identifier for the user")
|
393 |
+
|
394 |
+
class Config:
|
395 |
+
schema_extra = {
|
396 |
+
"example": {
|
397 |
+
"query": "How can I improve my productivity?",
|
398 |
+
"model_id": "openai/gpt-4o-mini",
|
399 |
+
"conversation_id": "123e4567-e89b-12d3-a456-426614174000",
|
400 |
+
"user_id": "user123"
|
401 |
+
}
|
402 |
+
}
|
403 |
+
|
404 |
+
FOLLOWUP_AGENT_PROMPT = """
|
405 |
+
You are a helpful assistant with the following skills, use them, as necessary. If the user request needs further clarification, analyze it and generate clarifying questions with options. Else respond with a helpful answer. <response>response to user request in markdown</response> <clarification> questions: - text: [First clarifying question] options: - [Option 1] - [Option 2] - [Option 3] - [Option 4 (if needed)] - text: [Second clarifying question] options: - [Option 1] - [Option 2] - [Option 3] # Add more questions as needed # make sure this section is in valid YAML format </clarification>
|
406 |
+
"""
|
407 |
+
|
408 |
+
def parse_followup_response(response):
|
409 |
+
response_parts = response.split("<response>")
|
410 |
+
if len(response_parts) > 1:
|
411 |
+
response_content = response_parts[1].split("</response>")[0].strip()
|
412 |
+
else:
|
413 |
+
response_content = ""
|
414 |
+
|
415 |
+
clarification_parts = response.split("<clarification>")
|
416 |
+
if len(clarification_parts) > 1:
|
417 |
+
clarification_yaml = clarification_parts[1].split("</clarification>")[0].strip()
|
418 |
+
try:
|
419 |
+
clarification = yaml.safe_load(clarification_yaml)
|
420 |
+
except yaml.YAMLError:
|
421 |
+
clarification = None
|
422 |
+
else:
|
423 |
+
clarification = None
|
424 |
+
|
425 |
+
return response_content, clarification
|
426 |
+
|
427 |
+
@app.post("/followup-agent")
|
428 |
+
async def followup_agent(query: FollowupQueryModel, background_tasks: BackgroundTasks, api_key: str = Depends(verify_api_key)):
|
429 |
+
"""
|
430 |
+
Followup agent endpoint that provides helpful responses or generates clarifying questions based on user queries.
|
431 |
+
Requires API Key authentication via X-API-Key header.
|
432 |
+
"""
|
433 |
+
logger.info(f"Received followup agent query: {query.query}")
|
434 |
+
|
435 |
+
if query.conversation_id not in conversations:
|
436 |
+
conversations[query.conversation_id] = [
|
437 |
+
{"role": "system", "content": FOLLOWUP_AGENT_PROMPT}
|
438 |
+
]
|
439 |
+
|
440 |
+
conversations[query.conversation_id].append({"role": "user", "content": query.query})
|
441 |
+
last_activity[query.conversation_id] = time.time()
|
442 |
+
|
443 |
+
# Limit tokens in the conversation history
|
444 |
+
limited_conversation = conversations[query.conversation_id]
|
445 |
+
|
446 |
+
def process_response():
|
447 |
+
full_response = ""
|
448 |
+
for content in chat_with_llama_stream(limited_conversation, model=query.model_id):
|
449 |
+
full_response += content
|
450 |
+
yield content
|
451 |
+
|
452 |
+
response_content, clarification = parse_followup_response(full_response)
|
453 |
+
|
454 |
+
result = {
|
455 |
+
"response": response_content,
|
456 |
+
"clarification": clarification
|
457 |
+
}
|
458 |
+
|
459 |
+
yield "\n\n" + json.dumps(result)
|
460 |
+
|
461 |
+
# Add the assistant's response to the conversation history
|
462 |
+
conversations[query.conversation_id].append({"role": "assistant", "content": full_response})
|
463 |
+
|
464 |
+
background_tasks.add_task(update_db, query.user_id, query.conversation_id, query.query, full_response)
|
465 |
+
logger.info(f"Completed followup agent response for query: {query.query}")
|
466 |
+
|
467 |
+
return StreamingResponse(process_response(), media_type="text/event-stream")
|
468 |
+
|
469 |
if __name__ == "__main__":
|
470 |
import uvicorn
|
471 |
logger.info("Starting the application")
|