Text Generation Inference (TGI) now supports [JSON and regex grammars](#grammar-and-constraints) and [tools and functions](#tools-and-functions) to help developers guide LLM responses to fit their needs.
These feature are available starting from version `1.4.3`. They are accessible via the [text_generation](https://pypi.org/project/text-generation/) library. The tool support is compatible with OpenAI's client libraries. The following guide will walk you through the new features and how to use them!
_note: guidance is supported as grammar in the `/generate` endpoint and as tools in the `/chat/completions` endpoint._
## How it works
TGI leverages the [outlines](https://github.com/outlines-dev/outlines) library to efficiently parse and compile the grammatical structures and tools specified by users. This integration transforms the defined grammars into an intermediate representation that acts as a framework to guide and constrain content generation, ensuring that outputs adhere to the specified grammatical rules.
If you are interested in the technical details on how outlines is used in TGI, you can check out the [conceptual guidance documentation](../conceptual/guidance).
## Table of Contents 📚
### Grammar and Constraints
-[The Grammar Parameter](#the-grammar-parameter): Shape your AI's responses with precision.
-[Constrain with Pydantic](#constrain-with-pydantic): Define a grammar using Pydantic models.
-[JSON Schema Integration](#json-schema-integration): Fine-grained control over your requests via JSON schema.
-[Using the client](#using-the-client): Use TGI's client libraries to shape the AI's responses.
### Tools and Functions
-[The Tools Parameter](#the-tools-parameter): Enhance the AI's capabilities with predefined functions.
-[Via the client](#text-generation-inference-client): Use TGI's client libraries to interact with the Messages API and Tool functions.
-[OpenAI integration](#openai-integration): Use OpenAI's client libraries to interact with TGI's Messages API and Tool functions.
## Grammar and Constraints 🛣️
### The Grammar Parameter
In TGI `1.4.3`, we've introduced the grammar parameter, which allows you to specify the format of the response you want from the LLM.
Using curl, you can make a request to TGI's Messages API with the grammar parameter. This is the most primitive way to interact with the API and using [Pydantic](#constrain-with-pydantic) is recommended for ease of use and readability.
```json
curllocalhost:3000/generate\
-XPOST\
-H'Content-Type:application/json'\
-d'{
"inputs":"I saw a puppy a cat and a raccoon during my bike ride in the park",
A grammar can be defined using Pydantic models, JSON schemas, or regular expressions. The LLM will then generate a response that conforms to the specified grammar.
> Note: A grammar must compile to an intermediate representation to constrain the output. Grammar compilation is a computationally expensive and may take a few seconds to complete on the first request. Subsequent requests will use the cached grammar and will be much faster.
### Constrain with Pydantic
Using Pydantic models we can define a similar grammar as the previous example in a shorter and more readable way.
```python
importrequests
frompydanticimportBaseModel,conint
fromtypingimportList
classAnimals(BaseModel):
location:str
activity:str
animals_seen:conint(ge=1,le=5)# Constrained integer type
animals:List[str]
prompt="convert to JSON: I saw a puppy a cat and a raccoon during my bike ride in the park"
TGI provides a client library to that make it easy to send requests with all of the parameters we've discussed above. Here's an example of how to use the client to send a request with a grammar parameter.
```python
fromtext_generationimportAsyncClient
fromtext_generation.typesimportGrammarType
# NOTE: tools defined above and removed for brevity
# Define an async function to encapsulate the async operation
# Once the response is received, you can process it
print(response.generated_text)
# Ensure the main async function is run in the event loop
if__name__=="__main__":
importasyncio
asyncio.run(main())
# 118.8.0.84
```
## Tools and Functions 🛠️
### The Tools Parameter
In addition to the grammar parameter, we've also introduced a set of tools and functions to help you get the most out of the Messages API.
Tools are a set of user defined functions that can be used in tandem with the chat functionality to enhance the LLM's capabilities. Functions, similar to grammar are defined as JSON schema and can be passed as part of the parameters to the Messages API.
Functions, similar to grammar are defined as JSON schema and can be passed as part of the parameters to the Messages API.
```json
curllocalhost:3000/v1/chat/completions\
-XPOST\
-H'Content-Type:application/json'\
-d'{
"model":"tgi",
"messages":[
{
"role":"user",
"content":"What is the weather like in New York?"
}
],
"tools":[
{
"type":"function",
"function":{
"name":"get_current_weather",
"description":"Get the current weather",
"parameters":{
"type":"object",
"properties":{
"location":{
"type":"string",
"description":"The city and state, e.g. San Francisco, CA"
},
"format":{
"type":"string",
"enum":["celsius","fahrenheit"],
"description":"The temperature unit to use. Infer this from the users location."
TGI provides a client library to interact with the Messages API and Tool functions. The client library is available in both synchronous and asynchronous versions.
```python
fromtext_generationimportAsyncClient
# NOTE: tools defined above and removed for brevity
# Define an async function to encapsulate the async operation
"description":"The city and state, e.g. San Francisco, CA",
},
"format":{
"type":"string",
"enum":["celsius","fahrenheit"],
"description":"The temperature unit to use. Infer this from the users location.",
},
},
"required":["location","format"],
},
},
},
{
"type":"function",
"function":{
"name":"get_n_day_weather_forecast",
"description":"Get an N-day weather forecast",
"parameters":{
"type":"object",
"properties":{
"location":{
"type":"string",
"description":"The city and state, e.g. San Francisco, CA",
},
"format":{
"type":"string",
"enum":["celsius","fahrenheit"],
"description":"The temperature unit to use. Infer this from the users location.",
},
"num_days":{
"type":"integer",
"description":"The number of days to forecast",
},
},
"required":["location","format","num_days"],
},
},
}
]
```
</details>
### OpenAI integration
TGI exposes an OpenAI-compatible API, which means you can use OpenAI's client libraries to interact with TGI's Messages API and Tool functions.
However there are some minor differences in the API, for example `tool_choice="auto"` will ALWAYS choose the tool for you. This is different from OpenAI's API where `tool_choice="auto"` will choose a tool if the model thinks it's necessary.
```python
fromopenaiimportOpenAI
# Initialize the client, pointing it to one of the available models
client=OpenAI(
base_url="http://localhost:3000/v1",
api_key="_",
)
# NOTE: tools defined above and removed for brevity
chat_completion=client.chat.completions.create(
model="tgi",
messages=[
{
"role":"system",
"content":"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.",
},
{
"role":"user",
"content":"What's the weather like the next 3 days in San Francisco, CA?",
Visual Language Model (VLM) are models that consume both image and text inputs to generate text.
VLM's are trained on a combination of image and text data and can handle a wide range of tasks, such as image captioning, visual question answering, and visual dialog.
> What distinguishes VLMs from other text and image models is their ability to handle long context and generate text that is coherent and relevant to the image even after multiple turns or in some cases, multiple images.
Below are couple of common use cases for vision language models:
-**Image Captioning**: Given an image, generate a caption that describes the image.
-**Visual Question Answering (VQA)**: Given an image and a question about the image, generate an answer to the question.
-**Mulimodal Dialog**: Generate response to multiple turns of images and conversations.
-**Image Information Retrieval**: Given an image, retrieve information from the image.
## How to Use a Vision Language Model?
### Hugging Face Hub Python Library
To infer with vision language models through Python, you can use the [`huggingface_hub`](https://pypi.org/project/huggingface-hub/) library. The `InferenceClient` class provides a simple way to interact with the [Inference API](https://huggingface.co/docs/api-inference/index). Images can be passed as URLs or base64-encoded strings. The `InferenceClient` will automatically detect the image format.
# This is a picture of an anthropomorphic rabbit in a space suit.
```
If you want additional details, you can add `details=True`. In this case, you get a `TextGenerationStreamResponse` which contains additional information such as the probabilities and the tokens. For the final response in the stream, it also returns the full generated text.
### Inference Through Sending `cURL` Requests
To use the `generate_stream` endpoint with curl, you can add the `-N` flag. This flag disables curl default buffering and shows data as it arrives from the server.
```bash
curl -N 127.0.0.1:3000/generate_stream \
-X POST \
-d'{"inputs":"What is this a picture of?\n\n","parameters":{"max_new_tokens":16, "seed": 42}}'\
-H'Content-Type: application/json'
# ...
# data:{"index":16,"token":{"id":28723,"text":".","logprob":-0.6196289,"special":false},"generated_text":"This is a picture of an anthropomorphic rabbit in a space suit.","details":null}
```
### Inference Through JavaScript
First, we need to install the `@huggingface/inference` library.
```bash
npm install @huggingface/inference
```
If you're using the free Inference API, you can use [Huggingface.js](https://huggingface.co/docs/huggingface.js/inference/README)'s `HfInference`. If you're using inference endpoints, you can use `HfInferenceEndpoint` class to easily interact with the Inference API.
We can create a `HfInferenceEndpoint` providing our endpoint URL and We can create a `HfInferenceEndpoint` providing our endpoint URL and [Hugging Face access token](https://huggingface.co/settings/tokens).
"What is this a picture of?\n\n";
conststream=hf.textGenerationStream({
inputs:prompt,
parameters:{max_new_tokens:16,seed:42},
});
forawait(constrofstream){
// yield the generated token
process.stdout.write(r.token.text);
}
// This is a picture of an anthropomorphic rabbit in a space suit.
```
## Combining Vision Language Models with Other Features
VLMs in TGI have several advantages, for example these models can be used in tandem with other features for more complex tasks. For example, you can use VLMs with [Guided Generation](/docs/conceptual/guided-generation) to generate specific JSON data from an image.
For example we can extract information from the rabbit image and generate a JSON object with the location, activity, number of animals seen, and the animals seen. That would look like this:
```json
{
"activity":"Standing",
"animals":["Rabbit"],
"animals_seen":1,
"location":"Rocky surface with mountains in the background and a red light on the rabbit's chest"
}
```
All we need to do is provide a JSON schema to the VLM model and it will generate the JSON object for us.
```bash
curl localhost:3000/generate \
-X POST \
-H'Content-Type: application/json'\
-d'{
"inputs":"What is this a picture of?\n\n",
# "generated_text": "{ \"activity\": \"Standing\", \"animals\": [ \"Rabbit\" ], \"animals_seen\": 1, \"location\": \"Rocky surface with mountains in the background and a red light on the rabbit's chest\" }"
# }
```
Want to learn more about how Vision Language Models work? Check out the [awesome blog post on the topic](https://huggingface.co/blog/vlms).
Text Generation Inference (TGI) now supports [JSON and regex grammars](#grammar-and-constraints) and [tools and functions](#tools-and-functions) to help developer guide LLM responses to fit their needs.
## What is Guidance?
These feature are available starting from version `1.4.3`. They are accessible via the [text_generation](https://pypi.org/project/text-generation/) library and is compatible with OpenAI's client libraries. The following guide will walk you through the new features and how to use them!
Guidance is a feature that allows users to constrain the generation of a large language model with a specified grammar. This feature is particularly useful when you want to generate text that follows a specific structure or uses a specific set of words or produce output in a specific format.
## Quick Start
## How is it used?
Before we jump into the deep end, ensure your system is using TGI version `1.4.3` or later to access all the features we're about to explore in this guide.
Guidance can be in many ways and the community is always finding new ways to use it. Here are some examples of how you can use guidance:
If you're not up to date, grab the latest version and let's get started!
Technically, guidance can be used to generate:
## Table of Contents 📚
- a specific JSON object
- a function signature
- typed output like a list of integers
### Grammar and Constraints
However these use cases can span a wide range of applications, such as:
-[The Grammar Parameter](#the-grammar-parameter): Shape your AI's responses with precision.
-[Constrain with Pydantic](#constrain-with-pydantic): Define a grammar using Pydantic models.
-[JSON Schema Integration](#json-schema-integration): Fine grain control over your requests via JSON schema.
-[Using the client](#using-the-client): Use TGI's client libraries to shape the AI's responses.
- extracting structured data from unstructured text
- summarizing text into a specific format
- limit output to specific classes of words (act as a LLM powered classifier)
- generate the input to specific APIs or services
- provide reliable and consistent output for downstream tasks
- extract data from multimodal inputs
### Tools and Functions
## How it works?
-[The Tools Parameter](#the-tools-parameter): Enhance the AI's capabilities with predefined functions.
-[Via the client](#text-generation-inference-client): Use TGI's client libraries to interact with the Messages API and Tool functions.
-[OpenAI integration](#openai-integration): Use OpenAI's client libraries to interact with TGI's Messages API and Tool functions.
Diving into the details, guidance is enabled by including a grammar with a generation request that is compiled, and used to modify the chosen tokens.
## Grammar and Constraints 🛣️
This process can be broken down into the following steps:
### The Grammar Parameter
1. A request is sent to the backend, it is processed and placed in batch. Processing includes compiling the grammar into a finite state machine and a grammar state.
In TGI `1.4.3`, we've introduced the grammar parameter, which allows you to specify the format of the response you want from the AI. This is a game-changer for those who need precise control over the AI's output.
Using curl, you can make a request to TGI's Messages API with the grammar parameter. This is the most primitive way to interact with the API and using [Pydantic](#constrain-with-pydantic) is recommended for ease of use and readability.
2. The model does a forward pass over the batch. This returns probabilities for each token in the vocabulary for each request in the batch.
```json
curllocalhost:3000/generate\
-XPOST\
-H'Content-Type:application/json'\
-d'{
"inputs":"I saw a puppy a cat and a raccoon during my bike ride in the park",
3. The process of choosing one of those tokens is called `sampling`. The model samples from the distribution of probabilities to choose the next token. In TGI all of the steps before sampling are called `processor`. Grammars are applied as a processor that masks out tokens that are not allowed by the grammar.
A grammar can be defined using Pydantic models, JSON schema, or regular expressions. The AI will then generate a response that conforms to the specified grammar.
4. The grammar mask is applied and the model samples from the remaining tokens. Once a token is chosen, we update the grammar state with the new token, to prepare it for the next pass.
> Note: A grammar must compile to a intermediate representation to constrain the output. Grammar compilation is a computationally expensive and may take a few seconds to complete on the first request. Subsequent requests will use the cached grammar and will be much faster.
Pydantic is a powerful library for data validation and settings management. It's the perfect tool for crafting the a specific response format.
There are two main ways to use guidance; you can either use the `/generate` endpoint with a grammar or use the `/chat/completion` endpoint with tools.
Using Pydantic models we can define a similar grammar as the previous example in a shorter and more readable way.
Under the hood tools are a special case of grammars that allows the model to choose one or none of the provided tools.
```python
importrequests
frompydanticimportBaseModel,conint
fromtypingimportList
Please refer to [using guidance](../basic_tutorial/using_guidance) for more examples and details on how to use guidance in Python, JavaScript, and cURL.
classAnimals(BaseModel):
location:str
activity:str
animals_seen:conint(ge=1,le=5)# Constrained integer type
animals:List[str]
### Getting the most out of guidance
prompt="convert to JSON: I saw a puppy a cat and a raccoon during my bike ride in the park"
Depending on how you are using guidance, you may want to make use of different features. Here are some tips to get the most out of guidance:
If Pydantic's not your style, go raw with direct JSON Schema integration. It's like having a conversation with the AI in its own language. This is simliar to the first example but with programmatic control.
TGI provides a client library to that make it easy to send requests with all of the parameters we've discussed above. Here's an example of how to use the client to send a request with a grammar parameter.
```python
fromtext_generationimportAsyncClient
fromtext_generation.typesimportGrammarType
# NOTE: tools defined above and removed for brevity
# Define an async function to encapsulate the async operation
# Once the response is received, you can process it
print(response.generated_text)
# Ensure the main async function is run in the event loop
if__name__=="__main__":
importasyncio
asyncio.run(main())
# 118.8.0.84
```
## Tools and Functions 🛠️
### The Tools Parameter
In addition to the grammar parameter, we've also introduced a set of tools and functions to help you get the most out of the Messages API.
Tools are a set of user defined functions that can be used in tandem with the chat functionality to enhance the AI's capabilities. You can use these tools to perform a variety of tasks, such as data manipulation, formatting, and more.
Functions, similar to grammar are defined as JSON schema and can be passed as part of the parameters to the Messages API.
```json
curllocalhost:3000/v1/chat/completions\
-XPOST\
-H'Content-Type:application/json'\
-d'{
"model":"tgi",
"messages":[
{
"role":"user",
"content":"What is the weather like in New York?"
}
],
"tools":[
{
"type":"function",
"function":{
"name":"get_current_weather",
"description":"Get the current weather",
"parameters":{
"type":"object",
"properties":{
"location":{
"type":"string",
"description":"The city and state, e.g. San Francisco, CA"
},
"format":{
"type":"string",
"enum":["celsius","fahrenheit"],
"description":"The temperature unit to use. Infer this from the users location."
"description":"The city and state, e.g. San Francisco, CA",
},
"format":{
"type":"string",
"enum":["celsius","fahrenheit"],
"description":"The temperature unit to use. Infer this from the users location.",
},
},
"required":["location","format"],
},
},
},
{
"type":"function",
"function":{
"name":"get_n_day_weather_forecast",
"description":"Get an N-day weather forecast",
"parameters":{
"type":"object",
"properties":{
"location":{
"type":"string",
"description":"The city and state, e.g. San Francisco, CA",
},
"format":{
"type":"string",
"enum":["celsius","fahrenheit"],
"description":"The temperature unit to use. Infer this from the users location.",
},
"num_days":{
"type":"integer",
"description":"The number of days to forecast",
},
},
"required":["location","format","num_days"],
},
},
}
]
```
</details>
### Text Generation Inference Client
TGI provides a client library to interact with the Messages API and Tool functions. The client library is available in both synchronous and asynchronous versions.
```python
fromtext_generationimportAsyncClient
# NOTE: tools defined above and removed for brevity
# Define an async function to encapsulate the async operation
TGI exposes an OpenAI-compatible API, which means you can use OpenAI's client libraries to interact with TGI's Messages API and Tool functions.
However there are some minor differences in the API, for example `tool_choice="auto"` will ALWAYS choose the tool for you. This is different from OpenAI's API where `tool_choice="auto"` will choose a tool if the model thinks it's necessary.
```python
fromopenaiimportOpenAI
# Initialize the client, pointing it to one of the available models
client=OpenAI(
base_url="http://localhost:3000/v1",
api_key="_",
)
# NOTE: tools defined above and removed for brevity
chat_completion=client.chat.completions.create(
model="tgi",
messages=[
{
"role":"system",
"content":"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.",
},
{
"role":"user",
"content":"What's the weather like the next 3 days in San Francisco, CA?",
- If you are using the `/generate` with a `grammar` it is recommended to include the grammar in the prompt prefixed by something like `Please use the following JSON schema to generate the output:`. This will help the model understand the context of the grammar and generate the output accordingly.
- If you are getting a response with many repeated tokens, please use the `frequency_penalty` or `repetition_penalty` to reduce the number of repeated tokens in the output.
Speculative decoding, assisted generation, Medusa, and others are a few different names for the same idea.
The idea is to generate tokens *before* the large model actually runs, and only *check* if those tokens where valid.
...
...
@@ -36,7 +37,7 @@ In order to use medusa models in TGI, simply point to a medusa enabled model, an
If you don't have a medusa model, or don't have the resource to fine-tune, you can try to use `n-gram`.
Ngram works by trying to find in the previous sequence existing tokens that match, and use those as speculation.
N-gram works by trying to find matching tokens in the previous sequence, and use those as speculation for generating new tokens. For example, if the tokens "np.mean" appear multiple times in the sequence, the model can speculate that the next continuation of the tokens "np." is probably also "mean".
This is an extremely simple method, which works best for code, or highly repetitive text. This might not be beneficial, if the speculation misses too much.
@@ -15,7 +15,7 @@ Token streaming is the mode in which the server returns the tokens one by one as
/>
</div>
With token streaming, the server can start returning the tokens one by one before having to generate the whole response. Users can have a sense of the generation's quality earlier than the end of the generation. This has different positive effects:
With token streaming, the server can start returning the tokens one by one before having to generate the whole response. Users can have a sense of the generation's quality before the end of the generation. This has different positive effects:
* Users can get results orders of magnitude earlier for extremely long queries.
* Seeing something in progress allows users to stop the generation if it's not going in the direction they expect.
- Custom Prompt Generation: Easily generate text by providing custom prompts to guide the model's output.
- Fine-tuning Support: Utilize fine-tuned models for specific tasks to achieve higher accuracy and performance.
-[Guidance](../conceptual/guidance): Enable function calling and tool-use by forcing the model to generate structured outputs based on your own predefined output schemas.
Text Generation Inference is used in production by multiple projects, such as: