4a5695ed9c
Расширяем просмотр документа, чтобы оператор видел не только текстовые чанки, но и как они лежат в ChromaDB в виде векторов — по паттерну из work-pcs-dr-cdss. Backend: - services/vectorstore.get_document_chunks теперь запрашивает include=["embeddings"] и отдаёт вектор как list[float]. Chroma возвращает numpy-массивы, поэтому проверка наличия embeddings сделана через len(), без or-шортката. - models.ChunkDetail: поля embedding: list[float] + embedding_dim: int. - routers/documents прокидывает вектор и размерность в ответ. Frontend (static/index.html): - В карточку чанка добавлен блок .chunk-card-actions с кнопкой «вектор (N dim)»; раскрывается в .embedding-box с полным списком координат (округление до 6 знаков, моноширинный шрифт, скролл). - Функция toggleChunkText переписана через .closest + querySelector, чтобы не ломаться от новой обёртки кнопок. - Добавлена toggleEmb(embId). Проверено на загруженных документах — возвращается по 1024 координаты (E5-large), совпадает с ожиданиями embedding-модели. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
80 lines
1.6 KiB
Python
80 lines
1.6 KiB
Python
from pydantic import BaseModel, Field
|
|
|
|
|
|
class DocumentInfo(BaseModel):
|
|
document_id: str
|
|
name: str
|
|
chunks_count: int
|
|
file_type: str
|
|
created_at: str
|
|
metadata: dict = Field(default_factory=dict)
|
|
|
|
|
|
class ChunkPreview(BaseModel):
|
|
index: int
|
|
section: str = ""
|
|
page_number: int = 0
|
|
text_preview: str = ""
|
|
char_length: int = 0
|
|
|
|
|
|
class DocumentUploadResponse(BaseModel):
|
|
document_id: str
|
|
name: str
|
|
chunks_count: int
|
|
status: str = "indexed"
|
|
created_at: str
|
|
chunks_preview: list[ChunkPreview] = Field(default_factory=list)
|
|
|
|
|
|
class DocumentListResponse(BaseModel):
|
|
documents: list[DocumentInfo]
|
|
total: int
|
|
|
|
|
|
class ChunkDetail(BaseModel):
|
|
index: int
|
|
section: str = ""
|
|
page_number: int = 0
|
|
text: str = ""
|
|
char_length: int = 0
|
|
embedding: list[float] = Field(default_factory=list)
|
|
embedding_dim: int = 0
|
|
|
|
|
|
class DocumentChunksResponse(BaseModel):
|
|
document_id: str
|
|
name: str
|
|
file_type: str
|
|
chunks_count: int
|
|
chunks: list[ChunkDetail] = Field(default_factory=list)
|
|
|
|
|
|
class DocumentDeleteResponse(BaseModel):
|
|
ok: bool = True
|
|
deleted_chunks: int
|
|
|
|
|
|
class SourceInfo(BaseModel):
|
|
document_id: str
|
|
document_name: str
|
|
chunk_text: str
|
|
section: str = ""
|
|
page: int = 0
|
|
relevance_score: float = 0.0
|
|
|
|
|
|
class QueryResponse(BaseModel):
|
|
answer: str
|
|
sources: list[SourceInfo]
|
|
model_used: str
|
|
assembled_prompt: str = ""
|
|
|
|
|
|
class HealthResponse(BaseModel):
|
|
status: str = "ok"
|
|
chromadb: str
|
|
embedding_model: str
|
|
documents_count: int
|
|
chunks_count: int
|