RAGSpine
Riferimento

Punti di estensione

Interfacce tipizzate per provider, store, recupero, chunking, routing, corrispondenza dei flussi di lavoro, connettori e confini di servizio.

La pluggabilità di RAGSpine non è un registro di plugin — è semplice tipizzazione strutturale. Ogni dipendenza esterna è un Protocol Python; il core dipende dall'astrazione, mai da un SDK di terze parti. Aggiungere un provider, un vector store, un reranker o un motore OCR richiede un solo nuovo file, e ogni SDK pesante viene importato in modo lazy, così il core si importa senza problemi e funziona completamente offline con il MockProvider deterministico.

Tutte le interfacce descritte di seguito sono Protocol @runtime_checkable — la vostra implementazione non deve ereditare da nulla, deve solo avere le firme di metodo corrette. mypy --strict copre il core, e gli SDK anthropic / openai / sentence-transformers / paddleocr vengono importati solo all'interno delle implementazioni concrete, mai nell'interfaccia.

Le interfacce

LLMProvider

corespine (riesportato tramite agent/llm_provider.py) — chat(messages, tools) restituisce una ChatCompletion; formato chat-completions di OpenAI.

EmbeddingBackend

retrieval/lexical/retrieval.py — trasforma batch di testi in vettori per il canale vettoriale iniettabile.

ListwiseJudge

retrieval/rerank/listwise_rerank.py — reranking listwise: restituisce gli indici dei candidati in ordine dal migliore.

OcrBackend

extraction/extractors/pdf_scanned_extractor.py — riconosce l'immagine di una singola pagina scansionata.

NarrativeRetriever

agent/agent.py — l'interfaccia di recupero narrativo iniettata nell'orchestratore.

TaskQueue

service/tasks/task_queue.py — coda di job asincrona (FakeQueue nei test, RQQueue in produzione).

SourceConnector

ingestion/source/connector.py — iter_documents() produce RawDoc da una sorgente di knowledge base (filesystem, HTTP, Notion, in-memory).

RelationExtractor

graph/extractor.py — extract(chunks) restituisce gli archi del grafo; lo slot opzionale per le relazioni narrative accanto a build_relation_graph.

Chunker

retrieval/chunking/chunker.py — da testo più DocumentMeta a chunk che preservano la tracciabilità; implementazioni integrate ed entry point di terze parti.

LibraryRouter / FilterExtractor

retrieval/routing e filtering — selezione deterministica della libreria ed estrazione opzionale di filtri strutturati sui metadati.

TemplateMatcher

workflows/matching.py — classifica riferimenti a template eseguibili basati solo su metadati per lo scaffolding in linguaggio naturale.

Interfacce attuali per recupero e flussi di lavoro

Chunker.chunk(text, meta, *, max_chars, overlap_chars) -> list[Chunk] è responsabile della strategia di chunking. make_chunker supporta le implementazioni deterministica predefinita, layout, parent-child, sentence-window, laws, QA, book e semantica, oltre al gruppo di entry point ragspine.chunkers. Le implementazioni devono preservare doc_id e source_locator; i dati di gerarchia/finestra sono additivi, non un sostituto della tracciabilità.

LibraryRouter seleziona uno o più ID RoutableLibrary. MultiIndexRetriever invoca in modo indipendente i NarrativeRetriever selezionati e ne fonde i risultati con RRF; in caso di errore del router si ricade su tutte le librerie. FilterExtractor può proporre predicati sui metadati, ma i filtri restano operazioni di restrizione validate.

TemplateMatcher riceve riferimenti di catalogo contenenti metadati di corrispondenza, non prompt dei flussi di lavoro né credenziali. I matcher integrati lessicale e ONNX restituiscono candidati classificati; la policy di scaffolding applica la soglia di punteggio/margine e valida il template selezionato. Un matcher personalizzato non acquisisce autorità di scrittura su file o di esecuzione.

LLMProvider

Di proprietà di corespine e riesportato da src/ragspine/agent/llm_provider.py — l'unico metodo pilotato dal ciclo di tool-use dell'agente. Parla il formato chat-completions di OpenAI (un solo metodo chat). AnthropicProvider importa in modo lazy l'SDK anthropic e mappa il formato sull'API Anthropic; MockProvider non richiede né chiave né rete.

Proprietà

Tipo

Migrazione 0.3.0. Questo ha sostituito il vecchio create_message(*, system, messages, tools) -> ProviderResponse. Il contratto ora risiede nel core condiviso della famiglia corespine, così ragspine e i suoi pacchetti fratelli condividono un unico contratto di provider — vedere ADR 0012.

EmbeddingBackend

src/ragspine/retrieval/lexical/retrieval.py — il punto di dependency injection per il canale vettoriale. Il valore predefinito è none (BM25 puro); iniettatelo per aggiungere un canale vettoriale.

Proprietà

Tipo

ListwiseJudge

src/ragspine/retrieval/rerank/listwise_rerank.py — l'interfaccia opzionale del reranker listwise basato su LLM. L'implementazione reale è Claude (tramite build_listwise_prompt / parse_listwise_response); i test usano un fake deterministico. In sua assenza si ricade sull'ordine RRF.

Proprietà

Tipo

OcrBackend

src/ragspine/extraction/extractors/pdf_scanned_extractor.py — l'interfaccia OCR/VLM per i PDF scansionati. Il backend reale (PaddleOCR) gira su Ubuntu + GPU; i test di logica usano un fake così il flusso render → map → threshold → review è completamente testabile su una macchina senza GPU.

Proprietà

Tipo

NarrativeRetriever

src/ragspine/agent/agent.py — l'implementazione di recupero narrativo iniettata in answer_question. Duck-typed; se omessa, il percorso narrativo degrada in modo onesto.

Proprietà

Tipo

TaskQueue

src/ragspine/service/tasks/task_queue.py — la coda di job asincrona. RQQueue (RQ + Redis) per la produzione, FakeQueue (sincrona inline) per i test. rq / redis vengono importati in modo lazy solo all'interno di RQQueue.

Proprietà

Tipo

SourceConnector

src/ragspine/ingestion/source/connector.py — l'interfaccia delle sorgenti di knowledge base. Un connettore produce documenti grezzi da qualunque posto in cui risieda la vostra KB; il FilesystemConnector predefinito non richiede alcun extra, mentre i connettori HTTP / Notion importano in modo lazy httpx dietro l'extra [connectors].

Proprietà

Tipo

Le implementazioni integrate si registrano per nome in una tabella a livello di modulo; i connettori di terze parti vengono scoperti tramite il gruppo di entry point ragspine.source_connectors (in caso di conflitto vincono i nomi integrati). Selezionatene uno con la factory make_source_connector(spec=None, **kwargs) o con la variabile d'ambiente RAGSPINE_SOURCE_CONNECTOR (none / NoneNone):

Proprietà

Tipo

RelationExtractor

src/ragspine/graph/extractor.py — lo slot opzionale per le relazioni narrative consumato da build_relation_graph(..., relation_extractor=None). Con il None predefinito, il grafo di base è identico byte per byte (nessun arco aggiuntivo). Vedere ADR 0015.

Proprietà

Tipo

Selezionate tramite make_relation_extractor(spec=None, *, provider=None, profile=None, **kwargs) o RAGSPINE_RELATION_EXTRACTOR (noneNone; deterministic / rule / cooccurrence → il predefinito deterministico; llm / on → l'estrattore LLM, che degrada onestamente a None quando nessun provider è disponibile).

Un arco estratto dal modello è utile ma non attendibile. LLMRelationExtractor scrive i marcatori derived=model-derived e verified=unverified nei metadati di ogni arco, prende la tracciabilità dal chunk (il chiamante) anziché dall'autodichiarazione del modello, e scarta qualsiasi arco il cui estremo venga rifiutato dal SecurityGate deterministico. Una relazione asserita dal modello non può mai essere letta come un fatto controllato e verificato.

Implementare un Protocol e iniettarlo

Poiché le interfacce sono strutturali, implementate il metodo (o i metodi) e passate l'istanza — nessuna registrazione, nessuna classe base. Ecco un LLMProvider basato su OpenAI, fondato sulla vera firma di chat e sul formato ChatCompletion (le dataclass provengono da corespine e sono riesportate da ragspine.agent.llm_provider):

my_openai_provider.py
from typing import Any

from openai import OpenAI  # lazy: only your file imports the SDK
from corespine import ChatCompletion, Choice, ResponseMessage, Usage


class OpenAIProvider:
    """A custom LLMProvider — no subclassing, just the chat method."""

    def __init__(self, model: str = "gpt-4o") -> None:
        self._client = OpenAI()
        self._model = model

    def chat(
        self,
        messages: list[dict[str, Any]],
        *,
        tools: list[dict[str, Any]] | None = None,
    ) -> ChatCompletion:
        # The messages are already in the OpenAI chat-completions shape, so they pass
        # through; the SDK response is the same shape, so the mapping back is direct.
        resp = self._client.chat.completions.create(
            model=self._model,
            messages=messages,
            tools=tools or [],  # adapt / omit as needed
        )
        choice = resp.choices[0]
        message = ResponseMessage(role="assistant", content=choice.message.content)
        u = resp.usage
        usage = (
            Usage(
                prompt_tokens=u.prompt_tokens,
                completion_tokens=u.completion_tokens,
                total_tokens=u.total_tokens,
            )
            if u is not None
            else None
        )
        return ChatCompletion(
            choices=(Choice(index=0, message=message, finish_reason=choice.finish_reason or "stop"),),
            usage=usage,
            model=resp.model,
            id=resp.id,
        )

Iniettatelo esattamente dove andrebbe MockProvider:

from ragspine.agent.agent import answer_question
from ragspine.storage.fact_store import SqliteFactStore
from my_openai_provider import OpenAIProvider

store = SqliteFactStore("data/fact_metric.db")
store.init_schema()
result = answer_question("...", store, OpenAIProvider())

La protezione di prevenzione delle risposte inventate del canale strutturato non si fida della prosa del provider per il numero — un fatto trovato viene reso in modo deterministico a partire dal valore del fatto, e un risultato senza fatti viene riscritto come "not found" indipendentemente dall'output del modello. Sostituire il provider non può aggirare la protezione.

In questa pagina