Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9242ea3
Create the tools module
RobinPicard Sep 11, 2025
133f5bb
Create the outputs module
RobinPicard Sep 11, 2025
d048c39
Update the inputs module to include tools and outputs
RobinPicard Sep 11, 2025
457c58b
Update the base model and generator to use tools and outputs
RobinPicard Sep 11, 2025
fcfb303
Implement tools and outputs for the Anthropic model
RobinPicard Sep 11, 2025
988ea4c
Implement tools and outputs for the Dottxt model
RobinPicard Sep 11, 2025
789bda6
Implement tools and outputs for the Gemini model
RobinPicard Sep 11, 2025
11f0891
Implement tools and outputs for the LlamaCpp model
RobinPicard Sep 11, 2025
7f748f1
Implement tools and outputs for the MLXLM model
RobinPicard Sep 11, 2025
406f5a3
Implement tools and outputs for the Ollama model
RobinPicard Sep 11, 2025
62acef9
Implement tools and outputs for the OpenAI model
RobinPicard Sep 11, 2025
39a474d
Implement tools and outputs for the SgLang model
RobinPicard Sep 11, 2025
9955e1e
Implement tools and outputs for the TGI model
RobinPicard Sep 11, 2025
3e7f9a6
Implement tools and outputs for the Transformers model
RobinPicard Sep 11, 2025
b3f5032
Implement tools and outputs for the VLLM model
RobinPicard Sep 11, 2025
a6b231f
Implement tools and outputs for the VLLMOffline model
RobinPicard Sep 11, 2025
d52c958
Update tests to expect Output as the generation return value
RobinPicard Sep 11, 2025
00e5c82
Update the python examples
RobinPicard Sep 11, 2025
a89ab6f
Update the docs examples
RobinPicard Sep 11, 2025
9554b2c
Update the documentation to include tools and ouputs
RobinPicard Sep 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/examples/chain_of_density.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ model = outlines.from_transformers(
transformers.AutoTokenizer.from_pretrained(MODEL_NAME)
)
prompt = chain_of_density(article=article)
result = model(prompt, Summaries, max_new_tokens=2000)
result = model(prompt, Summaries, max_new_tokens=2000).content
```

We can now check the results:

```python
print(result)
print(result.content)
# {'summaries': [
# {
# 'missing_entities': 'English mathematician, cryptanalyst, philosopher',
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/chain_of_thought.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ We obtain a series of intermediate reasoning steps as well as the conclusion:
```python
import json

json_response = json.loads(response)
json_response = json.loads(response.content)

print(json_response["reasoning"])
print(json_response["conclusion"])
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/classification.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ prompts = [customer_support(request=request) for request in requests]
We can now ask the model to classify the requests:

```python
labels = generator(prompts)
labels = generator(prompts).content
print(labels)
# ['URGENT', 'STANDARD']
```
Expand All @@ -79,7 +79,7 @@ We can then create a generator with the Pydantic model we just defined and call

```python
generator = outlines.Generator(model, Classification)
labels = generator(prompts)
labels = generator(prompts).content
print(labels)
# ['{"label":"URGENT"}', '{ "label": "STANDARD" }']
```
2 changes: 1 addition & 1 deletion docs/examples/dating_profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ it's a good excuse for a date. I watch the latest series because I'm paying,
with my hard-earned money, for every streaming service."""

prompt = dating_profile_prompt(description=new_description, examples=samples)
profile = model(prompt, DatingProfile)
profile = model(prompt, DatingProfile).content
parsed_profile = DatingProfile.model_validate_json(json.loads(profile))
```

Expand Down
4 changes: 2 additions & 2 deletions docs/examples/deploy-using-bentoml.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ We then need to define an HTTP endpoint using `@bentoml.api` to decorate the met
from outlines.types import JsonSchema

generator = outlines.Generator(self.model, JsonSchema(json_schema))
character = generator(prompt)
character = generator(prompt).content

return json.loads(character)
```
Expand Down Expand Up @@ -200,7 +200,7 @@ with bentoml.SyncHTTPClient("http://localhost:3000") as client:
response = client.generate(
prompt="Give me a character description"
)
print(response)
print(response.content)
```

</details>
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/deploy-using-cerebrium.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def generate(

character = generator(
f"<s>[INST]Give me a character description. Describe {prompt}.[/INST]"
)
).content

return character
```
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/deploy-using-modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def generate(
# by models, so make sure to check the model's documentation.
character = generator(
f"<s>[INST]Give me a character description. Describe {prompt}.[/INST]"
)
).content

# Print out the generated character.
print(character)
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/earnings-reports.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ Provide the prompt to the model and run it:
csv_data = csv_extractor(
extract_financial_data_prompt(columns_to_extract, income_statement),
max_new_tokens=1024,
)
).content

print(csv_data)
```
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/extract_event_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class Event(BaseModel):
prompt = prompt_template(now=now, message=message)

# Extract the event information
event = generator(prompt)
event = generator(prompt).content # type: ignore

# Print the current date and time
print(f"Today: {now}")
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/extraction.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ prompts = [take_order(order=order) for order in orders]
generator = outlines.Generator(model, Order)

results = generator(prompts)
print(results)
print(results.content)
# ['{"pizza": "Pepperoni", "number": 2}',
# '{"pizza": "Margherita", "number": 12}']
```
Expand Down
8 changes: 5 additions & 3 deletions docs/examples/knowledge_graph_extraction.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ response = generator(prompt, max_tokens=1024, temperature=0, seed=42)
We obtain the nodes and edges of the knowledge graph:

```python
print(response)
print(response.content)
# {"nodes":[{"id":1,"label":"Alice","property":"loves,hates"},
# {"id":2,"label":"Bob","property":"loved_by"},
# {"id":3,"label":"Charlie","property":"hated_by"}],
Expand All @@ -137,12 +137,14 @@ print(response)
We can use the [Graphviz library](https://graphviz.readthedocs.io/en/stable/) to visualize the generated knowledge graph. For detailed installation instructions, see [here](https://graphviz.readthedocs.io/en/stable/#installation).

```python
import json
from graphviz import Digraph

json_response = json.loads(response.content)
dot = Digraph()
for node in response["nodes"]:
for node in json_response["nodes"]:
dot.node(str(node["id"]), node["label"], shape='circle', width='1', height='1')
for edge in response["edges"]:
for edge in json_response["edges"]:
dot.edge(str(edge["source"]), str(edge["target"]), label=edge["label"])

dot.render('knowledge-graph.gv', view=True)
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/models_playing_chess.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ board_state = " "
turn_number = 0
while not board.is_game_over():
regex_pattern = legal_moves_regex(board)
structured = model(prompt + board_state, regex_pattern)
structured = model(prompt + board_state, regex_pattern).content
move = board.parse_san(structured)

if turn_number % 2 == 0 : # It's White's turn
Expand Down
6 changes: 3 additions & 3 deletions docs/examples/qa-with-citations.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ import json

generator = outlines.Generator(model, Users)
response = generator("Create 5 fake users", max_tokens=1024, temperature=0, seed=42)
response = json.loads(response)
response = json.loads(response.content)
print(response['users'])
# [{'id': 1, 'first_name': 'John', 'last_name': 'Doe', 'age': 25},
# {'id': 2, 'first_name': 'Jane', 'last_name': 'Doe', 'age': 30},
Expand Down Expand Up @@ -164,7 +164,7 @@ I also started the Data Science club at the University of Waterloo and I was the
generator = outlines.Generator(model, QuestionAnswer)
prompt = hermes_prompt(question=question, context=context, schema=schema)
response = generator(prompt, max_tokens=1024, temperature=0, seed=42)
print(response)
print(response.content)
# {"question": "What did the author do during college?", "answer": "The author studied Computational Mathematics and physics in university and was also involved in starting the Data Science club, serving as its president for 2 years.", "citations": ["I went to an arts high school but in university I studied Computational Mathematics and physics.", "I also started the Data Science club at the University of Waterloo and I was the president of the club for 2 years."]}
```

Expand Down Expand Up @@ -222,7 +222,7 @@ for question, context in [
prompt = hermes_prompt(question=question, context=context, schema=schema)
generator = outlines.Generator(model, QuestionAnswer)
response = generator(prompt, max_tokens=1024, temperature=0, seed=42)
response = json.loads(response)
response = json.loads(response.content)
print(question)
print(response['answer'])
print(response['citations'])
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/react_agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class ChatBot:
def execute(self):
generator = outlines.Generator(model, Decision)
result = generator(self.prompt, max_tokens=1024, temperature=0, seed=42)
return result
return result.content
```

We define a query function:
Expand Down
6 changes: 3 additions & 3 deletions docs/examples/read-pdfs.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ page_summary_generator = outlines.Generator(model, PageSummary)

for image in images:
result = page_summary_generator({"text": prompt, "images": image})
print(result)
print(result.content)
```

### Regular expressions to extract the arxiv paper identifier
Expand Down Expand Up @@ -317,7 +317,7 @@ categorizer = outlines.Generator(model, Literal["llms", "cell biology", "other"]

# Categorize the paper
category = categorizer({"text": categorization_instruction, "images": images[0]})
print(category)
print(category.content)
```

Which should return:
Expand Down Expand Up @@ -357,7 +357,7 @@ two_image_prompt = tf_processor.apply_chat_template(
generator = outlines.Generator(model, Literal["hot dog", "not hot dog"])

result = generator({"text": two_image_prompt, "images": [images[0], images[1]]})
print(result)
print(result.content)
```

Using the first to pages of the paper (they are not images of hot dogs), we should get
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/receipt-digitization.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ result = receipt_summary_generator(
{"text": prompt, "images": image},
max_new_tokens=1024
)
print(result)
print(result.content)
```

## Output
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/simtom.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ perspective_prompt = perspective_taking(story=story, character=character)

# Call Mistral 7B with the first prompt
generator = outlines.Generator(model, PerspectiveTaking)
perspective = generator(perspective_prompt, max_new_tokens=1024)
perspective = generator(perspective_prompt, max_new_tokens=1024).content

print(perspective)
# {'character': 'Aria', 'events': ['1 Aria entered the front_yard.', '3 The grapefruit is in the green_bucket.', '4 Aria moved the grapefruit to the blue_container.']}
Expand All @@ -104,7 +104,7 @@ sim_prompt = simulation(events=json.loads(perspective)["events"], name=character
generator = outlines.Generator(model, Simulation)
result = generator(sim_prompt, max_new_tokens=1024)

print(result)
print(result.content)
# {'answer': 'green_bucket'}
```

Expand Down
12 changes: 6 additions & 6 deletions docs/examples/structured_generation_workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ With our prompt ready we can now generate 10 example phone numbers
```python
phone_generator_unstruct = outlines.Generator(model)
for _ in range(3):
print(phone_generator_unstruct(prompt_phone, max_new_tokens=12))
print(phone_generator_unstruct(prompt_phone, max_new_tokens=12).content)
```

> I'd be happy to help you generate a realistic phone\
Expand Down Expand Up @@ -105,7 +105,7 @@ We're ready to see if structured generation can make an improvement over our ini
phone_generator_v1 = outlines.Generator(model, phone_regex_1)

for _ in range(3):
print(phone_generator_v1(prompt_phone))
print(phone_generator_v1(prompt_phone).content)
```
> (206) 555-1234\
(206) 555-1234\
Expand Down Expand Up @@ -146,7 +146,7 @@ Now that we've validated, let's generate with this new regex!
phone_generator_v2 = outlines.Generator(model, phone_regex_2)

for _ in range(3):
print(phone_generator_v2(prompt_phone))
print(phone_generator_v2(prompt_phone).content)
```

> (206) 867-5309\
Expand Down Expand Up @@ -178,9 +178,9 @@ if not re.match(phone_regex_3_error, phone_number):
else:
matched_string = re.match(phone_regex_3_error, phone_number)[0]
if matched_string == phone_number:
print("Successful match")
print("Successful match")
else:
print(f"Error {matched_string} != {phone_number}")
print(f"Error {matched_string} != {phone_number}")
```
This prints out:
> Error (206) 386-463 != (206) 386-4636
Expand All @@ -192,7 +192,7 @@ phone_regex_3_fixed = Regex(r'\([0-9]{3}\) [2-4][7-9][4-6]-[3-6][2-8][1-4][6-9]'
phone_generator_v3 = outlines.Generator(model, phone_regex_3_fixed)

for _ in range(3):
print(phone_generator_v3(prompt_phone))
print(phone_generator_v3(prompt_phone).content)
```

>(206) 494-3216\
Expand Down
4 changes: 2 additions & 2 deletions docs/features/advanced/backends.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ model = outlines.from_transformers(
)

result = model("What is the capital of France?", output_type, backend="llguidance")
print(result) # 'Paris'
print(result.content) # 'Paris'

generator = outlines.Generaor(model, output_type)
result = generator("What is the capital of France?", backend="xgrammar")
print(result) # 'Paris'
print(result.content) # 'Paris'
```

If you do not provide a value for the `backend` argument, the default value will be used. The default value depends on the type of output type:
Expand Down
4 changes: 2 additions & 2 deletions docs/features/advanced/logits_processors.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ logits_processor = RegexLogitsProcessor(r"U\+[0-9A-Fa-f]{4,6}", model.tokenizer,
generator = Generator(model, processor=logits_processor)
response = generator("What's the unicode for the hugging face emoji")

print(response) # U+1F917
print(response.content) # U+1F917
```

## Creating Custom Logits Processors
Expand Down Expand Up @@ -95,5 +95,5 @@ formatted_prompt = tf_tokenizer.apply_chat_template(
generator = Generator(model, processor=logits_processor)
response = generator(formatted_prompt)

print(response) # "101111"
print(response.content) # "101111"
```
8 changes: 4 additions & 4 deletions docs/features/core/generator.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ generator = Generator(model)
result = generator("Write a short poem about AI.")

# Print the result
print(result)
print(result.content)
```

## Structured Generation
Expand Down Expand Up @@ -77,7 +77,7 @@ generator = Generator(model, BookRecommendation)
result = generator("Recommend a science fiction book.")

# Parse the JSON result into a Pydantic model
book = BookRecommendation.model_validate_json(result)
book = BookRecommendation.model_validate_json(result.content)
print(f"{book.title} by {book.author} ({book.year})")
```

Expand Down Expand Up @@ -109,7 +109,7 @@ result = generator(

## Return Value

The generator always returns a raw string containing the generated text. When generating structured outputs, you need to parse this string into the desired format.
The generator returns an `Output` instance (or a iterator containing `StreamingOutput` instances in case of streaming). The `content` field contains the generated text as a string. When generating structured outputs, you need to parse this string into the desired format.

Unlike in Outlines v0, where the return type could be a parsed object, in v1 you are responsible for parsing the output when needed:

Expand All @@ -126,7 +126,7 @@ generator = Generator(model, Person)
result = generator("Generate a person:")

# Parse the result yourself
person = Person.model_validate_json(result)
person = Person.model_validate_json(result.content)
```

::: outlines.generator.Generator
Loading
Loading