Files
microdao-daarion/services/rag-service/app/main.py
Apple 9b86f9a694 feat: implement RAG Service MVP with PARSER + Memory integration
RAG Service Implementation:
- Create rag-service/ with full structure (config, document_store, embedding, pipelines)
- Document Store: PostgreSQL + pgvector via Haystack
- Embedding: BAAI/bge-m3 (multilingual, 1024 dim)
- Ingest Pipeline: Convert ParsedDocument to Haystack Documents, embed, index
- Query Pipeline: Retrieve documents, generate answers via DAGI Router
- FastAPI endpoints: /ingest, /query, /health

Tests:
- Unit tests for ingest and query pipelines
- E2E test with example parsed JSON
- Test fixtures with real PARSER output example

Router Integration:
- Add mode='rag_query' routing rule in router-config.yml
- Priority 7, uses local_qwen3_8b for RAG queries

Docker:
- Add rag-service to docker-compose.yml
- Configure dependencies (router, city-db)
- Add model cache volume

Documentation:
- Complete README with API examples
- Integration guides for PARSER and Router
2025-11-16 04:41:53 -08:00

106 lines
2.6 KiB
Python

"""
RAG Service - FastAPI application
Retrieval-Augmented Generation for MicroDAO
"""
import logging
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from app.models import IngestRequest, IngestResponse, QueryRequest, QueryResponse
from app.ingest_pipeline import ingest_parsed_document
from app.query_pipeline import answer_query
logger = logging.getLogger(__name__)
# FastAPI app
app = FastAPI(
title="RAG Service",
description="Retrieval-Augmented Generation service for MicroDAO",
version="1.0.0"
)
# CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/health")
async def health():
"""Health check endpoint"""
return {
"status": "healthy",
"service": "rag-service",
"version": "1.0.0"
}
@app.post("/ingest", response_model=IngestResponse)
async def ingest_endpoint(request: IngestRequest):
"""
Ingest parsed document from PARSER service into RAG
Body:
- dao_id: DAO identifier
- doc_id: Document identifier
- parsed_json: ParsedDocument JSON from PARSER service
- user_id: Optional user identifier
"""
try:
result = ingest_parsed_document(
dao_id=request.dao_id,
doc_id=request.doc_id,
parsed_json=request.parsed_json,
user_id=request.user_id
)
return IngestResponse(**result)
except Exception as e:
logger.error(f"Ingest endpoint error: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=str(e))
@app.post("/query", response_model=QueryResponse)
async def query_endpoint(request: QueryRequest):
"""
Answer query using RAG pipeline
Body:
- dao_id: DAO identifier
- question: User question
- top_k: Optional number of documents to retrieve
- user_id: Optional user identifier
"""
try:
result = await answer_query(
dao_id=request.dao_id,
question=request.question,
top_k=request.top_k,
user_id=request.user_id
)
return QueryResponse(**result)
except Exception as e:
logger.error(f"Query endpoint error: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
import uvicorn
from app.core.config import settings
uvicorn.run(
"app.main:app",
host=settings.API_HOST,
port=settings.API_PORT,
reload=True
)