Ch2
This commit is contained in:
+67
-43
@@ -54,45 +54,49 @@ type Engine struct {
|
||||
GLPIKB *ingest.GLPIKBSyncer
|
||||
Persistence *persist.Coordinator
|
||||
|
||||
mu sync.Mutex
|
||||
stateMu sync.RWMutex
|
||||
lastScan time.Time
|
||||
lastEnrich time.Time
|
||||
lastAttempt time.Time
|
||||
nextEnrich time.Time
|
||||
ollamaOK bool
|
||||
enrichRunning bool
|
||||
enrichTrigger string
|
||||
enrichResult string
|
||||
enrichError string
|
||||
enrichCycles uint64
|
||||
enrichCreated uint64
|
||||
enrichRejected uint64
|
||||
relationsCreated uint64
|
||||
articlesCreated uint64
|
||||
articlesSkipped uint64
|
||||
enrichRequests chan string
|
||||
runtimeMu sync.RWMutex
|
||||
runtime RuntimeSettings
|
||||
runtimePath string
|
||||
researchEvidenceMu sync.RWMutex
|
||||
researchEvidenceCache map[string]researchEvidenceRecord
|
||||
sharedWork *workqueue.Limiter
|
||||
researchDedupeMu sync.Mutex
|
||||
researchDedupe map[string]*researchDedupeEntry
|
||||
interactiveInflight atomic.Int64
|
||||
autonomousWake chan struct{}
|
||||
autonomousScanRequests chan string
|
||||
autonomousRunning bool
|
||||
autonomousTaskID string
|
||||
autonomousTaskTopic string
|
||||
autonomousLastStarted time.Time
|
||||
autonomousLastCompleted time.Time
|
||||
autonomousLastError string
|
||||
autonomousCompleted uint64
|
||||
autonomousFailed uint64
|
||||
autonomousEvidence uint64
|
||||
autonomousArticles uint64
|
||||
mu sync.Mutex
|
||||
stateMu sync.RWMutex
|
||||
lastScan time.Time
|
||||
lastEnrich time.Time
|
||||
lastAttempt time.Time
|
||||
nextEnrich time.Time
|
||||
ollamaOK bool
|
||||
enrichRunning bool
|
||||
enrichTrigger string
|
||||
enrichResult string
|
||||
enrichError string
|
||||
enrichCycles uint64
|
||||
enrichCreated uint64
|
||||
enrichRejected uint64
|
||||
relationsCreated uint64
|
||||
articlesCreated uint64
|
||||
articlesSkipped uint64
|
||||
enrichRequests chan string
|
||||
runtimeMu sync.RWMutex
|
||||
runtime RuntimeSettings
|
||||
runtimePath string
|
||||
researchEvidenceMu sync.RWMutex
|
||||
researchEvidenceCache map[string]researchEvidenceRecord
|
||||
sharedWork *workqueue.Limiter
|
||||
researchDedupeMu sync.Mutex
|
||||
researchDedupe map[string]*researchDedupeEntry
|
||||
researchDedupeGuardFiltered uint64
|
||||
researchDedupeGuardPrimaryMismatch uint64
|
||||
researchDedupeGuardFocusMismatch uint64
|
||||
researchDedupeGuardEntityMismatch uint64
|
||||
interactiveInflight atomic.Int64
|
||||
autonomousWake chan struct{}
|
||||
autonomousScanRequests chan string
|
||||
autonomousRunning bool
|
||||
autonomousTaskID string
|
||||
autonomousTaskTopic string
|
||||
autonomousLastStarted time.Time
|
||||
autonomousLastCompleted time.Time
|
||||
autonomousLastError string
|
||||
autonomousCompleted uint64
|
||||
autonomousFailed uint64
|
||||
autonomousEvidence uint64
|
||||
autonomousArticles uint64
|
||||
}
|
||||
|
||||
func New(cfg config.Config, g *graph.Store, b *activity.Broker) *Engine {
|
||||
@@ -176,6 +180,12 @@ func New(cfg config.Config, g *graph.Store, b *activity.Broker) *Engine {
|
||||
if strings.TrimSpace(cfg.ArticleLanguage) == "" {
|
||||
cfg.ArticleLanguage = "de-DE"
|
||||
}
|
||||
if strings.TrimSpace(cfg.ArticleSynthesisModel) == "" {
|
||||
cfg.ArticleSynthesisModel = cfg.ChatModel
|
||||
}
|
||||
if strings.TrimSpace(cfg.ArticleReviewModel) == "" {
|
||||
cfg.ArticleReviewModel = cfg.ChatModel
|
||||
}
|
||||
if cfg.ResearchDedupeThreshold <= 0 {
|
||||
cfg.ResearchDedupeThreshold = .92
|
||||
}
|
||||
@@ -261,7 +271,7 @@ func New(cfg config.Config, g *graph.Store, b *activity.Broker) *Engine {
|
||||
e.GLPIKB = ingest.NewGLPIKBSyncer(ingest.GLPIKBConfig{Enabled: true, Path: cfg.GLPIKBPath, Filter: cfg.GLPIKBFilter, Limit: cfg.GLPIKBLimit, SyncInterval: cfg.GLPIKBSyncInterval, Source: cfg.GLPIKBSource, CachePath: filepath.Join(cfg.DataDir, "glpi-kb-cache.json"), ShouldSync: e.LearningEnabled}, client, g, b, persistence)
|
||||
}
|
||||
if b != nil {
|
||||
b.Publish(model.Activity{Type: "system.started", Source: "brain", Phase: "startup", Message: "Neural Brain wurde gestartet; das Analyseprotokoll zeichnet Läufe und Graphänderungen auf", Strength: .3, Metadata: map[string]any{"chat_model": cfg.ChatModel, "embedding_model": cfg.EmbeddingModel, "article_language": cfg.ArticleLanguage, "research_ollama_max_inflight": cfg.ResearchOllamaMaxInflight, "research_ollama_queue_size": cfg.ResearchOllamaQueueSize, "graph_version": g.Version()}})
|
||||
b.Publish(model.Activity{Type: "system.started", Source: "brain", Phase: "startup", Message: "Neural Brain wurde gestartet; das Analyseprotokoll zeichnet Läufe und Graphänderungen auf", Strength: .3, Metadata: map[string]any{"chat_model": cfg.ChatModel, "embedding_model": cfg.EmbeddingModel, "article_language": cfg.ArticleLanguage, "article_synthesis_model": cfg.ArticleSynthesisModel, "article_review_model": cfg.ArticleReviewModel, "article_review_repair_rounds": cfg.ArticleReviewRepairRounds, "article_pipeline": "research_generate_review", "research_ollama_max_inflight": cfg.ResearchOllamaMaxInflight, "research_ollama_queue_size": cfg.ResearchOllamaQueueSize, "graph_version": g.Version()}})
|
||||
}
|
||||
return e
|
||||
}
|
||||
@@ -811,7 +821,11 @@ func (e *Engine) enrichOne(ctx context.Context, trigger string) (EnrichOutcome,
|
||||
researchErr = dedupeErr
|
||||
} else if !lease.owner {
|
||||
results = cloneResearchResults(reused)
|
||||
e.Broker.Publish(model.Activity{Type: "research.deduplicated", Source: "brain", Phase: "research", NodeIDs: []string{a.ID, b.ID}, Message: fmt.Sprintf("Semantisch gleiche Relationsrecherche wurde wiederverwendet · %d Treffer", len(results)), Strength: .76, Metadata: mergeResearchMetadata(startMetadata, map[string]any{"similarity": lease.similarity, "reused_results": len(results), "dedupe_threshold": e.Cfg.ResearchDedupeThreshold})})
|
||||
metadata := mergeResearchMetadata(startMetadata, map[string]any{"similarity": lease.similarity, "reused_results": len(results), "dedupe_threshold": e.Cfg.ResearchDedupeThreshold})
|
||||
for key, value := range researchDedupeLeaseMetadata(lease) {
|
||||
metadata[key] = value
|
||||
}
|
||||
e.Broker.Publish(model.Activity{Type: "research.deduplicated", Source: "brain", Phase: "research", NodeIDs: []string{a.ID, b.ID}, Message: fmt.Sprintf("Semantisch gleiche Relationsrecherche wurde wiederverwendet · %d Treffer", len(results)), Strength: .76, Metadata: metadata})
|
||||
} else {
|
||||
// Relation research intentionally considers more than the old four
|
||||
// snippets. The full article pipeline remains the final quality gate.
|
||||
@@ -860,6 +874,16 @@ func (e *Engine) enrichOne(ctx context.Context, trigger string) (EnrichOutcome,
|
||||
decision = reviewed
|
||||
}
|
||||
}
|
||||
// Always close the relation-research lifecycle explicitly. Older code
|
||||
// only emitted research.ingested when at least one source passed the
|
||||
// Thinking filter, leaving zero-result and filtered-out searches stuck
|
||||
// as "running" forever in the analysis history.
|
||||
completedMetadata := mergeResearchMetadata(resultMetadata, map[string]any{
|
||||
"duration_ms": time.Since(researchStarted).Milliseconds(),
|
||||
"accepted_count": len(allowedResults),
|
||||
"result": "completed",
|
||||
})
|
||||
e.Broker.Publish(model.Activity{Type: "research.completed", Source: "brain", Phase: "research", NodeIDs: []string{a.ID, b.ID}, Message: fmt.Sprintf("Relationsrecherche beendet · %d verwendbare Treffer", len(allowedResults)), Strength: .72, Metadata: completedMetadata})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -929,12 +953,12 @@ func (e *Engine) Status() map[string]any {
|
||||
"article_research_min_relevance": e.Cfg.ArticleResearchMinRelevance, "article_research_min_quality": e.Cfg.ArticleResearchMinQuality,
|
||||
"article_research_page_max_bytes": e.Cfg.ArticleResearchPageMaxBytes, "article_research_page_max_chars": e.Cfg.ArticleResearchPageMaxChars,
|
||||
"article_research_fetch_timeout": e.Cfg.ArticleResearchFetchTimeout.String(), "article_research_allow_private": e.Cfg.ArticleResearchAllowPrivate,
|
||||
"article_language": e.Cfg.ArticleLanguage, "research_dedupe": e.researchDedupeStatus(),
|
||||
"article_language": e.Cfg.ArticleLanguage, "article_synthesis_model": e.Cfg.ArticleSynthesisModel, "article_review_model": e.Cfg.ArticleReviewModel, "article_review_repair_rounds": e.Cfg.ArticleReviewRepairRounds, "article_pipeline": "research_generate_review", "research_dedupe": e.researchDedupeStatus(),
|
||||
"enrich_interval": e.Cfg.EnrichInterval.String(),
|
||||
"enrich_batch_size": e.Cfg.EnrichBatchSize, "enrich_anchors": e.Cfg.EnrichAnchors,
|
||||
"research_enabled": e.ResearchEnabledForRuntime(), "chat_model": e.Cfg.ChatModel, "embedding_model": e.Cfg.EmbeddingModel,
|
||||
"searxng": e.ResearchStatus(),
|
||||
"ollama_pool": e.Ollama.PoolStatus(), "persistence": e.Persistence.Status(), "graph_storage": e.Graph.StorageStatus(),
|
||||
"ollama_pool": e.Ollama.PoolStatus(), "article_model_status": map[string]any{"synthesis": e.Ollama.ModelStatus(e.Cfg.ArticleSynthesisModel), "review": e.Ollama.ModelStatus(e.Cfg.ArticleReviewModel)}, "persistence": e.Persistence.Status(), "graph_storage": e.Graph.StorageStatus(),
|
||||
"runtime_settings": e.RuntimeSettingsView(),
|
||||
}
|
||||
if e.GLPIKB != nil {
|
||||
|
||||
Reference in New Issue
Block a user