refactor: remove pgvector runtime
This commit is contained in:
@@ -2,9 +2,9 @@ from pathlib import Path
|
||||
|
||||
import typer
|
||||
|
||||
from tht.cli._guards import require_vector_write_allowed
|
||||
from tht.cli.config_cmd import CONFIG_OPT
|
||||
from tht.cli.schema_cmd import _load_config_or_exit
|
||||
from tht.cli._guards import require_vector_write_allowed
|
||||
|
||||
evidence_app = typer.Typer(help="Generazione e gestione delle evidence")
|
||||
|
||||
@@ -56,12 +56,13 @@ def extract_cmd(config: Path = CONFIG_OPT) -> None:
|
||||
|
||||
@evidence_app.command("index")
|
||||
def index_cmd(config: Path = CONFIG_OPT) -> None:
|
||||
"""Embedda e sincronizza su pgvector tutte le evidence presenti in artifacts/."""
|
||||
"""Embedda e sincronizza nel semantic store tutte le evidence presenti in artifacts/."""
|
||||
from tht.adapters.factory import build_vector_store
|
||||
from tht.cli.vector_cmd import (
|
||||
_print_stats,
|
||||
make_embedder,
|
||||
open_store,
|
||||
require_vector_cfg,
|
||||
sync_canonical_records,
|
||||
)
|
||||
from tht.evidence.model import load_evidence_dir
|
||||
from tht.vectorstore.records import evidence_records
|
||||
@@ -71,6 +72,10 @@ def index_cmd(config: Path = CONFIG_OPT) -> None:
|
||||
require_vector_cfg(cfg)
|
||||
docs = load_evidence_dir(evidence_root(cfg))
|
||||
records = evidence_records(docs, cfg.vector.max_chunk_chars)
|
||||
store = open_store(cfg, "evidence")
|
||||
stats = store.sync(records, make_embedder(cfg.embeddings), kinds={"evidence"})
|
||||
stats = sync_canonical_records(
|
||||
"evidence",
|
||||
records,
|
||||
store=build_vector_store(cfg, require_write=True),
|
||||
embedder=make_embedder(cfg.embeddings),
|
||||
)
|
||||
_print_stats(stats)
|
||||
|
||||
@@ -11,7 +11,6 @@ import typer
|
||||
from sqlalchemy.exc import OperationalError, ProgrammingError
|
||||
|
||||
from tht.cli._guards import (
|
||||
has_vector_write_rest,
|
||||
require_server_profile,
|
||||
require_vector_write_allowed,
|
||||
)
|
||||
@@ -45,15 +44,8 @@ def _resync_memory(cfg):
|
||||
|
||||
def clear_memory_index(cfg):
|
||||
from tht.adapters.factory import build_vector_store
|
||||
from tht.cli.vector_cmd import make_embedder, open_store, require_direct_vector_cfg
|
||||
|
||||
if cfg.vectors is not None and cfg.vectors.type == "qdrant":
|
||||
return build_vector_store(cfg, require_write=True).delete_kinds("memory", ["memory"])
|
||||
|
||||
require_direct_vector_cfg(cfg)
|
||||
legacy_store = open_store(cfg, "memory")
|
||||
legacy_store.sync([], make_embedder(cfg.embeddings), kinds={"memory"})
|
||||
return 0
|
||||
return build_vector_store(cfg, require_write=True).delete_kinds("memory", ["memory"])
|
||||
|
||||
|
||||
@memory_app.command("promote")
|
||||
@@ -451,19 +443,13 @@ def search_cmd(
|
||||
def index_solved_session(cfg, session_id: str) -> int:
|
||||
"""Indicizza la coppia domanda->SQL della sessione (kind solved_question).
|
||||
|
||||
Solleva RuntimeError se manca la writer key e SolvedIndexError se mancano gli
|
||||
artefatti: il finalize li degrada a warning, il comando CLI li converte in
|
||||
errori espliciti."""
|
||||
Solleva SolvedIndexError se mancano gli artefatti: il finalize lo degrada a warning,
|
||||
il comando CLI lo converte in errore esplicito."""
|
||||
from tht.adapters.factory import build_vector_store
|
||||
from tht.cli.sql_cmd import promoted_tables_for
|
||||
from tht.cli.vector_cmd import make_embedder
|
||||
from tht.solved import build_solved_snapshot, save_solved_question
|
||||
|
||||
if not has_vector_write_rest(cfg):
|
||||
raise RuntimeError(
|
||||
"vector_write_rest assente: la coppia domanda->SQL si indicizza solo con la "
|
||||
"writer key configurata nel workspace yaml"
|
||||
)
|
||||
store = build_vector_store(cfg, require_write=True)
|
||||
record = build_solved_snapshot(load_snapshot_or_exit(cfg, session_id), promoted_tables_for(cfg, session_id))
|
||||
return save_solved_question(
|
||||
@@ -518,10 +504,9 @@ def solved_search_cmd(
|
||||
from rich.table import Table
|
||||
|
||||
from tht.cli.vector_cmd import make_embedder, open_searcher
|
||||
from tht.ports.vector import VectorReadUnavailable
|
||||
from tht.ports.vector import VectorReadUnavailable, VectorStoreError
|
||||
from tht.solved import SOLVED_KIND
|
||||
from tht.vectorstore.embeddings import EmbeddingsError
|
||||
from tht.vectorstore.rest_client import VectorRestError
|
||||
|
||||
cfg = _load_config_or_exit(config)
|
||||
require_vector_cfg(cfg)
|
||||
@@ -532,7 +517,7 @@ def solved_search_cmd(
|
||||
searcher = open_searcher(cfg)
|
||||
embedder = make_embedder(cfg.embeddings)
|
||||
hits = searcher.search(embedder.embed_query(question), top_n=top, kinds=[SOLVED_KIND])
|
||||
except (VectorRestError, VectorReadUnavailable, EmbeddingsError, OperationalError) as e:
|
||||
except (VectorStoreError, VectorReadUnavailable, EmbeddingsError, OperationalError) as e:
|
||||
typer.secho(
|
||||
f"ATTENZIONE: exemplar non disponibili ({e}). Prosegui senza.",
|
||||
fg=typer.colors.YELLOW, err=True,
|
||||
|
||||
@@ -255,11 +255,10 @@ def pack_cmd(
|
||||
from sqlalchemy.exc import OperationalError
|
||||
|
||||
from tht.cli.vector_cmd import make_embedder, open_searcher, require_vector_cfg
|
||||
from tht.ports.vector import VectorReadUnavailable
|
||||
from tht.ports.vector import VectorReadUnavailable, VectorStoreError
|
||||
from tht.search import combined_search, schema_tables
|
||||
from tht.solved import SOLVED_KIND
|
||||
from tht.vectorstore.embeddings import EmbeddingsError
|
||||
from tht.vectorstore.rest_client import VectorRestError
|
||||
|
||||
cfg = _load_config_or_exit(config)
|
||||
from tht.search.evidence import validate_corpus_workspace
|
||||
@@ -273,7 +272,7 @@ def pack_cmd(
|
||||
evidence: list[dict] = []
|
||||
solved: list[dict] = []
|
||||
warnings: list[str] = []
|
||||
degrade = (VectorRestError, VectorReadUnavailable, EmbeddingsError, OperationalError)
|
||||
degrade = (VectorStoreError, VectorReadUnavailable, EmbeddingsError, OperationalError)
|
||||
|
||||
vec = None
|
||||
searcher = embedder = None
|
||||
|
||||
@@ -2,11 +2,7 @@ from pathlib import Path
|
||||
|
||||
import typer
|
||||
|
||||
from tht.cli._guards import (
|
||||
has_vector_write_rest,
|
||||
require_server_profile,
|
||||
require_vector_write_allowed,
|
||||
)
|
||||
from tht.cli._guards import require_server_profile, require_vector_write_allowed
|
||||
from tht.cli.config_cmd import CONFIG_OPT
|
||||
from tht.cli.schema_cmd import _load_config_or_exit, annotations_path, physical_path
|
||||
from tht.ports.vector import VectorWriteRecord
|
||||
@@ -26,8 +22,8 @@ def require_vector_cfg(cfg):
|
||||
missing = []
|
||||
if cfg.embeddings is None:
|
||||
missing.append("embeddings")
|
||||
if cfg.vectors is None and cfg.vector_db is None and not has_vector_write_rest(cfg):
|
||||
missing.append("vectors o vector_db o vector_write_rest")
|
||||
if cfg.vectors is None:
|
||||
missing.append("vectors")
|
||||
if missing:
|
||||
typer.secho(
|
||||
f"ERRORE: sezioni mancanti nel workspace yaml: {', '.join(missing)}.",
|
||||
@@ -36,27 +32,6 @@ def require_vector_cfg(cfg):
|
||||
raise typer.Exit(code=1)
|
||||
|
||||
|
||||
def require_direct_vector_cfg(cfg):
|
||||
missing = [k for k in ("vector_db", "embeddings") if getattr(cfg, k) is None]
|
||||
if missing:
|
||||
typer.secho(
|
||||
f"ERRORE: sezioni mancanti nel workspace yaml: {', '.join(missing)}.",
|
||||
fg=typer.colors.RED, err=True,
|
||||
)
|
||||
raise typer.Exit(code=1)
|
||||
|
||||
|
||||
def open_store(cfg, table: str):
|
||||
"""Writer table-scoped per il LOADING.
|
||||
|
||||
Sul server preferisce la connessione diretta. In profilo workstation usa `vector_write_rest`
|
||||
se configurato, con upsert remoto non distruttivo.
|
||||
"""
|
||||
from tht.adapters.factory import build_vector_loader
|
||||
|
||||
return build_vector_loader(cfg, table)
|
||||
|
||||
|
||||
def open_searcher(cfg):
|
||||
"""Searcher per la LETTURA (similarity search): via REST se `vector_rest` è configurato,
|
||||
altrimenti connessione diretta (dev/test)."""
|
||||
@@ -115,20 +90,20 @@ def init_cmd(
|
||||
False, "--skip-ollama-check", help="Non verificare la raggiungibilita' di Ollama."
|
||||
),
|
||||
) -> None:
|
||||
"""Crea schema e tabella pgvector (idempotente) e verifica le connessioni."""
|
||||
from sqlalchemy.exc import OperationalError
|
||||
|
||||
"""Verifica il runtime Qdrant e la raggiungibilita' dell'embedder configurato."""
|
||||
from tht.adapters.factory import build_vector_store
|
||||
from tht.vectorstore.embeddings import EmbeddingsError
|
||||
from tht.vectorstore.reader import ALL_TABLES
|
||||
|
||||
cfg = _load_config_or_exit(config)
|
||||
require_server_profile(cfg, "vector init")
|
||||
require_direct_vector_cfg(cfg)
|
||||
try:
|
||||
for table in ALL_TABLES:
|
||||
open_store(cfg, table).init_schema()
|
||||
except OperationalError as e:
|
||||
typer.secho(f"ERRORE connessione pgvector: {e.orig}", fg=typer.colors.RED, err=True)
|
||||
require_vector_cfg(cfg)
|
||||
health = build_vector_store(cfg, require_write=True).health()
|
||||
if not health.ok:
|
||||
typer.secho(
|
||||
f"ERRORE runtime vettoriale: {health.detail or 'Qdrant non raggiungibile o incompatibile'}",
|
||||
fg=typer.colors.RED,
|
||||
err=True,
|
||||
)
|
||||
raise typer.Exit(code=1)
|
||||
if not skip_ollama_check:
|
||||
try:
|
||||
@@ -137,8 +112,8 @@ def init_cmd(
|
||||
typer.secho(f"ERRORE: {e}", fg=typer.colors.RED, err=True)
|
||||
raise typer.Exit(code=1)
|
||||
typer.secho(
|
||||
f"OK: schema {cfg.vector_db.db_schema} pronto (tabelle: {', '.join(ALL_TABLES)}) su "
|
||||
f"{cfg.vector_db.host}:{cfg.vector_db.port}", fg=typer.colors.GREEN,
|
||||
f"OK: runtime Qdrant pronto per la collezione {cfg.vectors.collection}",
|
||||
fg=typer.colors.GREEN,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user