diff --git a/src/services/wiki_page_writer.py b/src/services/wiki_page_writer.py index 1307d34..e402a4c 100644 --- a/src/services/wiki_page_writer.py +++ b/src/services/wiki_page_writer.py @@ -131,8 +131,8 @@ class WikiPageWriter: conflicts=conflicts ) - # Reconstruct with LLM - reconstructed = await self._call_llm(prompt) + # Reconstruct with LLM (lower temperature for precise merging) + reconstructed = await self._call_llm(prompt, temperature=0.2) # Ensure standard sections are present reconstructed = self._ensure_standard_sections( @@ -155,7 +155,7 @@ class WikiPageWriter: Returns: List of conflicts with: {fact_a, fact_b, confidence, context} """ - prompt = f"""Analyze these two pieces of content for factual conflicts. + prompt = f"""Analyze these contents for direct factual conflicts. EXISTING CONTENT: {existing_content[:2000]} @@ -163,25 +163,26 @@ EXISTING CONTENT: NEW INFORMATION: {new_information[:2000]} -Identify any facts that contradict each other. For each conflict, provide: -1. The fact from existing content -2. The contradicting fact from new information -3. Confidence level (low/medium/high) -4. Context/explanation +ANALYSIS STEPS: +1. Identify specific factual claims in existing content (dates, numbers, names, states) +2. Identify specific factual claims in new content +3. Compare ONLY for direct contradictions (X says A, Y says not-A) -Return ONLY valid JSON: +RULES: +- Do NOT flag differences in wording or phrasing as conflicts +- Do NOT flag new/additional information as conflicts +- Do NOT flag opinion differences as conflicts +- ONLY flag direct factual contradictions +- Return valid JSON only, no commentary + +Return format: {{ "conflicts": [ - {{ - "existing_fact": "fact from old content", - "new_fact": "contradicting fact", - "confidence": "medium", - "context": "explanation of why these conflict" - }} + {{"existing_fact": "...", "new_fact": "...", "confidence": "low/medium/high", "context": "..."}} ] }} -If no conflicts, return: {{"conflicts": []}} +If no conflicts: {{"conflicts": []}} JSON:""" @@ -189,7 +190,8 @@ JSON:""" response = await self.ollama.generate_text( prompt=prompt, model=self.model, - stream=False + stream=False, + temperature=0.0 # Deterministic for consistent conflict detection ) # Extract JSON @@ -348,6 +350,13 @@ FORMATTING RULES: - Keep sections focused and scannable - Adapt structure to content - not all sections apply to all topics +CRITICAL CONSTRAINTS: +- Do NOT invent facts not present in the source information above +- Do NOT add speculative information or assumptions +- Do NOT fill sections with placeholder text or generic statements +- If information for a section is not available, OMIT the section entirely +- Base ALL content strictly on provided source information + Generate ONLY the markdown content (do not include Sources, Knowledge Graph, or Mind Map sections - those are added automatically). MARKDOWN:""" @@ -403,6 +412,13 @@ FORMATTING RULES: - Bold important terms - Add subsections (###) where it improves clarity +CRITICAL CONSTRAINTS: +- Do NOT rephrase facts in ways that change their meaning +- Do NOT remove ANY information unless explicitly superseded by newer facts +- Do NOT add information not present in existing content or new information +- Preserve exact quotes, dates, numbers, and names verbatim +- Do NOT fill gaps with assumptions or general knowledge + OUTPUT INSTRUCTIONS: - Return complete page content (do not include Sources, Knowledge Graph, Mind Map - those are added automatically) - Include updated "Changes & Updates" section noting what was changed today @@ -410,13 +426,21 @@ OUTPUT INSTRUCTIONS: RECONSTRUCTED MARKDOWN:""" - async def _call_llm(self, prompt: str) -> str: - """Call LLM with prompt and return response.""" + async def _call_llm(self, prompt: str, temperature: float = 0.3) -> str: + """ + Call LLM with prompt and return response. + + Args: + prompt: The prompt text + temperature: Sampling temperature (0.0=deterministic, higher=creative) + Default 0.3 for controlled but natural content generation + """ try: response = await self.ollama.generate_text( prompt=prompt, model=self.model, - stream=False + stream=False, + temperature=temperature ) if not response: