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
21 lines
629 B
Python
21 lines
629 B
Python
from qdrant_client.models import ScoredPoint
|
|
|
|
|
|
def rerank(query: str, results: list[ScoredPoint], k: int = 5) -> list[dict]:
|
|
if not results:
|
|
return []
|
|
|
|
def get_payload(p: ScoredPoint, key: str, default=""):
|
|
return (p.payload or {}).get(key, default)
|
|
|
|
scored = []
|
|
for r in results:
|
|
scored.append({
|
|
"ticket_id": get_payload(r, "ticket_id"),
|
|
"score": float(r.score or 0),
|
|
"full_text": get_payload(r, "full_text"),
|
|
"category": get_payload(r, "category"),
|
|
})
|
|
|
|
scored.sort(key=lambda x: x["score"], reverse=True)
|
|
return scored[:k]
|