- Frontend: Vite + React + TypeScript chat interface - Backend: FastAPI gateway with LangGraph routing - Knowledge Service: ChromaDB RAG with Gitea scraper - LangGraph Service: Multi-agent orchestration - Airflow: Scheduled Gitea ingestion DAG - Documentation: Complete plan and implementation guides Architecture: - Modular Docker Compose per service - External ai-mesh network for communication - Fast rebuilds with /app/packages pattern - Intelligent agent routing (no hardcoded keywords) Services: - Frontend (5173): React chat UI - Chat Gateway (8000): FastAPI entry point - LangGraph (8090): Agent orchestration - Knowledge (8080): ChromaDB RAG - Airflow (8081): Scheduled ingestion - PostgreSQL (5432): Chat history Excludes: node_modules, .venv, chroma_db, logs, .env files Includes: All source code, configs, docs, docker files
50 lines
1.8 KiB
Plaintext
50 lines
1.8 KiB
Plaintext
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from pydantic import BaseModel
|
|
import httpx
|
|
import logging
|
|
import sys
|
|
import traceback
|
|
import os
|
|
|
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s", handlers=[logging.StreamHandler(sys.stdout)])
|
|
logger = logging.getLogger(__name__)
|
|
|
|
app = FastAPI()
|
|
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])
|
|
|
|
class MessageRequest(BaseModel):
|
|
message: str
|
|
|
|
LANGGRAPH_URL = os.getenv("LANGGRAPH_URL", "http://langgraph-service:8090")
|
|
|
|
@app.post("/chat")
|
|
async def chat(request: MessageRequest):
|
|
"""Updated chat endpoint that routes through LangGraph Supervisor."""
|
|
logger.info(f"Gateway: Received message: {request.message}")
|
|
|
|
try:
|
|
# Call LangGraph Supervisor instead of direct brain
|
|
async with httpx.AsyncClient(timeout=httpx.Timeout(60.0, connect=10.0)) as client:
|
|
response = await client.post(
|
|
f"{LANGGRAPH_URL}/query",
|
|
json={"query": request.message}
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
result = response.json()
|
|
logger.info(f"Gateway: Response from {result.get('agent_used', 'unknown')} agent")
|
|
return {"response": result["response"]}
|
|
else:
|
|
logger.error(f"Gateway: LangGraph error {response.status_code}")
|
|
return {"response": "Error: Orchestration service unavailable"}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Gateway: Error routing through LangGraph: {traceback.format_exc()}")
|
|
return {"response": "Error: Unable to process your request at this time."}
|
|
|
|
@app.get("/health")
|
|
async def health():
|
|
return {"status": "healthy", "service": "chat-gateway"}
|
|
|