09-agentic-workflow-sys / src /model_assist.py
FlyingNunchucks's picture
Sync from GitHub via hub-sync
ef4748f verified
Raw History Blame Contribute Delete
3.26 kB
"""Bounded model assistance for the synthetic wealth-onboarding workflow.
The model may organize onboarding notes and propose only a household profile category
plus a concise summary. Application code controls prompt inputs, parses strict JSON,
validates the proposal with Pydantic, and returns normalized data to the workflow.
The model never receives or controls workflow state, exception routing, handler
identifiers, retry limits, document rules, identity-review status, or human decisions.
"""
from __future__ import annotations
from enum import Enum
from typing import Callable
from pydantic import BaseModel, ConfigDict, Field, ValidationError
ModelCall = Callable[[str], str]
class HouseholdProfileCategory(str, Enum):
STANDARD_HOUSEHOLD = "STANDARD_HOUSEHOLD"
COMPLEX_HOUSEHOLD = "COMPLEX_HOUSEHOLD"
SPECIAL_STRUCTURE = "SPECIAL_STRUCTURE"
class OnboardingAIProposal(BaseModel):
"""Strict structured output accepted from the onboarding model boundary."""
model_config = ConfigDict(extra="forbid", str_strip_whitespace=True)
profile_category: HouseholdProfileCategory
summary: str = Field(min_length=1, max_length=400)
class ModelOnboardingError(ValueError):
"""Raised when model output cannot be accepted as a bounded proposal."""
def build_onboarding_prompt(*, household_type: str, onboarding_notes: str) -> str:
"""Build a minimal prompt containing only information needed for intake organization."""
return (
"Organize this fictional wealth-management onboarding intake. Return ONLY a JSON "
"object with exactly two fields: profile_category and summary. "
"profile_category must be exactly one of STANDARD_HOUSEHOLD, COMPLEX_HOUSEHOLD, "
"SPECIAL_STRUCTURE. summary must be a concise plain-text intake summary. "
"Do not recommend approval, rejection, routing, account opening, or any workflow action.\n\n"
f"household_type: {household_type}\n"
f"onboarding_notes: {onboarding_notes}"
)
def organize_onboarding_with_model(
model_call: ModelCall,
*,
household_type: str,
onboarding_notes: str,
) -> dict[str, str]:
"""Call a model and strictly validate its bounded onboarding proposal.
Errors are deliberately sanitized because executor error text is included in
control-plane audit events. Rejected model output is never copied into those events.
"""
prompt = build_onboarding_prompt(
household_type=household_type,
onboarding_notes=onboarding_notes,
)
try:
raw_response = model_call(prompt)
except Exception as exc:
raise ModelOnboardingError("model onboarding call failed") from exc
if not isinstance(raw_response, str) or not raw_response.strip():
raise ModelOnboardingError("model response must be a non-blank JSON string")
try:
proposal = OnboardingAIProposal.model_validate_json(raw_response)
except (ValidationError, ValueError) as exc:
raise ModelOnboardingError(
"model onboarding output failed schema validation"
) from exc
return {
"profile_category": proposal.profile_category.value,
"summary": proposal.summary,
"source": "MODEL_ASSISTED",
}