Improve Readme example

This commit is contained in:
Aymeric 2024-12-26 19:00:09 +01:00
parent f8b9cb34f9
commit 654f0047f3
5 changed files with 49 additions and 42 deletions

View File

@ -50,7 +50,7 @@ from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel
agent = CodeAgent(tools=[DuckDuckGoSearchTool()], model=HfApiModel()) agent = CodeAgent(tools=[DuckDuckGoSearchTool()], model=HfApiModel())
agent.run("What time would the world's fastest car take to travel from New York to San Francisco?") agent.run("What time would it take for a leopard at full speed to run through Pont des Arts?")
``` ```
> TODO: Add video > TODO: Add video

View File

@ -23,33 +23,10 @@ In this guided visit, you will learn how to build an agent, how to run it, and h
To initialize a minimal agent, you need at least these two arguments: To initialize a minimal agent, you need at least these two arguments:
- An LLM to power your agent - because the agent is different from a simple LLM, it is a system that uses a LLM as its engine. - An text-generation model to power your agent - because the agent is different from a simple LLM, it is a system that uses a LLM as its engine.
- A list of tools from which the agent pick tools to execute - A list of tools from which the agent pick tools to execute
For defining your LLM, you can make a `custom_model` method which accepts a list of [messages](./chat_templating) and returns text. This callable also needs to accept a `stop_sequences` argument that indicates when to stop generating. For your model, you can use any of these options:
```python
from huggingface_hub import login, InferenceClient
login("<YOUR_HUGGINGFACEHUB_API_TOKEN>")
model_id = "meta-llama/Llama-3.3-70B-Instruct"
client = InferenceClient(model=model_id)
def custom_model(messages, stop_sequences=["Task"]) -> str:
response = client.chat_completion(messages, stop=stop_sequences, max_tokens=1000)
answer = response.choices[0].message.content
return answer
```
You could use any `custom_model` method as long as:
1. it follows the [messages format](./chat_templating) (`List[Dict[str, str]]`) for its input `messages`, and it returns a `str`.
2. it stops generating outputs at the sequences passed in the argument `stop_sequences`
Additionally, `custom_model` can also take a `grammar` argument. In the case where you specify a `grammar` upon agent initialization, this argument will be passed to the calls to model, with the `grammar` that you defined upon initialization, to allow [constrained generation](https://huggingface.co/docs/text-generation-inference/conceptual/guidance) in order to force properly-formatted agent outputs.
For convenience, we provide pre-built classes for your model engine:
- [`TransformersModel`] takes a pre-initialized `transformers` pipeline to run inference on your local machine using `transformers`. - [`TransformersModel`] takes a pre-initialized `transformers` pipeline to run inference on your local machine using `transformers`.
- [`HfApiModel`] leverages a `huggingface_hub.InferenceClient` under the hood. - [`HfApiModel`] leverages a `huggingface_hub.InferenceClient` under the hood.
- We also provide [`LiteLLMModel`], which lets you call 100+ different models through [LiteLLM](https://docs.litellm.ai/)! - We also provide [`LiteLLMModel`], which lets you call 100+ different models through [LiteLLM](https://docs.litellm.ai/)!
@ -60,6 +37,11 @@ Once you have these two arguments, `tools` and `model`, you can create an agent
```python ```python
from smolagents import CodeAgent, HfApiModel from smolagents import CodeAgent, HfApiModel
from huggingface_hub import login
login("<YOUR_HUGGINGFACEHUB_API_TOKEN>")
model_id = "meta-llama/Llama-3.3-70B-Instruct"
model = HfApiModel(model_id=model_id) model = HfApiModel(model_id=model_id)
agent = CodeAgent(tools=[], model=model, add_base_tools=True) agent = CodeAgent(tools=[], model=model, add_base_tools=True)

View File

@ -57,10 +57,30 @@ We provide two types of agents, based on the main [`Agent`] class.
## Models ## Models
You're free to create and use your own engines to be usable by the Agents framework. You're free to create and use your own models to power your agent.
These engines have the following specification:
1. Follow the [messages format](../chat_templating.md) for its input (`List[Dict[str, str]]`) and return a string. You could use any `model` callable for your agent, as long as:
2. Stop generating outputs *before* the sequences passed in the argument `stop_sequences` 1. It follows the [messages format](./chat_templating) (`List[Dict[str, str]]`) for its input `messages`, and it returns a `str`.
2. It stops generating outputs *before* the sequences passed in the argument `stop_sequences`
For defining your LLM, you can make a `custom_model` method which accepts a list of [messages](./chat_templating) and returns text. This callable also needs to accept a `stop_sequences` argument that indicates when to stop generating.
```python
from huggingface_hub import login, InferenceClient
login("<YOUR_HUGGINGFACEHUB_API_TOKEN>")
model_id = "meta-llama/Llama-3.3-70B-Instruct"
client = InferenceClient(model=model_id)
def custom_model(messages, stop_sequences=["Task"]) -> str:
response = client.chat_completion(messages, stop=stop_sequences, max_tokens=1000)
answer = response.choices[0].message.content
return answer
```
Additionally, `custom_model` can also take a `grammar` argument. In the case where you specify a `grammar` upon agent initialization, this argument will be passed to the calls to model, with the `grammar` that you defined upon initialization, to allow [constrained generation](https://huggingface.co/docs/text-generation-inference/conceptual/guidance) in order to force properly-formatted agent outputs.
### TransformersModel ### TransformersModel

View File

@ -23,7 +23,6 @@ class GetCatImageTool(Tool):
return Image.open(BytesIO(response.content)) return Image.open(BytesIO(response.content))
LAUNCH_GRADIO = False
get_cat_image = GetCatImageTool() get_cat_image = GetCatImageTool()
@ -34,11 +33,11 @@ agent = CodeAgent(
use_e2b_executor=True use_e2b_executor=True
) )
if LAUNCH_GRADIO: agent.run(
from smolagents import GradioUI
GradioUI(agent).launch()
else:
agent.run(
"Return me an image of a cat. Directly use the image provided in your state.", additional_args={"cat_image":get_cat_image()} "Return me an image of a cat. Directly use the image provided in your state.", additional_args={"cat_image":get_cat_image()}
) # Asking to directly return the image from state tests that additional_args are properly sent to server. ) # Asking to directly return the image from state tests that additional_args are properly sent to server.
# Try the agent in a Gradio UI
from smolagents import GradioUI
GradioUI(agent).launch()

View File

@ -153,15 +153,21 @@ class DuckDuckGoSearchTool(Tool):
} }
output_type = "any" output_type = "any"
def forward(self, query: str) -> list[dict[str, str]]: def __init__(self):
super().__init__(self)
try: try:
from duckduckgo_search import DDGS from duckduckgo_search import DDGS
except ImportError: except ImportError:
raise ImportError( raise ImportError(
"You must install package `duckduckgo_search` to run this tool: for instance run `pip install duckduckgo-search`." "You must install package `duckduckgo_search` to run this tool: for instance run `pip install duckduckgo-search`."
) )
results = DDGS().text(query, max_results=7) self.ddgs = DDGS()
return results
def forward(self, query: str) -> str:
results = self.ddgs.text(query, max_results=10)
postprocessed_results = [f"[{result['title']}]({result['href']})\n{result['body']}" for result in results]
return "## Search Results\n\n" + "\n\n".join(postprocessed_results)
class GoogleSearchTool(Tool): class GoogleSearchTool(Tool):
@ -246,7 +252,7 @@ class GoogleSearchTool(Tool):
) )
web_snippets.append(redacted_version) web_snippets.append(redacted_version)
return "## Web Results\n" + "\n\n".join(web_snippets) return "## Search Results\n" + "\n\n".join(web_snippets)
class VisitWebpageTool(Tool): class VisitWebpageTool(Tool):