Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| import logging | |
| from app.schemas.visual_lesson import EvidenceClaim, EvidenceSource, VisualizationRequest | |
| from app.services.visual_evidence import VisualEvidenceResolver, _clean | |
| logger = logging.getLogger(__name__) | |
| CANONICAL_ODE_SOURCES = [ | |
| EvidenceSource( | |
| source_id="builtin:openstax-ode", | |
| origin="builtin", | |
| title="OpenStax Calculus Volume 2 — Introduction to Differential Equations", | |
| url="https://openstax.org/books/calculus-volume-2/pages/4-1-basics-of-differential-equations", | |
| excerpt="Canonical reference metadata for initial-value problems, solution curves, and slope fields.", | |
| authority="canonical", | |
| ), | |
| EvidenceSource( | |
| source_id="builtin:openstax-logistic", | |
| origin="builtin", | |
| title="OpenStax Calculus Volume 2 — The Logistic Equation", | |
| url="https://openstax.org/books/calculus-volume-2/pages/4-4-the-logistic-equation", | |
| excerpt="Canonical reference metadata for logistic growth, equilibria, and carrying capacity.", | |
| authority="canonical", | |
| ), | |
| ] | |
| class DifferentialEquationEvidenceResolver: | |
| def __init__(self, base: VisualEvidenceResolver | None = None) -> None: | |
| self.base = base or VisualEvidenceResolver() | |
| async def resolve(self, project_id: str, request: VisualizationRequest, family: str) -> tuple[list[EvidenceSource], list[EvidenceClaim], list[str]]: | |
| prompt = request.prompt.lower() | |
| contextual = any(term in prompt for term in ("paper", "selected", "according to", "reported model", "figure")) | |
| sources = self.base._selection_sources(request) if contextual else [] | |
| warnings: list[str] = [] | |
| if contextual and request.project_context_enabled: | |
| try: | |
| rows = await self.base._project_search(project_id, [_clean(request.prompt)], request.active_document_ids) | |
| sources.extend(self.base._candidate_sources(rows, "project")[:4]) | |
| logger.info("Differential-equation contextual evidence request=%s rows=%d", request.request_id, len(rows)) | |
| except Exception: | |
| warnings.append("The selected project context was unavailable; the stated equation and canonical mathematics were used.") | |
| else: | |
| logger.info("Differential-equation evidence canonical-only request=%s family=%s", request.request_id, family) | |
| sources.extend(CANONICAL_ODE_SOURCES) | |
| claims = [ | |
| EvidenceClaim(claim_id="ode-initial-value", text="A solution curve is determined by the differential equation together with its initial conditions.", claim_type="standard_definition", support_level="canonical", source_ids=["builtin:openstax-ode"]), | |
| EvidenceClaim(claim_id="ode-direction-field", text="A direction field displays the local derivative prescribed by a first-order differential equation.", claim_type="standard_definition", support_level="canonical", source_ids=["builtin:openstax-ode"]), | |
| EvidenceClaim(claim_id="ode-logistic", text="The logistic equation has equilibrium states at 0 and K, with maximum positive growth at K/2 when r and K are positive.", claim_type="standard_definition", support_level="canonical", source_ids=["builtin:openstax-logistic"]), | |
| EvidenceClaim(claim_id="ode-numerical-method", text="The damped-oscillator trajectory is compiled with a fixed-step fourth-order Runge–Kutta method.", claim_type="derived_fact", support_level="derived", source_ids=[]), | |
| ] | |
| return sources, claims, warnings | |