| from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks, Request, UploadFile, File, Form, Query |
| from typing import List, Dict, Any, Optional |
|
|
| from ...core.neo4j_store import Neo4jStore |
| from ...retrieval.agent import AgentRetrievalSystem |
| from ...ingestion.pipeline import IngestionPipeline |
| from ...config import settings |
| from ...api.models import * |
| from ...api.auth import get_current_user, User |
| import redis |
| from ..dependencies import get_graph_store, get_retrieval_agent, get_ingestion_pipeline, get_redis_client |
|
|
| router = APIRouter() |
|
|
| from ...core.storage import get_storage |
| storage = get_storage() |
|
|
| @router.get("/api/conversations", response_model=ConversationListResponse, tags=["Memory"]) |
| async def list_conversations(request: Request, current_user: User = Depends(get_current_user)): |
| """List all conversation threads for current user""" |
| query = """ |
| MATCH (u:User {username: $username})-[:HAS_CONVERSATION]->(c:Conversation) |
| RETURN c.id as id, c.title as title, c.created_at as created_at, c.updated_at as updated_at |
| ORDER BY c.updated_at DESC |
| """ |
| results = await request.app.state.graph_store.execute_query(query, {"username": current_user.username}) |
| |
| convs = [] |
| for r in results: |
| convs.append(Conversation( |
| id=r["id"], |
| title=r["title"], |
| created_at=r.get("created_at", datetime.now().isoformat()), |
| updated_at=r.get("updated_at", datetime.now().isoformat()) |
| )) |
| return ConversationListResponse(conversations=convs) |
|
|
|
|
|
|
| @router.get("/api/conversations/{conversation_id}", response_model=Conversation, tags=["Memory"]) |
| async def get_conversation(request: Request, |
| conversation_id: str, |
| current_user: User = Depends(get_current_user) |
| ): |
| """Get a specific conversation thread and its messages""" |
| query = """ |
| MATCH (u:User {username: $username})-[:HAS_CONVERSATION]->(c:Conversation {id: $conversation_id}) |
| OPTIONAL MATCH (c)-[:HAS_MESSAGE]->(m:Message) |
| RETURN c.id as id, c.title as title, c.created_at as created_at, c.updated_at as updated_at, |
| m.id as msg_id, m.role as role, m.content as content, |
| m.reasoning as reasoning_str, m.sources as sources_str, m.created_at as msg_created_at |
| ORDER BY m.created_at ASC |
| """ |
| results = await request.app.state.graph_store.execute_query(query, { |
| "username": current_user.username, |
| "conversation_id": conversation_id |
| }) |
| |
| if not results: |
| raise HTTPException(status_code=404, detail="Conversation not found") |
| |
| c_info = results[0] |
| messages = [] |
| import json |
| for r in results: |
| if r.get("msg_id"): |
| reasoning = json.loads(r["reasoning_str"]) if r.get("reasoning_str") else [] |
| sources = json.loads(r["sources_str"]) if r.get("sources_str") else [] |
| messages.append(Message( |
| id=r["msg_id"], |
| role=r["role"], |
| content=r["content"], |
| reasoning=reasoning, |
| sources=sources, |
| created_at=r.get("msg_created_at", "") |
| )) |
| |
| return Conversation( |
| id=c_info["id"], |
| title=c_info["title"], |
| created_at=c_info.get("created_at", ""), |
| updated_at=c_info.get("updated_at", ""), |
| messages=messages |
| ) |
|
|
|
|
|
|
| @router.delete("/api/conversations/{conversation_id}", tags=["Memory"]) |
| async def delete_conversation(request: Request, |
| conversation_id: str, |
| current_user: User = Depends(get_current_user) |
| ): |
| """Delete a conversation thread""" |
| query = """ |
| MATCH (u:User {username: $username})-[:HAS_CONVERSATION]->(c:Conversation {id: $conversation_id}) |
| OPTIONAL MATCH (c)-[:HAS_MESSAGE]->(m:Message) |
| DETACH DELETE c, m |
| """ |
| await request.app.state.graph_store.execute_query(query, { |
| "username": current_user.username, |
| "conversation_id": conversation_id |
| }) |
| return {"status": "deleted", "conversation_id": conversation_id} |
|
|
|
|
| |
|
|
|
|
|
|