prodigy.analysis.ai_candidates

Loop invariants proposed by a language model and checked by Prodigy.

The model only proposes candidates. Every candidate goes through the same exact check as an invariant typed in by hand (strategies evt_invariant and evt_subinvariant), so a wrong answer makes an attempt fail but never makes a result unsound. When a candidate is rejected, the next request tells the model why (e.g. Φ(I) − I), so it can correct itself.

Answers are untrusted input. Before any computer algebra system sees a candidate (SymPy’s parser evaluates Python code), it must consist of numbers, the program’s variables and parameters, + - * / ^, parentheses, sqrt and exp, and parse as a pGCL expression.

Configuration, read from the environment of prodigy (it never reaches the browser):

  • ANTHROPIC_API_KEY: Claude API, model PRODIGY_AI_MODEL (default claude-sonnet-5-5); ANTHROPIC_WORKSPACE_ID for a key that is not scoped to a workspace.

  • OPENAI_API_KEY and/or PRODIGY_AI_BASE_URL with PRODIGY_AI_MODEL: an OpenAI-compatible chat-completions API, e.g. http://localhost:11434/v1 for a local model served by Ollama.

  • PRODIGY_AI_PROVIDER (anthropic or openai) chooses if both are configured; PRODIGY_AI_TIMEOUT: seconds per request (default 120).

exception AIConfigurationError[source]

Bases: Exception

No language model is configured, or its configuration is incomplete.

exception AIRequestError[source]

Bases: Exception

The request to the language model failed.

exception CandidateError[source]

Bases: ValueError

An answer contains no admissible candidate.

class Provider(name, model, ask, diagnostics=dict())[source]

Bases: object

Parameters:
name: str
model: str
ask: Callable[[str, str], str]

(system prompt, user prompt) -> text of the answer

diagnostics: Dict[str, Any]

Why the last answer ended (stop_reason) and the kinds of its content blocks.

get_provider(env=None)[source]

The configured language model (see the module documentation).

Parameters:

env (Mapping[str, str] | None)

Return type:

Provider

prompt(form, program, loop, variables, parameters, entering, rejected)[source]

The request for a candidate of kind form (see FORMS) for loop.

Parameters:
Return type:

str

candidate_from_answer(answer, names)[source]

The candidate in a model’s answer: its last ANSWER: line, else the last line of its last code block or of the answer.

Raises CandidateError unless it is an expression over names, numbers, + - * / ^, parentheses, sqrt and exp that parses as a pGCL expression.

Parameters:
Return type:

str