feat: score ingest facet suggestions with Jev
CI / quality (push) Canceled after 0s

This commit is contained in:
vasily committed 2026-10-14 20:43:09 +08:00
1 parent 7b2c43ddaf
commit 0e1a2ad008
8 files changed
+191 -27

No files matched your search

+68 -22
View File
@@ -8,7 +8,13 @@ from typing import Any, cast
from urllib.error import HTTPError, URLError
from urllib.request import HTTPRedirectHandler, Request, build_opener
from gewu.domain.contracts import IngestReviewCreate, ProjectRecord, ResearchLens
from gewu.domain.contracts import (
FacetName,
IngestReviewCreate,
JevFacetScore,
ProjectRecord,
ResearchLens,
)
ENDPOINT = "https://openrouter.ai/api/alpha/decisions"
MODEL = "typesafe/jev-1.13"
@@ -21,6 +27,7 @@ class JevAssessment:
lens: ResearchLens
lens_confidence: float
model: str
facet_scores: tuple[JevFacetScore, ...] = ()
class JevUnavailable(RuntimeError):
@@ -44,6 +51,30 @@ class OpenRouterJev:
self._model = model
def assess(self, item: IngestReviewCreate, project: ProjectRecord) -> JevAssessment:
facet_candidates: tuple[tuple[FacetName, tuple[str, ...]], ...] = (
("tags", item.candidate_tags),
("audience", item.candidate_audience),
("use_for", item.candidate_use_for),
("domain", item.candidate_domain),
)
facet_questions: dict[str, object] = {}
facet_question_map: dict[str, tuple[FacetName, str]] = {}
for facet, candidates in facet_candidates:
for index, value in enumerate(candidates):
key = f"facet_{facet}_{index}"
facet_question_map[key] = (facet, value)
facet_questions[key] = {
"type": "noul",
"instructions": (
f"Does the candidate {facet} label accurately describe the passage "
"in the context of this project? Judge the label itself, not just "
"whether its words appear in the excerpt."
),
"criteria": {
"true": "This label is a useful, well-supported classification.",
"false": "This label is inaccurate, unsupported, or too broad.",
},
}
state = {
"project_title": project.title,
"project_north_star": project.north_star,
@@ -52,6 +83,9 @@ class OpenRouterJev:
"candidate_summary": item.summary,
"candidate_relevance_rationale": item.relevance_rationale,
"source_excerpt": item.excerpt,
"candidate_facets": {
facet: candidates for facet, candidates in facet_candidates if candidates
},
}
criteria = {
"technical": "Engineering, implementation, technology, or operational practice.",
@@ -59,30 +93,32 @@ class OpenRouterJev:
"cultural-historical": "Cultural, artistic, historical, social, or audience context.",
"financial-market": "Costs, revenues, business models, markets, or financing.",
}
questions: dict[str, object] = {
"project_relation": {
"type": "noul",
"instructions": (
"Does this passage help answer a project question or explain "
"the project's technical, conceptual, cultural-historical, or "
"financial-market context? Treat indirect context as relevant when "
"the connection is plausible."
),
"criteria": {
"true": "A plausible, specific connection to the project exists.",
"false": "The passage has no plausible project connection.",
},
},
"best_lens": {
"type": "choice",
"instructions": "Which project research lens best describes this passage?",
"criteria": criteria,
},
**facet_questions,
}
payload = json.dumps(
{
"model": self._model,
"state": state,
"questions": {
"project_relation": {
"type": "noul",
"instructions": (
"Does this passage help answer a project question or explain "
"the project's technical, conceptual, cultural-historical, or "
"financial-market context? Treat indirect context as relevant when "
"the connection is plausible."
),
"criteria": {
"true": "A plausible, specific connection to the project exists.",
"false": "The passage has no plausible project connection.",
},
},
"best_lens": {
"type": "choice",
"instructions": "Which project research lens best describes this passage?",
"criteria": criteria,
},
},
"questions": questions,
},
ensure_ascii=False,
separators=(",", ":"),
@@ -113,6 +149,14 @@ class OpenRouterJev:
lens = answers["best_lens"]["choice"]
confidence = float(answers["best_lens"]["confidence"])
served_model = str(result["model"])
facet_scores = tuple(
JevFacetScore(
facet=facet,
value=value,
probability=float(answers[key]["noul"]),
)
for key, (facet, value) in facet_question_map.items()
)
except (KeyError, TypeError, ValueError, json.JSONDecodeError) as error:
raise JevUnavailable("Jev response did not match its typed decision schema") from error
if (
@@ -122,4 +166,6 @@ class OpenRouterJev:
or len(served_model) > 100
):
raise JevUnavailable("Jev response contained an invalid decision")
return JevAssessment(relation, cast(ResearchLens, lens), confidence, served_model)
return JevAssessment(
relation, cast(ResearchLens, lens), confidence, served_model, facet_scores
)