Skip to main content
valen

API REFERENCE

Create a decision

Provide a state, instructions, and candidate choices. Receive probabilities for the next decision.

POST/v1/decisionsJSON

The hosted endpoint and request example follow the official API cookbook. View source

Free API: no key

We provide a free API with limited capacity for evaluation and small requests. The example needs no key. Retry later on HTTP 429 and avoid concurrent batch workloads.

https://api.valen-team.workers.dev/v1/decisions

The free endpoint supports valen-preview-0923, valen-2b, valen-4b, and valen-0-8b, selected through model. Each request accepts one question named q0: predicate, choice, or score. Supply 2–8 choices for choice, or 2–8 ordered levels (label, description) for score, with temperature: 1.0. Text is limited to 4000 characters, instructions to 1000, and each choice description to 300. Keep images under 3 MB and request bodies under 4,500,000 bytes.

Python/cURL examples include the Origin header required by the free endpoint. The website demo and Valen API Hugging Face Space can call it directly; browser calls from other websites are not enabled. Origin is not an access credential.

Higher quotas: request a key by email

For batch workloads or higher quotas, email liuziyu77@sjtu.edu.cn with your use case, expected volume, and input types. Quotas are subject to confirmation by the service operator.

Once approved, change the example URL to the official endpoint and send your own key through Authorization: Bearer. Never put keys in frontend code.

import os

url = "https://llm-proxy.openxxlab.com/v1/decisions"
headers = {"Authorization": "Bearer " + os.environ["VALEN_API_KEY"]}

Request body

APPLICATION/JSON
modelstringREQUEST

Choose valen-preview-0923, valen-2b, valen-4b, or valen-0-8b. Examples default to valen-2b.

inputstring | messages[]REQUEST

Text context, or a message list containing text and image inputs.

questionsobject[]REQUEST

The free endpoint accepts one question named q0 per request.

namestring

A name to identify the question.

typestring

Supports predicate (Yes/No), choice, and score.

instructionsstring

Describe what the model should decide.

choicesobject[]

Each candidate includes a value and a description.

{"value": "cat", "description": "A cat"}
levelsobject[]

For score: 2–8 ordered levels, each with label and description. The returned score is the probability-weighted average of level indices starting at 0.

{"label": "High", "description": "Strong purchase intent"}
temperaturenumber

The cookbook example uses 1.0. Consult the hosted service documentation for its parameter contract.

Read the response

Read the question results from answers. Keep the question identifiers and candidate choices for the next step in your application.

response.json()["answers"][0]

Predicate returns probability (the probability the condition is true); choice returns choice and probabilities; score returns score and level probabilities (label, numeric index value, probability). Score is weighted over level indices starting at 0: five levels span 0–4. Optional confidence is separate. Confidence is a separate field, not the maximum choice probability. Answers match questions by position and echo their name. Select a model with the request model field; the response includes a model_id identifier.

Multimodal inputs

Represent an image as a JPEG data URL in a message containing input_text and input_image, then pass the message list as input.

Understand the data format and local interface

Video input: decisions from a frame

The homepage video example extracts the middle frame of an MP4, then sends its JPEG data URL as input_image. This is not a video upload; hosted input_video support has not been verified. A single frame cannot establish motion or event order.

python -m pip install requests "Pillow>=10" av==16.1.0

Place assets/cookbook/momos.mp4 from the official repository in the working directory and use the free endpoint without a key. Only one JPEG is uploaded; frame extraction happens locally.

import base64
import io

import av
import requests

# Extract the middle frame, following the official cookbook.
video_path = "momos.mp4"
with av.open(video_path) as video:
frame_count = sum(1 for _ in video.decode(video=0))
if frame_count == 0:
raise ValueError("The video has no decodable frames")
with av.open(video_path) as video:
for index, frame in enumerate(video.decode(video=0)):
if index == frame_count // 2:
image = frame.to_image()
break

buffer = io.BytesIO()
image.save(buffer, format="JPEG", quality=95)
image_url = "data:image/jpeg;base64," + base64.b64encode(
buffer.getvalue()
).decode("ascii")

response = requests.post(
"https://api.valen-team.workers.dev/v1/decisions",
headers={"Origin": "https://valen-team.github.io"},
json={
"model": "valen-2b",
"input": [{
"role": "user",
"content": [
{"type": "input_text", "text": "Answer using only the visible image."},
{"type": "input_image", "image_url": image_url},
],
}],
"questions": [{
"name": "q0",
"type": "choice",
"instructions": "What is the color of the sauce in the foil container on the left?",
"choices": [
{"value": "brown", "description": "Brown"},
{"value": "white", "description": "White"},
{"value": "red", "description": "Red"},
{"value": "orange", "description": "Orange"},
],
}],
"temperature": 1.0,
},
timeout=120,
)
response.raise_for_status()
answer = response.json()["answers"][0]
print(answer["choice"], answer["confidence"])
for entry in answer["probabilities"]:
print(entry["value"], entry["probability"])