mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-07-02 02:58:10 +02:00
Deliver explainability triples inline in retrieval response stream (#763)
Provenance triples are now included directly in explain messages from GraphRAG, DocumentRAG, and Agent services, eliminating the need for follow-up knowledge graph queries to retrieve explainability details. Each explain message in the response stream now carries: - explain_id: root URI for this provenance step (unchanged) - explain_graph: named graph where triples are stored (unchanged) - explain_triples: the actual provenance triples for this step (new) Changes across the stack: - Schema: added explain_triples field to GraphRagResponse, DocumentRagResponse, and AgentResponse - Services: all explain message call sites pass triples through (graph_rag, document_rag, agent react, agent orchestrator) - Translators: encode explain_triples via TripleTranslator for gateway wire format - Python SDK: ProvenanceEvent now includes parsed ExplainEntity and raw triples; expanded event_type detection - CLI: invoke_graph_rag, invoke_agent, invoke_document_rag use inline entity when available, fall back to graph query - Tech specs updated Additional explainability test
This commit is contained in:
parent
2f8d6a3ffb
commit
ddd4bd7790
16 changed files with 521 additions and 49 deletions
|
|
@ -1,6 +1,7 @@
|
|||
from typing import Dict, Any, Tuple
|
||||
from ...schema import AgentRequest, AgentResponse
|
||||
from .base import MessageTranslator
|
||||
from .primitives import TripleTranslator
|
||||
|
||||
|
||||
class AgentRequestTranslator(MessageTranslator):
|
||||
|
|
@ -49,10 +50,13 @@ class AgentRequestTranslator(MessageTranslator):
|
|||
|
||||
class AgentResponseTranslator(MessageTranslator):
|
||||
"""Translator for AgentResponse schema objects"""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.triple_translator = TripleTranslator()
|
||||
|
||||
def decode(self, data: Dict[str, Any]) -> AgentResponse:
|
||||
raise NotImplementedError("Response translation to Pulsar not typically needed")
|
||||
|
||||
|
||||
def encode(self, obj: AgentResponse) -> Dict[str, Any]:
|
||||
result = {}
|
||||
|
||||
|
|
@ -75,6 +79,13 @@ class AgentResponseTranslator(MessageTranslator):
|
|||
if explain_graph is not None:
|
||||
result["explain_graph"] = explain_graph
|
||||
|
||||
# Include explain_triples for explain messages
|
||||
explain_triples = getattr(obj, "explain_triples", [])
|
||||
if explain_triples:
|
||||
result["explain_triples"] = [
|
||||
self.triple_translator.encode(t) for t in explain_triples
|
||||
]
|
||||
|
||||
# Always include error if present
|
||||
if hasattr(obj, 'error') and obj.error and obj.error.message:
|
||||
result["error"] = {"message": obj.error.message, "code": obj.error.code}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from typing import Dict, Any, Tuple
|
||||
from ...schema import DocumentRagQuery, DocumentRagResponse, GraphRagQuery, GraphRagResponse
|
||||
from .base import MessageTranslator
|
||||
from .primitives import TripleTranslator
|
||||
|
||||
|
||||
class DocumentRagRequestTranslator(MessageTranslator):
|
||||
|
|
@ -28,6 +29,9 @@ class DocumentRagRequestTranslator(MessageTranslator):
|
|||
class DocumentRagResponseTranslator(MessageTranslator):
|
||||
"""Translator for DocumentRagResponse schema objects"""
|
||||
|
||||
def __init__(self):
|
||||
self.triple_translator = TripleTranslator()
|
||||
|
||||
def decode(self, data: Dict[str, Any]) -> DocumentRagResponse:
|
||||
raise NotImplementedError("Response translation to Pulsar not typically needed")
|
||||
|
||||
|
|
@ -53,6 +57,13 @@ class DocumentRagResponseTranslator(MessageTranslator):
|
|||
if explain_graph is not None:
|
||||
result["explain_graph"] = explain_graph
|
||||
|
||||
# Include explain_triples for explain messages
|
||||
explain_triples = getattr(obj, "explain_triples", [])
|
||||
if explain_triples:
|
||||
result["explain_triples"] = [
|
||||
self.triple_translator.encode(t) for t in explain_triples
|
||||
]
|
||||
|
||||
# Include end_of_stream flag (LLM stream complete)
|
||||
result["end_of_stream"] = getattr(obj, "end_of_stream", False)
|
||||
|
||||
|
|
@ -107,6 +118,9 @@ class GraphRagRequestTranslator(MessageTranslator):
|
|||
class GraphRagResponseTranslator(MessageTranslator):
|
||||
"""Translator for GraphRagResponse schema objects"""
|
||||
|
||||
def __init__(self):
|
||||
self.triple_translator = TripleTranslator()
|
||||
|
||||
def decode(self, data: Dict[str, Any]) -> GraphRagResponse:
|
||||
raise NotImplementedError("Response translation to Pulsar not typically needed")
|
||||
|
||||
|
|
@ -132,6 +146,13 @@ class GraphRagResponseTranslator(MessageTranslator):
|
|||
if explain_graph is not None:
|
||||
result["explain_graph"] = explain_graph
|
||||
|
||||
# Include explain_triples for explain messages
|
||||
explain_triples = getattr(obj, "explain_triples", [])
|
||||
if explain_triples:
|
||||
result["explain_triples"] = [
|
||||
self.triple_translator.encode(t) for t in explain_triples
|
||||
]
|
||||
|
||||
# Include end_of_stream flag (LLM stream complete)
|
||||
result["end_of_stream"] = getattr(obj, "end_of_stream", False)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue