feature/knowledge-curation #91

Merged
cameron merged 19 commits from feature/knowledge-curation into master 2026-05-12 15:40:57 +00:00
Showing only changes of commit f200466508 - Show all commits

View File

@@ -720,7 +720,9 @@ async fn synthesize_merge<D: KnowledgeDao + 'static>(
entities refer to the same real-world thing and are about to be merged. Write a \
single neutral third-person description (1-2 sentences, max 300 chars) that \
preserves any concrete facts in either source. Do not invent details. Do not \
editorialize. Return ONLY the merged description — no preamble, no quotes.";
editorialize. Plain prose only — no markdown, no bold, no italics, no headings, \
no bullets, no lists, no code fences. Return ONLY the merged description — no \
preamble, no labels, no quotes.";
let prompt = format!(
"Entity A: {} [{}]\nDescription: {}\n\nEntity B: {} [{}]\nDescription: {}\n\nMerged description:",
source.name, source.entity_type, source_desc,
@@ -731,15 +733,46 @@ async fn synthesize_merge<D: KnowledgeDao + 'static>(
let model_used = ollama.primary_model.clone();
let proposed = match ollama.generate(&prompt, Some(system)).await {
Ok(out) => {
// Some models open with their own framing — strip a
// leading quote or "Merged:" lead-in defensively.
let cleaned = out
.trim()
// Strip the framing models reach for even with explicit
// "no preamble" guidance: leading "Merged description:"
// labels, wrapping quotes, ``` code fences, leading
// bullets / hash headings. Belt-and-braces against the
// system prompt's plain-text directive.
let mut s = out.trim().to_string();
s = s
.trim_start_matches("Merged description:")
.trim_start_matches("Merged Description:")
.trim()
.to_string();
// Code fences (``` or ```text)
s = s
.trim_start_matches("```text")
.trim_start_matches("```markdown")
.trim_start_matches("```")
.trim_end_matches("```")
.trim()
.to_string();
// Markdown headings / bullets at the very start
while let Some(stripped) = s
.strip_prefix('#')
.or_else(|| s.strip_prefix('*'))
.or_else(|| s.strip_prefix('-'))
.or_else(|| s.strip_prefix('>'))
{
s = stripped.trim_start().to_string();
}
// Wrapping quotes
s = s
.trim_matches(|c| c == '"' || c == '\'')
.to_string();
cleaned
// Inline emphasis: drop standalone `**` / `*` / `__` /
// `_` markers without trying to parse markdown — just
// remove the punctuation. Rare enough that this naive
// replace is fine.
s = s
.replace("**", "")
.replace("__", "");
s
}
Err(e) => {
log::warn!("synthesize_merge generate failed: {:?}", e);