Backend:
- Fix TicketInput ticket_id type (int|str -> str) — Pydantic 500 on numeric IDs
- Fix LLM module: add missing logger import, handle 429 and non-200 responses
- Switch LLM model to poolside/laguna-m.1:free (avoid OpenRouter rate limits)
- Add GET /api/collections/{id} endpoint to fetch single collection
- Deduplicate tickets: replace randomized hash() with deterministic
hashlib.md5 for Qdrant point IDs
- Add get_existing_ticket_ids() — scroll Qdrant before processing,
skip already-imported tickets, avoid redundant embeddings
- Multi-tenant isolation: tenant_id + collection_id in all Qdrant filters
- Fix embedding: drop incompatible openai SDK, use raw httpx
- Fix reranking: access ScoredPoint.payload via .get(), not []
- Fix chunking: expand role detection (support/operator/agent + client/user/customer)
- Fix bcrypt: downgrade to 4.0.1 (incompatible 5.x with passlib)
Frontend:
- Register: add plan selection (free/starter/pro)
- CollectionView: fetch ticket_count from backend on mount
(not only from upload response — survived page refresh)
- uploadFile: use getToken() instead of stale module-level var,
show real HTTP status in error messages
- Nginx: increase client_max_body_size to 50M for file uploads
47 lines
1.2 KiB
Python
47 lines
1.2 KiB
Python
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
from app.config import settings
|
|
from app.database import engine
|
|
from app.models.base import Base
|
|
from app.routers import auth, tickets, search
|
|
from app.middleware import RateLimitMiddleware
|
|
from app.metrics import MetricsMiddleware, metrics_endpoint
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
async with engine.begin() as conn:
|
|
await conn.run_sync(Base.metadata.create_all)
|
|
yield
|
|
|
|
|
|
app = FastAPI(title=settings.app_name, version="0.1.0", lifespan=lifespan)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=[
|
|
"https://sovet.itoservice.ru",
|
|
"https://api.sovet.itoservice.ru",
|
|
"http://sovet.itoservice.ru",
|
|
"http://api.sovet.itoservice.ru",
|
|
],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
app.add_middleware(MetricsMiddleware)
|
|
app.add_middleware(RateLimitMiddleware, requests_per_minute=30)
|
|
|
|
app.include_router(auth.router)
|
|
app.include_router(tickets.router)
|
|
app.include_router(search.router)
|
|
|
|
app.add_route("/api/metrics", metrics_endpoint, methods=["GET"])
|
|
|
|
|
|
@app.get("/api/health")
|
|
async def health():
|
|
return {"status": "ok"}
|