derp.ai – AI Client¶
AI client wrapping OpenAI-compatible providers.
- class derp.ai.AIClient[source]¶
Bases:
objectAsync AI client wrapping several providers.
Example:
config = AIConfig(api_key="...") ai = AIClient(config) response = await ai.chat( model="gpt-4o-mini", messages=[{"role": "user", "content": "Hello"}], )
- async chat(model, *, messages, tools=(), **kwargs)[source]¶
Create a chat completion.
- Parameters:
- Returns:
ChatResponse with content, usage, and protocol adapters.
- Return type:
- async stream_chat(model, *, messages, tools=(), **kwargs)[source]¶
Create a streaming chat completion.
- Parameters:
- Yields:
ChatChunk for each text delta. The final chunk includes parsed tool_calls when the model invokes tools.
- Return type:
- async stream_agent(model, *, messages, tools=(), tool_args=(), max_turns=10, **kwargs)[source]¶
Stream a chat completion loop, auto-executing tool calls.
Streams via
stream_chat()in a loop. Text deltas are yielded as they arrive. When the model returns tool calls, each tool is executed via itsrun()method, results are appended as tool messages, and the next round starts automatically.The loop continues until the model returns a text response (no tool calls) or max_turns is reached.
- Parameters:
model (str) – Model ID to use.
messages (list[dict[str, Any]]) – List of message dicts (mutated in place).
tools (Sequence[type[Tool]]) – Tool subclasses available to the model.
tool_args (Sequence[Any]) – Extra positional args forwarded to each
Tool.run()call (e.g. request-scoped state).max_turns (int) – Maximum number of tool-call round-trips.
**kwargs (Any) – Additional arguments forwarded to the API.
- Yields:
ChatChunk for each text delta across all turns.
- Return type:
- async fal_call(app, *, inputs, poll_interval=2.0, timeout=60.0, start_timeout=10.0)[source]¶
Submit a fal job and wait for the result.
Convenience method combining
fal_submit(),fal_poll(), andfal_get()into a single call.- Parameters:
- Returns:
Result dict from the completed job.
- Raises:
FalJobFailedError – If the job fails.
TimeoutError – If the job does not complete within timeout.
- Return type:
- async fal_cancel(app, request_id)[source]¶
Cancel a fal job.
- Parameters:
- Returns:
CancelResult with the cancellation state and job state.
- Raises:
FalJobAlreadyCompletedError – If the job already completed.
FalJobNotFoundError – If the job was not found.
- Return type:
- class derp.ai.AIConfig[source]¶
Bases:
_StrictModelAI configuration for OpenAI-compatible providers.
- modal: ModalConfig | None¶
- model_config = {'extra': 'forbid'}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class derp.ai.ChatChunk[source]¶
Bases:
BaseModelA single chunk from a streaming chat completion.
- tool_event: ToolEventType | None¶
- tool_output: Any¶
- vercel_ai_json(*, message_id, stream_id='text-1')[source]¶
Format as Vercel AI SDK events.
Includes lifecycle events when is_first/is_last are set. When tool_event is set, emits tool lifecycle events instead.
- tanstack_ai_json(*, message_id, run_id=None)[source]¶
Format as TanStack AG-UI events.
Includes lifecycle events when is_first/is_last are set. When tool_event is set, emits AG-UI tool call events instead.
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class derp.ai.ChatResponse[source]¶
Bases:
BaseModelNon-streaming chat completion response.
- tanstack_ai_json(*, run_id=None, message_id=None)[source]¶
Format as TanStack AG-UI protocol events.
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class derp.ai.JobState[source]¶
Bases:
StrEnumState of an async AI job.
- QUEUED = 'queued'¶
- IN_PROGRESS = 'in_progress'¶
- COMPLETED = 'completed'¶
- FAILED = 'failed'¶
- UNKNOWN = 'unknown'¶
- __new__(value)¶
- class derp.ai.JobStatus[source]¶
Bases:
BaseModelStatus of an async AI job (e.g. fal image generation).
Wraps fal’s Queued/InProgress/Completed statuses into a single model.
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class derp.ai.Tool[source]¶
-
Base class for defining AI tools.
Subclass with typed fields for parameters, a docstring for the description, and implement
run():class GetWeather(Tool): """Get the current weather for a city.""" city: str unit: str = "celsius" async def run(self) -> str: return f"22° {self.unit}"
Pass the class (not an instance) to
chat()orrun():response = await ai.chat(model="gpt-4o", messages=msgs, tools=[GetWeather])
- classmethod function_name()[source]¶
The function name sent to the LLM (snake_cased class name).
- Return type:
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class derp.ai.ToolCall[source]¶
Bases:
BaseModelA parsed tool call returned by the LLM.
- args: Any¶
- async run(*args, **kwargs)[source]¶
Execute the tool call. Only works when args is a Tool instance.
Extra positional and keyword arguments are forwarded to
Tool.run(), allowing request-scoped state to be injected without closures.
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class derp.ai.ToolEventType[source]¶
Bases:
StrEnumType of tool lifecycle event emitted during agentic streaming.
- INPUT_START = 'input_start'¶
- INPUT_AVAILABLE = 'input_available'¶
- OUTPUT_AVAILABLE = 'output_available'¶
- __new__(value)¶
- class derp.ai.Usage[source]¶
Bases:
BaseModelToken usage statistics.
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
Provider-agnostic AI response models with protocol adapters.
- class derp.ai.models.SSEEvent[source]¶
-
A single SSE event. Behaves like a dict with a dump() method.
- class derp.ai.models.Usage[source]¶
Bases:
BaseModelToken usage statistics.
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class derp.ai.models.Tool[source]¶
-
Base class for defining AI tools.
Subclass with typed fields for parameters, a docstring for the description, and implement
run():class GetWeather(Tool): """Get the current weather for a city.""" city: str unit: str = "celsius" async def run(self) -> str: return f"22° {self.unit}"
Pass the class (not an instance) to
chat()orrun():response = await ai.chat(model="gpt-4o", messages=msgs, tools=[GetWeather])
- classmethod function_name()[source]¶
The function name sent to the LLM (snake_cased class name).
- Return type:
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class derp.ai.models.ToolCall[source]¶
Bases:
BaseModelA parsed tool call returned by the LLM.
- args: Any¶
- async run(*args, **kwargs)[source]¶
Execute the tool call. Only works when args is a Tool instance.
Extra positional and keyword arguments are forwarded to
Tool.run(), allowing request-scoped state to be injected without closures.
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class derp.ai.models.ChatResponse[source]¶
Bases:
BaseModelNon-streaming chat completion response.
- tanstack_ai_json(*, run_id=None, message_id=None)[source]¶
Format as TanStack AG-UI protocol events.
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class derp.ai.models.ToolEventType[source]¶
Bases:
StrEnumType of tool lifecycle event emitted during agentic streaming.
- INPUT_START = 'input_start'¶
- INPUT_AVAILABLE = 'input_available'¶
- OUTPUT_AVAILABLE = 'output_available'¶
- __new__(value)¶
- class derp.ai.models.ChatChunk[source]¶
Bases:
BaseModelA single chunk from a streaming chat completion.
- tool_event: ToolEventType | None¶
- tool_output: Any¶
- vercel_ai_json(*, message_id, stream_id='text-1')[source]¶
Format as Vercel AI SDK events.
Includes lifecycle events when is_first/is_last are set. When tool_event is set, emits tool lifecycle events instead.
- tanstack_ai_json(*, message_id, run_id=None)[source]¶
Format as TanStack AG-UI events.
Includes lifecycle events when is_first/is_last are set. When tool_event is set, emits AG-UI tool call events instead.
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class derp.ai.models.CancelState[source]¶
Bases:
StrEnumResult of a job cancellation request.
- CANCELLATION_REQUESTED = 'cancellation_requested'¶
- ALREADY_COMPLETED = 'already_completed'¶
- NOT_FOUND = 'not_found'¶
- __new__(value)¶
- class derp.ai.models.CancelResult[source]¶
Bases:
BaseModelResult of a cancel request with the job’s state at cancellation time.
- state: CancelState¶
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class derp.ai.models.JobState[source]¶
Bases:
StrEnumState of an async AI job.
- QUEUED = 'queued'¶
- IN_PROGRESS = 'in_progress'¶
- COMPLETED = 'completed'¶
- FAILED = 'failed'¶
- UNKNOWN = 'unknown'¶
- __new__(value)¶
- class derp.ai.models.JobStatus[source]¶
Bases:
BaseModelStatus of an async AI job (e.g. fal image generation).
Wraps fal’s Queued/InProgress/Completed statuses into a single model.
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].