|
1 | | -"""Claim lattice expert.""" |
| 1 | +"""Claim Lattice Expert Implementation.""" |
| 2 | +from typing import Dict, Any |
| 3 | +from epistemic_forge.experts.base import EpistemicExpert |
| 4 | +from epistemic_forge.models import ProjectSpec, ClaimLatticeOutput |
| 5 | +from epistemic_forge.llm import generate_structured |
| 6 | +from loguru import logger |
2 | 7 |
|
3 | | -from __future__ import annotations |
| 8 | +class ClaimLatticeExpert(EpistemicExpert): |
| 9 | + """Deconstructs the question into a structured, epistemically grounded claim lattice.""" |
| 10 | + |
| 11 | + @property |
| 12 | + def expert_name(self) -> str: |
| 13 | + return "Epistemic_Claim_Lattice_Generator" |
4 | 14 |
|
5 | | -from typing import Any, Dict, List |
6 | | - |
7 | | -from epistemic_forge.models import Claim, Confidence, ProjectSpec |
8 | | - |
9 | | - |
10 | | -def extract_claims(spec: ProjectSpec, instruction: str) -> Dict[str, Any]: |
11 | | - q = spec.question.strip() |
12 | | - title = spec.title.strip() |
13 | | - # Deterministic structured extraction (no external LLM required) |
14 | | - core = Claim( |
15 | | - id="C1", |
16 | | - text=f"Core thesis addressing: {q}", |
17 | | - support=[ |
18 | | - f"Aligned with instruction: {instruction[:120]}...", |
19 | | - f"Keywords in play: {', '.join(spec.keywords) or 'general domain cues'}", |
20 | | - ], |
21 | | - objections=[ |
22 | | - "The framing may smuggle unstated assumptions about the audience.", |
23 | | - "Evidence quality is not yet measured; confidence should stay provisional.", |
24 | | - ], |
25 | | - confidence=Confidence.LIKELY, |
26 | | - sources=["user-question", "instruction"], |
27 | | - tags=["thesis"], |
28 | | - ) |
29 | | - support_c = Claim( |
30 | | - id="C2", |
31 | | - text=f"Working support: a structured approach to Ā«{title}Ā» improves decision quality under uncertainty.", |
32 | | - support=[ |
33 | | - "Decomposition reduces hidden tradeoffs.", |
34 | | - "Explicit objections prevent one-sided writing.", |
35 | | - ], |
36 | | - objections=["Structure without domain data can become cargo-cult rigor."], |
37 | | - confidence=Confidence.POSSIBLE, |
38 | | - tags=["support"], |
39 | | - ) |
40 | | - residual = Claim( |
41 | | - id="C3", |
42 | | - text="Residual uncertainty: which single metric or stakeholder criterion should dominate tradeoffs?", |
43 | | - support=["Multi-objective problems need a declared primary criterion."], |
44 | | - objections=["Premature metric fixation can distort the inquiry."], |
45 | | - confidence=Confidence.WEAK, |
46 | | - tags=["uncertainty"], |
47 | | - ) |
48 | | - claims: List[Claim] = [core, support_c, residual] |
49 | | - return { |
50 | | - "claims": [c.to_dict() for c in claims], |
51 | | - "lattice_summary": ( |
52 | | - "Three-node lattice: thesis, support, residual uncertainty. " |
53 | | - "Ready for dialectic stress-test and packaging." |
54 | | - ), |
55 | | - } |
| 15 | + def analyze(self, spec: ProjectSpec, context: Dict[str, Any]) -> ClaimLatticeOutput: |
| 16 | + """Forces the LLM to generate claims ONLY if it can provide a warrant/explanation.""" |
| 17 | + |
| 18 | + messages = [ |
| 19 | + { |
| 20 | + "role": "system", |
| 21 | + "content": ( |
| 22 | + "You are a rigorous analytical philosopher and scientist. Your task is to break down the user's premise into a 'Claim Lattice'. " |
| 23 | + "CRITICAL RULE: You are strictly forbidden from making ANY claim without providing an 'epistemic_warrant' (a clear logical explanation or evidence) " |
| 24 | + "and a 'potential_falsifier' (what would prove it wrong). No confident mush allowed." |
| 25 | + ) |
| 26 | + }, |
| 27 | + { |
| 28 | + "role": "user", |
| 29 | + "content": f"Core Premise: {spec.question}\nKeywords: {spec.keywords}\nDeconstruct this into rigorously grounded claims." |
| 30 | + } |
| 31 | + ] |
| 32 | + |
| 33 | + logger.debug("Dispatching to LLM for Claim Lattice Generation (Enforcing Truthfulness)...") |
| 34 | + return generate_structured( |
| 35 | + messages=messages, |
| 36 | + response_model=ClaimLatticeOutput, |
| 37 | + model=spec.target_model, |
| 38 | + api_base=spec.api_base |
| 39 | + ) |
0 commit comments