mindnet/app/models/dto.py
Lars 5755eb1f08
All checks were successful
Deploy mindnet to llm-node / deploy (push) Successful in 3s
app/models/dto.py hinzugefügt
2025-10-07 11:03:16 +02:00

95 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
app/models/dto.py — Pydantic-Modelle (DTOs) für WP-04 Endpunkte
Zweck:
Laufzeit-Modelle für FastAPI (Requests/Responses), getrennt von JSON-Schemas.
Deckt die Graph-/Retriever-Endpunkte ab, ohne bestehende Funktionen zu ändern.
Kompatibilität:
Python 3.12+, Pydantic 2.x, FastAPI 0.110+
Version:
0.1.0 (Erstanlage für WP-04)
Stand:
2025-10-07
Bezug:
- schemas/*.json (Speicherschema für Notes/Chunks/Edges)
- WP-04 API-Design (Query- und Graph-Endpunkte)
Nutzung:
from app.models.dto import QueryRequest, QueryResponse, GraphResponse
Änderungsverlauf:
0.1.0 (2025-10-07) Erstanlage.
"""
from __future__ import annotations
from pydantic import BaseModel
from typing import List, Literal, Optional, Dict
EdgeKind = Literal["references", "references_at", "backlink", "next", "prev", "belongs_to"]
class NodeDTO(BaseModel):
"""Darstellung eines Knotens (Note oder Chunk) im API-Graph."""
id: str
type: Literal["note", "chunk"]
title: Optional[str] = None
note_id: Optional[str] = None
tags: Optional[List[str]] = None
in_degree: Optional[int] = None
out_degree: Optional[int] = None
score: Optional[float] = None
section_title: Optional[str] = None
section_path: Optional[str] = None
path: Optional[str] = None
class EdgeDTO(BaseModel):
"""Darstellung einer Kante im API-Graph."""
id: str
kind: EdgeKind
source: str
target: str
weight: float
direction: Literal["out", "in", "undirected"] = "out"
class QueryRequest(BaseModel):
"""
Request für /query:
- mode: 'semantic' | 'edge' | 'hybrid'
- query: (optional) Freitext; Embedding wird später angebunden
- query_vector: (optional) direkter Vektor (384d) für Quick-Tests ohne Embedding
"""
mode: Literal["semantic", "edge", "hybrid"] = "hybrid"
query: Optional[str] = None
query_vector: Optional[List[float]] = None
top_k: int = 10
expand: Dict = {"depth": 1, "edge_types": ["references", "belongs_to", "prev", "next"]}
filters: Optional[Dict] = None
ret: Dict = {"with_paths": True, "with_notes": True, "with_chunks": True}
class QueryHit(BaseModel):
"""Einzelnes Trefferobjekt für /query."""
node_id: str
note_id: Optional[str]
semantic_score: float
edge_bonus: float
centrality_bonus: float
total_score: float
paths: Optional[List[List[Dict]]] = None
source: Optional[Dict] = None
class QueryResponse(BaseModel):
"""Antwortstruktur für /query (Liste von Treffern + Telemetrie)."""
results: List[QueryHit]
used_mode: str
latency_ms: int
class GraphResponse(BaseModel):
"""Antwortstruktur für /graph/{note_id} (Nachbarschaft)."""
center_note_id: str
nodes: List[NodeDTO]
edges: List[EdgeDTO]
stats: Dict[str, int]