mirror of
https://github.com/ollama/ollama-python.git
synced 2026-05-01 11:48:17 +08:00
types/examples: add tool_name to message and examples (#537)
This commit is contained in:
parent
63ca747622
commit
33488eee06
@ -25,6 +25,7 @@ See [ollama/docs/api.md](https://github.com/ollama/ollama/blob/main/docs/api.md)
|
|||||||
### Tools/Function Calling - Call a function with a model
|
### Tools/Function Calling - Call a function with a model
|
||||||
- [tools.py](tools.py) - Simple example of Tools/Function Calling
|
- [tools.py](tools.py) - Simple example of Tools/Function Calling
|
||||||
- [async-tools.py](async-tools.py)
|
- [async-tools.py](async-tools.py)
|
||||||
|
- [multi-tool.py](multi-tool.py) - Using multiple tools, with thinking enabled
|
||||||
|
|
||||||
|
|
||||||
### Multimodal with Images - Chat with a multimodal (image chat) model
|
### Multimodal with Images - Chat with a multimodal (image chat) model
|
||||||
|
|||||||
@ -76,7 +76,7 @@ async def main():
|
|||||||
if response.message.tool_calls:
|
if response.message.tool_calls:
|
||||||
# Add the function response to messages for the model to use
|
# Add the function response to messages for the model to use
|
||||||
messages.append(response.message)
|
messages.append(response.message)
|
||||||
messages.append({'role': 'tool', 'content': str(output), 'name': tool.function.name})
|
messages.append({'role': 'tool', 'content': str(output), 'tool_name': tool.function.name})
|
||||||
|
|
||||||
# Get final response from model with function outputs
|
# Get final response from model with function outputs
|
||||||
final_response = await client.chat('llama3.1', messages=messages)
|
final_response = await client.chat('llama3.1', messages=messages)
|
||||||
|
|||||||
88
examples/multi-tool.py
Normal file
88
examples/multi-tool.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import random
|
||||||
|
from typing import Iterator
|
||||||
|
|
||||||
|
from ollama import ChatResponse, Client
|
||||||
|
|
||||||
|
|
||||||
|
def get_temperature(city: str) -> int:
|
||||||
|
"""
|
||||||
|
Get the temperature for a city in Celsius
|
||||||
|
|
||||||
|
Args:
|
||||||
|
city (str): The name of the city
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: The current temperature in Celsius
|
||||||
|
"""
|
||||||
|
# This is a mock implementation - would need to use a real weather API
|
||||||
|
import random
|
||||||
|
|
||||||
|
if city not in ['London', 'Paris', 'New York', 'Tokyo', 'Sydney']:
|
||||||
|
return 'Unknown city'
|
||||||
|
|
||||||
|
return str(random.randint(0, 35)) + ' degrees Celsius'
|
||||||
|
|
||||||
|
|
||||||
|
def get_conditions(city: str) -> str:
|
||||||
|
"""
|
||||||
|
Get the weather conditions for a city
|
||||||
|
"""
|
||||||
|
if city not in ['London', 'Paris', 'New York', 'Tokyo', 'Sydney']:
|
||||||
|
return 'Unknown city'
|
||||||
|
# This is a mock implementation - would need to use a real weather API
|
||||||
|
conditions = ['sunny', 'cloudy', 'rainy', 'snowy']
|
||||||
|
return random.choice(conditions)
|
||||||
|
|
||||||
|
|
||||||
|
available_functions = {
|
||||||
|
'get_temperature': get_temperature,
|
||||||
|
'get_conditions': get_conditions,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cities = ['London', 'Paris', 'New York', 'Tokyo', 'Sydney']
|
||||||
|
city = random.choice(cities)
|
||||||
|
city2 = random.choice(cities)
|
||||||
|
messages = [{'role': 'user', 'content': f'What is the temperature in {city}? and what are the weather conditions in {city2}?'}]
|
||||||
|
print('----- Prompt:', messages[0]['content'], '\n')
|
||||||
|
|
||||||
|
model = 'qwen3'
|
||||||
|
client = Client()
|
||||||
|
response: Iterator[ChatResponse] = client.chat(model, stream=True, messages=messages, tools=[get_temperature, get_conditions], think=True)
|
||||||
|
|
||||||
|
for chunk in response:
|
||||||
|
if chunk.message.thinking:
|
||||||
|
print(chunk.message.thinking, end='', flush=True)
|
||||||
|
if chunk.message.content:
|
||||||
|
print(chunk.message.content, end='', flush=True)
|
||||||
|
if chunk.message.tool_calls:
|
||||||
|
for tool in chunk.message.tool_calls:
|
||||||
|
if function_to_call := available_functions.get(tool.function.name):
|
||||||
|
print('\nCalling function:', tool.function.name, 'with arguments:', tool.function.arguments)
|
||||||
|
output = function_to_call(**tool.function.arguments)
|
||||||
|
print('> Function output:', output, '\n')
|
||||||
|
|
||||||
|
# Add the assistant message and tool call result to the messages
|
||||||
|
messages.append(chunk.message)
|
||||||
|
messages.append({'role': 'tool', 'content': str(output), 'tool_name': tool.function.name})
|
||||||
|
else:
|
||||||
|
print('Function', tool.function.name, 'not found')
|
||||||
|
|
||||||
|
print('----- Sending result back to model \n')
|
||||||
|
if any(msg.get('role') == 'tool' for msg in messages):
|
||||||
|
res = client.chat(model, stream=True, tools=[get_temperature, get_conditions], messages=messages, think=True)
|
||||||
|
done_thinking = False
|
||||||
|
for chunk in res:
|
||||||
|
if chunk.message.thinking:
|
||||||
|
print(chunk.message.thinking, end='', flush=True)
|
||||||
|
if chunk.message.content:
|
||||||
|
if not done_thinking:
|
||||||
|
print('\n----- Final result:')
|
||||||
|
done_thinking = True
|
||||||
|
print(chunk.message.content, end='', flush=True)
|
||||||
|
if chunk.message.tool_calls:
|
||||||
|
# Model should be explaining the tool calls and the results in this output
|
||||||
|
print('Model returned tool calls:')
|
||||||
|
print(chunk.message.tool_calls)
|
||||||
|
else:
|
||||||
|
print('No tool calls returned')
|
||||||
@ -74,7 +74,7 @@ if response.message.tool_calls:
|
|||||||
if response.message.tool_calls:
|
if response.message.tool_calls:
|
||||||
# Add the function response to messages for the model to use
|
# Add the function response to messages for the model to use
|
||||||
messages.append(response.message)
|
messages.append(response.message)
|
||||||
messages.append({'role': 'tool', 'content': str(output), 'name': tool.function.name})
|
messages.append({'role': 'tool', 'content': str(output), 'tool_name': tool.function.name})
|
||||||
|
|
||||||
# Get final response from model with function outputs
|
# Get final response from model with function outputs
|
||||||
final_response = chat('llama3.1', messages=messages)
|
final_response = chat('llama3.1', messages=messages)
|
||||||
|
|||||||
@ -284,6 +284,9 @@ class Message(SubscriptableBaseModel):
|
|||||||
Valid image formats depend on the model. See the model card for more information.
|
Valid image formats depend on the model. See the model card for more information.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
tool_name: Optional[str] = None
|
||||||
|
'Name of the executed tool.'
|
||||||
|
|
||||||
class ToolCall(SubscriptableBaseModel):
|
class ToolCall(SubscriptableBaseModel):
|
||||||
"""
|
"""
|
||||||
Model tool calls.
|
Model tool calls.
|
||||||
|
|||||||
@ -60,6 +60,7 @@ select = [
|
|||||||
'FLY', # flynt
|
'FLY', # flynt
|
||||||
'RUF', # ruff-specific rules
|
'RUF', # ruff-specific rules
|
||||||
]
|
]
|
||||||
|
ignore = ['FBT001'] # Boolean-typed positional argument in function definition
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
addopts = ['--doctest-modules']
|
addopts = ['--doctest-modules']
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user