"""Simple LLM helper for workbooks using Mirascope.""" import os from typing import TypeVar from mirascope.core import Messages, openai from pydantic import BaseModel T = TypeVar("T", bound=BaseModel) # Configure from environment (defaults match .env.example) _api_key = os.getenv("LLM_API_KEY", "") _base_url = os.getenv("LLM_API_URL", "https://litellm-notrack.app.monadical.io") _model = os.getenv("LLM_MODEL", "GLM-4.5-Air-FP8-dev") if _api_key: os.environ["OPENAI_API_KEY"] = _api_key if _base_url: base = _base_url.rstrip("/") os.environ["OPENAI_BASE_URL"] = base if base.endswith("/v1") else f"{base}/v1" async def llm_call( prompt: str, response_model: type[T], system_prompt: str = "You are a helpful assistant.", model: str | None = None, ) -> T: """Make a structured LLM call. Args: prompt: The user prompt response_model: Pydantic model for structured output system_prompt: System instructions model: Override the default model Returns: Parsed response matching the response_model schema """ use_model = model or _model @openai.call(model=use_model, response_model=response_model) async def _call(sys: str, usr: str) -> openai.OpenAIDynamicConfig: return { "messages": [ Messages.System(sys), Messages.User(usr), ] } return await _call(system_prompt, prompt)