Download backend/app/qualifier_models.py from Seth0330/qualifier: direct link, hf CLI and curl.
- Browser
- Download file 7.03 kB
-
https://huggingface.co/spaces/Seth0330/qualifier/resolve/main/backend/app/qualifier_models.py
- Command line
-
hf download hf://spaces/Seth0330/qualifier/backend/app/qualifier_models.py
-
curl -L -o qualifier_models.py https://huggingface.co/spaces/Seth0330/qualifier/resolve/main/backend/app/qualifier_models.py
7.03 kB
| """ | |
| Pydantic models for the RFQ Qualifier agent — skill CRUD (mirrors ChatAgentSkill* in models.py | |
| one-for-one, but kept as its own independent set per the "separate skill system per agent" | |
| decision) plus the qualification-run request/response and the structured decision schema the | |
| agent's final tool call must satisfy. | |
| """ | |
| from pydantic import BaseModel, Field | |
| from typing import Optional, List, Literal | |
| # --------------------------------------------------------------------------- | |
| # Skill CRUD — same anatomy as ChatAgentSkill* in models.py (name/description/instructions, | |
| # references/assets/templates/scripts/evals), independent request models per the "separate copy | |
| # per agent" decision. | |
| # --------------------------------------------------------------------------- | |
| class QualifierSkillReferenceItem(BaseModel): | |
| title: str = Field("", max_length=300) | |
| content: str = Field("", max_length=20000) | |
| class QualifierSkillAssetItem(BaseModel): | |
| name: str = Field("", max_length=300) | |
| content: str = Field("", max_length=20000) | |
| class QualifierSkillTemplateItem(BaseModel): | |
| name: str = Field("", max_length=300) | |
| content: str = Field("", max_length=20000) | |
| class QualifierSkillScriptItem(BaseModel): | |
| # The live background agent never executes this content. An admin can run it explicitly via | |
| # the sandboxed /scripts/{index}/run route (subprocess-isolated, secrets stripped, timed out) — | |
| # see qualifier_script_runner.py. | |
| name: str = Field("", max_length=300) | |
| description: str = Field("", max_length=2000) | |
| language: str = Field("", max_length=40) | |
| content: str = Field("", max_length=20000) | |
| last_run_status: Optional[str] = None | |
| last_run_output: Optional[str] = None | |
| last_run_at: Optional[str] = None | |
| class QualifierSkillEvalItem(BaseModel): | |
| """Unlike the chat agent's evals (a prompt + text assertion), a qualifier eval runs a real | |
| stored sample RFQ (input_ref points at a QualifierRun or an uploaded fixture) through the full | |
| pipeline and checks the resulting decision — closer to a regression test than a prompt probe.""" | |
| name: str = Field("", max_length=300) | |
| input_ref: str = Field( | |
| "", max_length=500, description="Reference to the fixture input, e.g. 'fixture:120-bloor-st-e.eml'" | |
| ) | |
| expected_decision: Optional[Literal["qualify", "disqualify", "needs_review"]] = None | |
| expected_project_type: Optional[Literal["modernization", "new_construction", "unknown"]] = None | |
| assertion_type: Literal["decision_equals", "must_contain", "must_not_contain", "llm_judge"] = "decision_equals" | |
| assertion_value: str = Field("", max_length=2000) | |
| last_run_status: Optional[str] = None | |
| last_run_detail: Optional[str] = None | |
| last_run_at: Optional[str] = None | |
| class QualifierSkillCreateRequest(BaseModel): | |
| name: str = Field(..., min_length=1, max_length=200) | |
| description: str = Field("", max_length=1000) | |
| instructions: str = Field(..., min_length=1, max_length=14000) | |
| references: List[QualifierSkillReferenceItem] = Field(default_factory=list, max_length=20) | |
| assets: List[QualifierSkillAssetItem] = Field(default_factory=list, max_length=20) | |
| templates: List[QualifierSkillTemplateItem] = Field(default_factory=list, max_length=20) | |
| scripts: List[QualifierSkillScriptItem] = Field(default_factory=list, max_length=20) | |
| evals: List[QualifierSkillEvalItem] = Field(default_factory=list, max_length=20) | |
| class QualifierSkillPatchRequest(BaseModel): | |
| name: Optional[str] = Field(None, min_length=1, max_length=200) | |
| description: Optional[str] = Field(None, max_length=1000) | |
| instructions: Optional[str] = Field(None, min_length=1, max_length=14000) | |
| references: Optional[List[QualifierSkillReferenceItem]] = Field(None, max_length=20) | |
| assets: Optional[List[QualifierSkillAssetItem]] = Field(None, max_length=20) | |
| templates: Optional[List[QualifierSkillTemplateItem]] = Field(None, max_length=20) | |
| scripts: Optional[List[QualifierSkillScriptItem]] = Field(None, max_length=20) | |
| evals: Optional[List[QualifierSkillEvalItem]] = Field(None, max_length=20) | |
| is_active: Optional[bool] = None | |
| sort_order: Optional[int] = None | |
| class QualifierSkillImportRequest(BaseModel): | |
| content: str = Field(..., min_length=1, max_length=100000) | |
| # --------------------------------------------------------------------------- | |
| # Qualification run — the structured decision object is what the agent's final forced tool call | |
| # ("submit_qualification_decision") must produce; OpenAI-style tool-calling validates the call | |
| # arguments against this shape at generation time, so this schema doubles as the tool's JSON Schema | |
| # (see qualifier_agent.py's DECISION_TOOL_SCHEMA, built from this model) and as the API response | |
| # model / QualifierRun.result_json shape. | |
| # --------------------------------------------------------------------------- | |
| class QualifierMatchedItem(BaseModel): | |
| item: str = Field(..., max_length=500, description="The RFQ line item as described in the spec") | |
| category: str = Field( | |
| ..., | |
| max_length=100, | |
| description="door_operator | clutch | panel_adaptor | car_door_panel | roller_guide | governor | car_safety | door_protective_device | other_in_scope", | |
| ) | |
| match: Literal["exact", "ambiguous"] = "exact" | |
| catalog_ref: Optional[str] = Field(None, max_length=200, description="Matched pricelist catalog code, if exact") | |
| note: str = Field("", max_length=1000) | |
| class QualifierExcludedItem(BaseModel): | |
| item: str = Field(..., max_length=500) | |
| reason: str = Field(..., max_length=300, description="Short out-of-scope category, e.g. 'motor', 'controller', 'cab_interior', 'wiring'") | |
| class QualifierDecision(BaseModel): | |
| qualify: Literal["qualify", "disqualify", "needs_review"] | |
| project_type: Literal["modernization", "new_construction", "unknown"] | |
| matched_items: List[QualifierMatchedItem] = Field(default_factory=list) | |
| excluded_items: List[QualifierExcludedItem] = Field(default_factory=list) | |
| flags: List[str] = Field(default_factory=list, description="e.g. 'needs_engineering_review', 'missing_deadline', 'competitor_already_awarded'") | |
| deadline: Optional[str] = Field(None, max_length=100, description="Stated bid/quote deadline, as found in the RFQ, or null if not stated") | |
| project_name: str = Field("", max_length=300) | |
| reasoning: str = Field(..., max_length=4000, description="Why this decision, referencing the qualify policy") | |
| confidence: float = Field(..., ge=0.0, le=1.0) | |
| class QualifierRunResponse(BaseModel): | |
| id: int | |
| status: Literal["running", "complete", "error"] | |
| decision: Optional[str] = None | |
| project_type: Optional[str] = None | |
| confidence: Optional[float] = None | |
| result: Optional[QualifierDecision] = None | |
| error_detail: Optional[str] = None | |
| project_name: str = "" | |
| sender_email: str = "" | |
| input_filename: str = "" | |
| total_tokens: int = 0 | |
| started_at: Optional[str] = None | |
| finished_at: Optional[str] = None | |