- A1: fire the hard filter (Apify is precise); embedding vibe-ranker (embed.py) blends with the floor-free white-box (rank.py) to sift ~90 -> top 18 - A2: Opus curator (curate.py) reads the 18 -> honest <=count + Gemini-voiced report cards; graceful fallback to the white-box + templated cards - LLM via opencode.ai/zen gateway (llm.py): Opus chat + direct-OpenAI embeddings - Run LLM work off the event loop (asyncio.to_thread) so the Redis response publishes - C1: dedicated Postgres (app/db/) persists the per-user feed; get_scout_feed replays it so matches survive navigation/refresh - match contract + report-card fields (schema.py); skills.py; tests/
54 lines
1.5 KiB
Python
54 lines
1.5 KiB
Python
"""matchmaking-v2 — FastAPI app (course-service mold).
|
|
|
|
Serves: the agent card (discovery), /a2a/tasks (orchestrator entry), /api/v1/health.
|
|
On-demand by design — no corpus DB, no nightly ingestion.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
from app.adk.worker import RedisStreamWorker
|
|
from app.api.v1 import router as api_router
|
|
from app.a2a.card import router as a2a_card_router
|
|
from app.a2a.tasks import router as a2a_tasks_router
|
|
from app.config import get_settings
|
|
|
|
logging.basicConfig(level=get_settings().LOG_LEVEL)
|
|
|
|
_settings = get_settings()
|
|
_worker = RedisStreamWorker(redis_url=_settings.ORCHESTRATOR_REDIS_URL or _settings.REDIS_URL)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(_: FastAPI):
|
|
from app.db.repo import init_db
|
|
await init_db() # create the feed table if DATABASE_URL is set (best-effort)
|
|
await _worker.start()
|
|
try:
|
|
yield
|
|
finally:
|
|
await _worker.stop()
|
|
|
|
|
|
def create_app() -> FastAPI:
|
|
s = get_settings()
|
|
app = FastAPI(title="Matchmaking v2", version="2.0.0", lifespan=lifespan)
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=s.cors_origins_list,
|
|
allow_credentials=s.cors_origins_list != ["*"],
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
app.include_router(api_router, prefix=s.API_PREFIX)
|
|
app.include_router(a2a_card_router)
|
|
app.include_router(a2a_tasks_router)
|
|
return app
|
|
|
|
|
|
app = create_app()
|