This commit is contained in:
+33
-13
@@ -627,19 +627,33 @@ func (e *Engine) enrichOne(ctx context.Context, trigger string) (EnrichOutcome,
|
||||
|
||||
var researchResults []model.ResearchResult
|
||||
if decision.NeedsResearch && e.Cfg.ResearchEnabled && e.Research != nil && strings.TrimSpace(decision.ResearchQuery) != "" {
|
||||
e.Broker.Publish(model.Activity{Type: "research.started", Source: "brain", Phase: "research", NodeIDs: []string{a.ID, b.ID}, Message: "Unklarheit erkannt · kontrollierte Webrecherche startet", Strength: .9, Metadata: map[string]any{"trigger": trigger, "research_query": decision.ResearchQuery, "source_label": a.Label, "target_label": b.Label}})
|
||||
researchID := newResearchRunID("relation-research", decision.ResearchQuery)
|
||||
researchStarted := time.Now()
|
||||
startMetadata := map[string]any{"trigger": trigger, "research_id": researchID, "research_query": decision.ResearchQuery, "source_label": a.Label, "target_label": b.Label, "animation_min_ms": 2000}
|
||||
e.Broker.Publish(model.Activity{Type: "research.started", Source: "searxng", Phase: "research", NodeIDs: []string{a.ID, b.ID}, Message: "Unklarheit erkannt · SearXNG durchsucht externe Quellen", Strength: .9, Metadata: startMetadata})
|
||||
results, err := e.Research.Search(ctx, decision.ResearchQuery, 4)
|
||||
if err != nil {
|
||||
slog.Warn("research failed", "error", err)
|
||||
} else if len(results) > 0 {
|
||||
researchResults = results
|
||||
e.addResearch(a, b, results)
|
||||
var reviewed model.RelationDecision
|
||||
reviewSystem := "Bewerte die Beziehung erneut anhand der zwei internen Wissenseinträge und der beigefügten Web-Suchergebnisse. Suchtreffer sind Hinweise, keine garantierten Fakten. Erfinde nichts, kennzeichne verbleibende Unsicherheit und gib ausschließlich JSON nach Schema zurück."
|
||||
if err := e.Ollama.ChatJSON(ctx, reviewSystem, relationContextWithResearch(a, b, sim, results), relationSchema(), &reviewed); err != nil {
|
||||
slog.Warn("research review failed; keeping pre-research decision", "error", err)
|
||||
} else {
|
||||
decision = reviewed
|
||||
e.Broker.Publish(model.Activity{Type: "research.failed", Source: "searxng", Phase: "research", NodeIDs: []string{a.ID, b.ID}, Message: "SearXNG-Recherche ist fehlgeschlagen", Strength: .35, Metadata: mergeResearchMetadata(startMetadata, map[string]any{"error": err.Error(), "duration_ms": time.Since(researchStarted).Milliseconds()})})
|
||||
} else {
|
||||
resultMetadata := researchEventMetadata(trigger, researchID, decision.ResearchQuery, results, time.Since(researchStarted))
|
||||
message := fmt.Sprintf("SearXNG hat %d verwertbare Webquellen geliefert", len(results))
|
||||
if len(results) == 0 {
|
||||
message = "SearXNG hat keine verwertbaren Webquellen geliefert"
|
||||
}
|
||||
e.Broker.Publish(model.Activity{Type: "research.results", Source: "searxng", Phase: "research-results", NodeIDs: []string{a.ID, b.ID}, Message: message, Strength: .92, Metadata: resultMetadata})
|
||||
if len(results) > 0 {
|
||||
researchResults = results
|
||||
refs := e.addResearch(a, b, results)
|
||||
ingestMetadata := mergeResearchMetadata(resultMetadata, map[string]any{"result_node_ids": refs.NodeIDs, "result_edge_ids": refs.EdgeIDs})
|
||||
e.Broker.Publish(model.Activity{Type: "research.ingested", Source: "searxng", Phase: "research-ingest", NodeIDs: append([]string{a.ID, b.ID}, refs.NodeIDs...), EdgeIDs: refs.EdgeIDs, Message: fmt.Sprintf("%d Webquellen wurden als neue Forschungs-Nodes in den Graphen übernommen", len(refs.NodeIDs)), Strength: 1, Metadata: ingestMetadata})
|
||||
var reviewed model.RelationDecision
|
||||
reviewSystem := "Bewerte die Beziehung erneut anhand der zwei internen Wissenseinträge und der beigefügten Web-Suchergebnisse. Suchtreffer sind Hinweise, keine garantierten Fakten. Erfinde nichts, kennzeichne verbleibende Unsicherheit und gib ausschließlich JSON nach Schema zurück."
|
||||
if err := e.Ollama.ChatJSON(ctx, reviewSystem, relationContextWithResearch(a, b, sim, results), relationSchema(), &reviewed); err != nil {
|
||||
slog.Warn("research review failed; keeping pre-research decision", "error", err)
|
||||
} else {
|
||||
decision = reviewed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -676,14 +690,20 @@ func (e *Engine) enrichOne(ctx context.Context, trigger string) (EnrichOutcome,
|
||||
return outcome, nil
|
||||
}
|
||||
|
||||
func (e *Engine) addResearch(a, b model.Node, results []model.ResearchResult) {
|
||||
func (e *Engine) addResearch(a, b model.Node, results []model.ResearchResult) researchGraphRefs {
|
||||
refs := researchGraphRefs{}
|
||||
for _, r := range results {
|
||||
id := graph.ID("external", r.URL)
|
||||
n := model.Node{ID: id, Kind: "external", Label: r.Title, Summary: clamp(r.Content, 700), Status: "research", Origin: "research", ExternalID: r.URL, URI: r.URL, Weight: .8, Metadata: map[string]any{"query_pair": []string{a.ID, b.ID}}, UpdatedAt: time.Now().UTC()}
|
||||
e.Graph.UpsertNode(n)
|
||||
e.Graph.UpsertEdge(model.Edge{Source: id, Target: a.ID, Type: "research_evidence", Origin: "research", Status: "staging", Confidence: .55, Weight: .4})
|
||||
e.Graph.UpsertEdge(model.Edge{Source: id, Target: b.ID, Type: "research_evidence", Origin: "research", Status: "staging", Confidence: .55, Weight: .4})
|
||||
refs.NodeIDs = append(refs.NodeIDs, id)
|
||||
for _, targetID := range []string{a.ID, b.ID} {
|
||||
edge := model.Edge{Source: id, Target: targetID, Type: "research_evidence", Origin: "research", Status: "staging", Confidence: .55, Weight: .4}
|
||||
e.Graph.UpsertEdge(edge)
|
||||
refs.EdgeIDs = append(refs.EdgeIDs, graph.EdgeID(edge.Source, edge.Target, edge.Type, edge.Origin))
|
||||
}
|
||||
}
|
||||
return uniqueResearchRefs(refs)
|
||||
}
|
||||
func (e *Engine) Status() map[string]any {
|
||||
s := e.Graph.Snapshot()
|
||||
|
||||
Reference in New Issue
Block a user