mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-04-25 00:16:23 +02:00
Fix incorrect property names in explainability (#698)
Remove type suffixes from explainability dataclass fields + fix show_explain_trace Rename dataclass fields to match KG property naming conventions: - Analysis: thought_uri/observation_uri → thought/observation - Synthesis/Conclusion/Reflection: document_uri → document Fix show_explain_trace for current API: - Resolve document content via librarian fetch instead of removed inline content fields (synthesis.content, conclusion.answer) - Add Grounding display for DocRAG traces - Update fetch_docrag_trace chain: Question → Grounding → Exploration → Synthesis - Pass api/explain_client to all print functions for content resolution Update all CLI tools and tests for renamed fields.
This commit is contained in:
parent
a115ec06ab
commit
c387670944
6 changed files with 122 additions and 62 deletions
|
|
@ -212,32 +212,32 @@ class Focus(ExplainEntity):
|
|||
@dataclass
|
||||
class Synthesis(ExplainEntity):
|
||||
"""Synthesis entity - the final answer."""
|
||||
document_uri: str = "" # Reference to librarian document
|
||||
document: str = ""
|
||||
|
||||
@classmethod
|
||||
def from_triples(cls, uri: str, triples: List[Tuple[str, str, Any]]) -> "Synthesis":
|
||||
document_uri = ""
|
||||
document = ""
|
||||
|
||||
for s, p, o in triples:
|
||||
if p == TG_DOCUMENT:
|
||||
document_uri = o
|
||||
document = o
|
||||
|
||||
return cls(
|
||||
uri=uri,
|
||||
entity_type="synthesis",
|
||||
document_uri=document_uri
|
||||
document=document
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Reflection(ExplainEntity):
|
||||
"""Reflection entity - intermediate commentary (Thought or Observation)."""
|
||||
document_uri: str = "" # Reference to content in librarian
|
||||
document: str = ""
|
||||
reflection_type: str = "" # "thought" or "observation"
|
||||
|
||||
@classmethod
|
||||
def from_triples(cls, uri: str, triples: List[Tuple[str, str, Any]]) -> "Reflection":
|
||||
document_uri = ""
|
||||
document = ""
|
||||
reflection_type = ""
|
||||
|
||||
types = [o for s, p, o in triples if p == RDF_TYPE]
|
||||
|
|
@ -249,12 +249,12 @@ class Reflection(ExplainEntity):
|
|||
|
||||
for s, p, o in triples:
|
||||
if p == TG_DOCUMENT:
|
||||
document_uri = o
|
||||
document = o
|
||||
|
||||
return cls(
|
||||
uri=uri,
|
||||
entity_type="reflection",
|
||||
document_uri=document_uri,
|
||||
document=document,
|
||||
reflection_type=reflection_type
|
||||
)
|
||||
|
||||
|
|
@ -264,15 +264,15 @@ class Analysis(ExplainEntity):
|
|||
"""Analysis entity - one think/act/observe cycle (Agent only)."""
|
||||
action: str = ""
|
||||
arguments: str = "" # JSON string
|
||||
thought_uri: str = "" # URI of thought sub-entity
|
||||
observation_uri: str = "" # URI of observation sub-entity
|
||||
thought: str = ""
|
||||
observation: str = ""
|
||||
|
||||
@classmethod
|
||||
def from_triples(cls, uri: str, triples: List[Tuple[str, str, Any]]) -> "Analysis":
|
||||
action = ""
|
||||
arguments = ""
|
||||
thought_uri = ""
|
||||
observation_uri = ""
|
||||
thought = ""
|
||||
observation = ""
|
||||
|
||||
for s, p, o in triples:
|
||||
if p == TG_ACTION:
|
||||
|
|
@ -280,37 +280,37 @@ class Analysis(ExplainEntity):
|
|||
elif p == TG_ARGUMENTS:
|
||||
arguments = o
|
||||
elif p == TG_THOUGHT:
|
||||
thought_uri = o
|
||||
thought = o
|
||||
elif p == TG_OBSERVATION:
|
||||
observation_uri = o
|
||||
observation = o
|
||||
|
||||
return cls(
|
||||
uri=uri,
|
||||
entity_type="analysis",
|
||||
action=action,
|
||||
arguments=arguments,
|
||||
thought_uri=thought_uri,
|
||||
observation_uri=observation_uri
|
||||
thought=thought,
|
||||
observation=observation
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Conclusion(ExplainEntity):
|
||||
"""Conclusion entity - final answer (Agent only)."""
|
||||
document_uri: str = "" # Reference to librarian document
|
||||
document: str = ""
|
||||
|
||||
@classmethod
|
||||
def from_triples(cls, uri: str, triples: List[Tuple[str, str, Any]]) -> "Conclusion":
|
||||
document_uri = ""
|
||||
document = ""
|
||||
|
||||
for s, p, o in triples:
|
||||
if p == TG_DOCUMENT:
|
||||
document_uri = o
|
||||
document = o
|
||||
|
||||
return cls(
|
||||
uri=uri,
|
||||
entity_type="conclusion",
|
||||
document_uri=document_uri
|
||||
document=document
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -782,8 +782,8 @@ class ExplainabilityClient:
|
|||
"""
|
||||
Fetch the complete DocumentRAG trace starting from a question URI.
|
||||
|
||||
Follows the provenance chain: Question -> Exploration -> Synthesis
|
||||
(No Focus step for DocRAG since it doesn't do edge selection)
|
||||
Follows the provenance chain:
|
||||
Question -> Grounding -> Exploration -> Synthesis
|
||||
|
||||
Args:
|
||||
question_uri: The question entity URI
|
||||
|
|
@ -794,13 +794,14 @@ class ExplainabilityClient:
|
|||
max_content: Maximum content length for synthesis
|
||||
|
||||
Returns:
|
||||
Dict with question, exploration, synthesis entities
|
||||
Dict with question, grounding, exploration, synthesis entities
|
||||
"""
|
||||
if graph is None:
|
||||
graph = "urn:graph:retrieval"
|
||||
|
||||
trace = {
|
||||
"question": None,
|
||||
"grounding": None,
|
||||
"exploration": None,
|
||||
"synthesis": None,
|
||||
}
|
||||
|
|
@ -811,8 +812,8 @@ class ExplainabilityClient:
|
|||
return trace
|
||||
trace["question"] = question
|
||||
|
||||
# Find exploration: ?exploration prov:wasGeneratedBy question_uri
|
||||
exploration_triples = self.flow.triples_query(
|
||||
# Find grounding: ?grounding prov:wasGeneratedBy question_uri
|
||||
grounding_triples = self.flow.triples_query(
|
||||
p=PROV_WAS_GENERATED_BY,
|
||||
o=question_uri,
|
||||
g=graph,
|
||||
|
|
@ -821,6 +822,30 @@ class ExplainabilityClient:
|
|||
limit=10
|
||||
)
|
||||
|
||||
if grounding_triples:
|
||||
grounding_uris = [
|
||||
extract_term_value(t.get("s", {}))
|
||||
for t in grounding_triples
|
||||
]
|
||||
for gnd_uri in grounding_uris:
|
||||
grounding = self.fetch_entity(gnd_uri, graph, user, collection)
|
||||
if isinstance(grounding, Grounding):
|
||||
trace["grounding"] = grounding
|
||||
break
|
||||
|
||||
if not trace["grounding"]:
|
||||
return trace
|
||||
|
||||
# Find exploration: ?exploration prov:wasDerivedFrom grounding_uri
|
||||
exploration_triples = self.flow.triples_query(
|
||||
p=PROV_WAS_DERIVED_FROM,
|
||||
o=trace["grounding"].uri,
|
||||
g=graph,
|
||||
user=user,
|
||||
collection=collection,
|
||||
limit=10
|
||||
)
|
||||
|
||||
if exploration_triples:
|
||||
exploration_uris = [
|
||||
extract_term_value(t.get("s", {}))
|
||||
|
|
@ -836,7 +861,6 @@ class ExplainabilityClient:
|
|||
return trace
|
||||
|
||||
# Find synthesis: ?synthesis prov:wasDerivedFrom exploration_uri
|
||||
# (DocRAG goes directly from exploration to synthesis, no focus step)
|
||||
synthesis_triples = self.flow.triples_query(
|
||||
p=PROV_WAS_DERIVED_FROM,
|
||||
o=trace["exploration"].uri,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue