TSNLWeb / src /nlw_codex /models.py
rvguha's picture
Deploy tsnlweb
c7cea55 verified
Raw History Blame Contribute Delete
2.85 kB
from __future__ import annotations
import json
import uuid
from dataclasses import dataclass, field
from datetime import UTC, datetime
from enum import StrEnum
from typing import Any
class Mode(StrEnum):
LIST = "list"
SUMMARIZE = "summarize"
GENERATE = "generate"
# What /ask and the MCP `ask` tool do when the caller names no mode: ranked
# results under a short overview of them. SearchRequest itself still defaults
# to LIST, so code that builds one directly opts in to the extra model call.
DEFAULT_MODE = Mode.SUMMARIZE
@dataclass(slots=True)
class SearchRequest:
query: str
site: str | None = None
mode: Mode = Mode.LIST
previous_queries: tuple[str, ...] = ()
max_results: int = 10
min_score: int = 70
canonical_query: str | None = None
retrieval: str = "compare"
ranking_model: str | None = None
@property
def effective_query(self) -> str:
return self.canonical_query or self.query
@dataclass(frozen=True, slots=True)
class Document:
id: str
url: str
name: str
site: str
text: str
schema_object: dict[str, Any]
@dataclass(frozen=True, slots=True)
class Candidate:
document: Document
vector_score: float | None
bm25_score: float | None
retrieval_score: float
retrieval_source: str
@property
def similarity(self) -> float:
return self.vector_score or 0.0
@dataclass(frozen=True, slots=True)
class Result:
document: Document
score: int
description: str
vector_score: float | None = None
bm25_score: float | None = None
retrieval_source: str | None = None
relevance: str = "relevant"
def wire(self) -> dict[str, Any]:
return {
"@type": "Item",
"url": self.document.url,
"name": self.document.name,
"site": self.document.site,
"score": self.score,
"relevance": self.relevance,
"description": self.description,
"vector_score": self.vector_score,
"bm25_score": self.bm25_score,
"retrieval_source": self.retrieval_source,
"schema_object": self.document.schema_object,
}
@dataclass(slots=True)
class Event:
type: str
data: Any = None
query_id: str = ""
sequence: int = 0
timestamp: str = field(default_factory=lambda: datetime.now(UTC).isoformat())
event_id: str = field(default_factory=lambda: str(uuid.uuid4()))
def wire(self) -> dict[str, Any]:
return {
"message_id": self.event_id,
"message_type": self.type,
"query_id": self.query_id,
"sequence": self.sequence,
"timestamp": self.timestamp,
"content": self.data,
}
def json(self) -> str:
return json.dumps(self.wire(), separators=(",", ":"))