Python Solver
Runs a custom Python function as the solver. Use this when the built-in declarative solvers cannot express the interaction patterns with the model you need.
Function Signature
Both def and async def are supported. The function must be named run_solver and accepts the following arguments:
from typing import Any
from latticeflow.core.dtypes import RawSample, SolverTrace
async def run_solver(sample: RawSample, model: Any, trace: SolverTrace) -> SolverTrace:where:
sampleis a dictionary representing the current sample (RawSampleis an alias fordict[str, Any]).modelis the model object used for inference (with apredictmethod).traceis aSolverTraceobject that can be used to record the conversation and should be returned by the function.
Accessing task config
run_solver can optionally accept a task_config argument to receive the task configuration as a plain Python dict. Config values of type dataset are not included.
async def run_solver(
sample: RawSample,
model: Any,
trace: SolverTrace,
task_config: dict[str, Any],
) -> SolverTrace:
system_prompt = task_config["system_prompt"]
...Using models from config
To call a model inside the solver, declare it in the task’s config_spec with type model and access it via task_config. The model exposes a predict method:
# config_spec:
# - type: model
# key: translate_model
# - type: string
# key: target_language
from latticeflow.core.dtypes import Message
async def run_solver(
sample: RawSample,
model: Any,
trace: SolverTrace,
task_config: dict[str, Any],
) -> SolverTrace:
translate_model = task_config["translate_model"]
target_language = task_config["target_language"]
response = await translate_model.predict([
Message(role="system", content=f"Translate the following question to {target_language}."),
Message(role="user", content=sample["question"]),
])
translated_question = response.text
...Examples
Example: Geography QA. A Python function builds the conversation trace manually - appending a system message, the user question from the dataset, calling the model, and recording the response.
Python Solver
# ...
definition:
# ...
solver:
type: "python"
run_solver_snippet: |
async def run_solver(sample, model, trace):
trace.append_system_message(
"You are a helpful assistant. Answer with a single word or short phrase."
)
trace.append_user_message(sample["question"])
response = await model.predict(trace.items)
trace.add_model_response(response)
return traceFor a sample {"question": "What is the capital of Japan?", "answer": "Tokyo"}, the solver builds and returns the following trace:
| Turn | Role | Content |
|---|---|---|
| 1 | system | You are a helpful assistant. Answer with a single word or short phrase. |
| 2 | user | What is the capital of Japan? |
| 3 | assistant | Tokyo |
Configuration
Properties
postprocessor PythonPostprocessorTemplate
An optional postprocessor applied to solver outputs before scoring.
Default: None
type Literal “python” required
The type of the solver.
run_solver_snippet string required
The Python code snippet defining how to run the solver. It must define a run_solver function with the following API:
from typing import Any
from latticeflow.core.dtypes import RawSample, SolverTrace
async def run_solver(sample: RawSample, model: Any, trace: SolverTrace) -> SolverTrace:where:
sampleis a dictionary representing the current sample (RawSampleis an alias fordict[str, Any]).modelis the model object used for inference (with apredictmethod).traceis aSolverTraceobject that can be used to record the conversation and should be returned by the function.