forked from dottxt-ai/outlines
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Robin Picard
committed
Feb 27, 2025
1 parent
f4497dd
commit 43b2d74
Showing
6 changed files
with
168 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
::: outlines.macros |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Macros | ||
|
||
Outlines offers a convenient way of encapsulating a model, a prompt template, and an output type in a single object called a `Macro`. After instantiating a `Macro`, it can be called just like a function with arguments that will be passed to the template to create the prompt. The prompt is then used to call the model with the output type first specified to generate an answer. | ||
|
||
## Create a Macro | ||
|
||
To create a Macro, you need to provide 3 arguments: | ||
|
||
- A model: an instance of an Outlines model class from module `outlines.models` | ||
- A template: either an instance of `outlines.templates.Template` or a callable that takes arguments and returns a prompt | ||
- An output type: a type instance from `outlines.types` that is used to define the structure of the output | ||
|
||
```python | ||
from pydantic import BaseModel | ||
from outlines.models import transformers | ||
from outlines.templates import Template | ||
from outlines.types import JsonType | ||
|
||
class OutputModel(BaseModel): | ||
result: int | ||
|
||
model = transformers.from_transformers( | ||
"microsoft/Phi-3-mini-4k-instruct", | ||
"microsoft/Phi-3-mini-4k-instruct" | ||
) | ||
template = Template.from_str("What is 2 times {{ num }}?") | ||
output_type = JsonType(OutputModel) | ||
|
||
macro = Macro(model, template, output_type) | ||
``` | ||
|
||
## Call a Macro | ||
|
||
Once the Macro is instantiated, it can be called just like a function with arguments that will be passed to the template to create the prompt. The prompt is then used to call the model with the output type first specified to generate an answer. | ||
|
||
```python | ||
result = macro(num=3) | ||
print(result) # Expected output: { "result" : 6 } | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
from dataclasses import dataclass | ||
from typing import Any, Callable, Union | ||
|
||
from outlines.generate import Generator | ||
from outlines.templates import Template | ||
from outlines.models import Model | ||
|
||
|
||
@dataclass | ||
class Macro: | ||
""" | ||
Macro is a class that encapsulates a model, a prompt template, and an | ||
output type. It can be called to generate a response. | ||
Parameters | ||
---------- | ||
model : Model | ||
The Outlines model to be used for generating responses. | ||
template : Union[Template, Callable] | ||
A callable that takes arguments and returns a prompt string. | ||
output_type : Any | ||
The expected output type of the generated response. | ||
Examples | ||
-------- | ||
from pydantic import BaseModel | ||
from transformers import AutoModelForCausalLM, AutoTokenizer | ||
from outlines import models, Macro | ||
from outlines.types import JsonType | ||
from outlines.templates import Template | ||
class OutputModel(BaseModel): | ||
result: int | ||
model = models.from_transformers( | ||
AutoModelForCausalLM.from_pretrained("microsoft/Phi-3-mini-4k-instruct"), | ||
AutoTokenizer.from_pretrained("microsoft/Phi-3-mini-4k-instruct") | ||
) | ||
template_string = "What is 2 times {{ num }}?" | ||
template = Template.from_str(template_string) | ||
my_macro = Macro(model, template, JsonType(OutputModel)) | ||
result = my_macro(num=3) | ||
print(result) # Expected output: { "result" : 6 } | ||
""" | ||
model: Model | ||
template: Union[Template, Callable] | ||
output_type: Any | ||
|
||
def __post_init__(self): | ||
self.template = self.template | ||
self.generator = Generator(self.model, self.output_type) | ||
|
||
def __call__(self, *args, **kwargs): | ||
prompt = self.template(*args, **kwargs) | ||
return self.generator(prompt) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import pytest | ||
|
||
import jinja2 | ||
|
||
from outlines.macros import Macro | ||
from outlines.templates import Template | ||
from outlines.models import Model | ||
from outlines.generate import Generator | ||
from typing import Any | ||
|
||
|
||
@pytest.fixture(scope="session") | ||
def model(): | ||
class MockModel(Model): | ||
type_adapter = None | ||
|
||
def generate(self, model_input: str, output_type=None, **kwargs) -> Any: | ||
return model_input | ||
|
||
return MockModel() | ||
|
||
|
||
def test_macro_initialization(model): | ||
template = Template.from_str("Test {{ value }}") | ||
output_type = None | ||
macro = Macro(model, template, output_type) | ||
|
||
assert macro.generator == Generator(model, output_type) | ||
assert macro.template == template | ||
|
||
|
||
def test_macro_template_call(model): | ||
template = Template.from_str("Test {{ value }}") | ||
output_type = None | ||
macro = Macro(model, template, output_type) | ||
result = macro(value="example") | ||
|
||
assert result == "Test example" | ||
|
||
|
||
def test_macro_callable_call(model): | ||
def template(value): | ||
return f"Test {value}" | ||
|
||
output_type = None | ||
macro = Macro(model, template, output_type) | ||
result = macro("example") | ||
|
||
assert result == "Test example" | ||
|
||
def test_macro_template_error(model): | ||
template = Template.from_str("Test {{ value }}") | ||
output_type = None | ||
macro = Macro(model, template, output_type) | ||
|
||
with pytest.raises(jinja2.exceptions.UndefinedError): | ||
macro(foo="bar") |