Compare commits
No commits in common. "f593dd060b82a52047f3b55601796482517ff288" and "ece245541577a0ebd35fc8419a057a14b1611f45" have entirely different histories.
f593dd060b
...
ece2455415
4 changed files with 1 additions and 111 deletions
|
|
@ -19,7 +19,6 @@ from researchers.web.models import (
|
||||||
DiscoveryEvent,
|
DiscoveryEvent,
|
||||||
Gap,
|
Gap,
|
||||||
GapCategory,
|
GapCategory,
|
||||||
OpenQuestion,
|
|
||||||
ResearchConstraints,
|
ResearchConstraints,
|
||||||
ResearchResult,
|
ResearchResult,
|
||||||
)
|
)
|
||||||
|
|
@ -94,14 +93,6 @@ Produce a JSON object with these exact fields:
|
||||||
"source_locator": "URL where you found this, or null"
|
"source_locator": "URL where you found this, or null"
|
||||||
}}
|
}}
|
||||||
],
|
],
|
||||||
"open_questions": [
|
|
||||||
{{
|
|
||||||
"question": "A follow-up question that emerged from the research",
|
|
||||||
"context": "What evidence prompted this question",
|
|
||||||
"priority": "high|medium|low",
|
|
||||||
"source_locator": "URL where this question arose, or null"
|
|
||||||
}}
|
|
||||||
],
|
|
||||||
"confidence": 0.0-1.0,
|
"confidence": 0.0-1.0,
|
||||||
"confidence_factors": {{
|
"confidence_factors": {{
|
||||||
"num_corroborating_sources": 0,
|
"num_corroborating_sources": 0,
|
||||||
|
|
@ -515,16 +506,6 @@ class WebResearcher:
|
||||||
for d in data.get("discovery_events", [])
|
for d in data.get("discovery_events", [])
|
||||||
]
|
]
|
||||||
|
|
||||||
open_questions = [
|
|
||||||
OpenQuestion(
|
|
||||||
question=q.get("question", ""),
|
|
||||||
context=q.get("context", ""),
|
|
||||||
priority=q.get("priority", "medium"),
|
|
||||||
source_locator=q.get("source_locator"),
|
|
||||||
)
|
|
||||||
for q in data.get("open_questions", [])
|
|
||||||
]
|
|
||||||
|
|
||||||
cf = data.get("confidence_factors", {})
|
cf = data.get("confidence_factors", {})
|
||||||
confidence_factors = ConfidenceFactors(
|
confidence_factors = ConfidenceFactors(
|
||||||
num_corroborating_sources=cf.get("num_corroborating_sources", 0),
|
num_corroborating_sources=cf.get("num_corroborating_sources", 0),
|
||||||
|
|
@ -540,7 +521,6 @@ class WebResearcher:
|
||||||
citations=citations,
|
citations=citations,
|
||||||
gaps=gaps,
|
gaps=gaps,
|
||||||
discovery_events=discovery_events,
|
discovery_events=discovery_events,
|
||||||
open_questions=open_questions,
|
|
||||||
confidence=data.get("confidence", 0.5),
|
confidence=data.get("confidence", 0.5),
|
||||||
confidence_factors=confidence_factors,
|
confidence_factors=confidence_factors,
|
||||||
cost_metadata=CostMetadata(
|
cost_metadata=CostMetadata(
|
||||||
|
|
|
||||||
|
|
@ -132,35 +132,6 @@ class DiscoveryEvent(BaseModel):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# Output types — OpenQuestion
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
class OpenQuestion(BaseModel):
|
|
||||||
"""A follow-up question that emerged from the research.
|
|
||||||
|
|
||||||
Distinct from gaps (what failed) and discovery events (what's lateral).
|
|
||||||
Open questions look forward: "based on what I found, this needs deeper
|
|
||||||
investigation." The PI uses these to decide whether to dispatch
|
|
||||||
additional research calls.
|
|
||||||
"""
|
|
||||||
|
|
||||||
question: str = Field(
|
|
||||||
description="The follow-up question that emerged from the research.",
|
|
||||||
)
|
|
||||||
context: str = Field(
|
|
||||||
description="What evidence or finding prompted this question.",
|
|
||||||
)
|
|
||||||
priority: str = Field(
|
|
||||||
description="'high' (critical to answer quality), 'medium' (would improve answer), 'low' (nice to know).",
|
|
||||||
)
|
|
||||||
source_locator: Optional[str] = Field(
|
|
||||||
default=None,
|
|
||||||
description="URL or source where this question arose from.",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Output types — Confidence
|
# Output types — Confidence
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
@ -244,10 +215,6 @@ class ResearchResult(BaseModel):
|
||||||
default_factory=list,
|
default_factory=list,
|
||||||
description="Lateral findings for other researchers.",
|
description="Lateral findings for other researchers.",
|
||||||
)
|
)
|
||||||
open_questions: list[OpenQuestion] = Field(
|
|
||||||
default_factory=list,
|
|
||||||
description="Follow-up questions that emerged from the research.",
|
|
||||||
)
|
|
||||||
confidence: float = Field(
|
confidence: float = Field(
|
||||||
ge=0.0,
|
ge=0.0,
|
||||||
le=1.0,
|
le=1.0,
|
||||||
|
|
|
||||||
|
|
@ -70,14 +70,6 @@ VALID_SYNTHESIS_JSON = json.dumps(
|
||||||
"source_locator": "https://example.com/ref",
|
"source_locator": "https://example.com/ref",
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"open_questions": [
|
|
||||||
{
|
|
||||||
"question": "What is the optimal irrigation schedule for high-elevation potatoes?",
|
|
||||||
"context": "Multiple sources mention irrigation is critical but none specify schedules.",
|
|
||||||
"priority": "medium",
|
|
||||||
"source_locator": "https://example.com/utah-crops",
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"confidence": 0.82,
|
"confidence": 0.82,
|
||||||
"confidence_factors": {
|
"confidence_factors": {
|
||||||
"num_corroborating_sources": 3,
|
"num_corroborating_sources": 3,
|
||||||
|
|
@ -205,8 +197,6 @@ class TestWebResearcher:
|
||||||
assert len(result.gaps) == 1
|
assert len(result.gaps) == 1
|
||||||
assert result.gaps[0].category == "source_not_found"
|
assert result.gaps[0].category == "source_not_found"
|
||||||
assert len(result.discovery_events) == 1
|
assert len(result.discovery_events) == 1
|
||||||
assert len(result.open_questions) == 1
|
|
||||||
assert "irrigation" in result.open_questions[0].question
|
|
||||||
assert result.confidence == 0.82
|
assert result.confidence == 0.82
|
||||||
assert result.confidence_factors.num_corroborating_sources == 3
|
assert result.confidence_factors.num_corroborating_sources == 3
|
||||||
assert result.cost_metadata.model_id == "claude-test"
|
assert result.cost_metadata.model_id == "claude-test"
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ from researchers.web.models import (
|
||||||
DiscoveryEvent,
|
DiscoveryEvent,
|
||||||
Gap,
|
Gap,
|
||||||
GapCategory,
|
GapCategory,
|
||||||
OpenQuestion,
|
|
||||||
ResearchConstraints,
|
ResearchConstraints,
|
||||||
ResearchResult,
|
ResearchResult,
|
||||||
)
|
)
|
||||||
|
|
@ -59,17 +58,6 @@ def make_discovery_event(**overrides) -> DiscoveryEvent:
|
||||||
return DiscoveryEvent(**defaults)
|
return DiscoveryEvent(**defaults)
|
||||||
|
|
||||||
|
|
||||||
def make_open_question(**overrides) -> OpenQuestion:
|
|
||||||
defaults = {
|
|
||||||
"question": "What is the optimal irrigation schedule for high-elevation potatoes?",
|
|
||||||
"context": "Multiple sources mention irrigation is critical but none specify schedules.",
|
|
||||||
"priority": "medium",
|
|
||||||
"source_locator": "https://example.com/utah-crops",
|
|
||||||
}
|
|
||||||
defaults.update(overrides)
|
|
||||||
return OpenQuestion(**defaults)
|
|
||||||
|
|
||||||
|
|
||||||
def make_confidence_factors(**overrides) -> ConfidenceFactors:
|
def make_confidence_factors(**overrides) -> ConfidenceFactors:
|
||||||
defaults = {
|
defaults = {
|
||||||
"num_corroborating_sources": 3,
|
"num_corroborating_sources": 3,
|
||||||
|
|
@ -101,7 +89,6 @@ def make_research_result(**overrides) -> ResearchResult:
|
||||||
"citations": [make_citation()],
|
"citations": [make_citation()],
|
||||||
"gaps": [make_gap()],
|
"gaps": [make_gap()],
|
||||||
"discovery_events": [make_discovery_event()],
|
"discovery_events": [make_discovery_event()],
|
||||||
"open_questions": [make_open_question()],
|
|
||||||
"confidence": 0.82,
|
"confidence": 0.82,
|
||||||
"confidence_factors": make_confidence_factors(),
|
"confidence_factors": make_confidence_factors(),
|
||||||
"cost_metadata": make_cost_metadata(),
|
"cost_metadata": make_cost_metadata(),
|
||||||
|
|
@ -263,33 +250,6 @@ class TestDiscoveryEvent:
|
||||||
assert e == e2
|
assert e == e2
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# OpenQuestion
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
class TestOpenQuestion:
|
|
||||||
def test_full_question(self):
|
|
||||||
q = make_open_question()
|
|
||||||
assert "irrigation" in q.question
|
|
||||||
assert q.priority == "medium"
|
|
||||||
assert q.source_locator is not None
|
|
||||||
|
|
||||||
def test_minimal_question(self):
|
|
||||||
q = OpenQuestion(
|
|
||||||
question="Is this viable?",
|
|
||||||
context="Found conflicting data.",
|
|
||||||
priority="low",
|
|
||||||
)
|
|
||||||
assert q.source_locator is None
|
|
||||||
|
|
||||||
def test_serialization_roundtrip(self):
|
|
||||||
q = make_open_question()
|
|
||||||
data = q.model_dump()
|
|
||||||
q2 = OpenQuestion(**data)
|
|
||||||
assert q == q2
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# ConfidenceFactors
|
# ConfidenceFactors
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
@ -365,18 +325,16 @@ class TestResearchResult:
|
||||||
assert len(r.citations) == 1
|
assert len(r.citations) == 1
|
||||||
assert len(r.gaps) == 1
|
assert len(r.gaps) == 1
|
||||||
assert len(r.discovery_events) == 1
|
assert len(r.discovery_events) == 1
|
||||||
assert len(r.open_questions) == 1
|
|
||||||
assert 0.0 <= r.confidence <= 1.0
|
assert 0.0 <= r.confidence <= 1.0
|
||||||
assert r.cost_metadata.model_id == "claude-sonnet-4-6"
|
assert r.cost_metadata.model_id == "claude-sonnet-4-6"
|
||||||
|
|
||||||
def test_empty_lists_allowed(self):
|
def test_empty_lists_allowed(self):
|
||||||
r = make_research_result(
|
r = make_research_result(
|
||||||
citations=[], gaps=[], discovery_events=[], open_questions=[]
|
citations=[], gaps=[], discovery_events=[]
|
||||||
)
|
)
|
||||||
assert r.citations == []
|
assert r.citations == []
|
||||||
assert r.gaps == []
|
assert r.gaps == []
|
||||||
assert r.discovery_events == []
|
assert r.discovery_events == []
|
||||||
assert r.open_questions == []
|
|
||||||
|
|
||||||
def test_confidence_bounds(self):
|
def test_confidence_bounds(self):
|
||||||
with pytest.raises(ValidationError):
|
with pytest.raises(ValidationError):
|
||||||
|
|
@ -400,7 +358,6 @@ class TestResearchResult:
|
||||||
"citations",
|
"citations",
|
||||||
"gaps",
|
"gaps",
|
||||||
"discovery_events",
|
"discovery_events",
|
||||||
"open_questions",
|
|
||||||
"confidence",
|
"confidence",
|
||||||
"confidence_factors",
|
"confidence_factors",
|
||||||
"cost_metadata",
|
"cost_metadata",
|
||||||
|
|
@ -408,10 +365,6 @@ class TestResearchResult:
|
||||||
}
|
}
|
||||||
assert set(data.keys()) == expected_keys
|
assert set(data.keys()) == expected_keys
|
||||||
|
|
||||||
# OpenQuestion keys
|
|
||||||
oq_keys = {"question", "context", "priority", "source_locator"}
|
|
||||||
assert set(data["open_questions"][0].keys()) == oq_keys
|
|
||||||
|
|
||||||
# Citation keys
|
# Citation keys
|
||||||
citation_keys = {
|
citation_keys = {
|
||||||
"source",
|
"source",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue