Examples and readme updates

This commit is contained in:
ParthSareen
2024-11-20 13:45:38 -08:00
parent c5c61a3b04
commit 238f142a5c
23 changed files with 294 additions and 110 deletions
+5
View File
@@ -2,6 +2,11 @@
The Ollama Python library provides the easiest way to integrate Python 3.8+ projects with [Ollama](https://github.com/ollama/ollama).
## Prerequisites
- Install [Ollama](https://ollama.com/download)
- Pull a model: `ollama pull <model>` See [Ollama models](https://ollama.com/models)
## Install
```sh
+61
View File
@@ -0,0 +1,61 @@
# Running Examples
Run the examples in this directory with:
```sh
# Navigate to examples directory
cd examples/
# Run example
python3 <example>.py
```
### Chat
- [chat.py](chat.py) - Basic chat with model
- [chat-stream.py](chat-stream.py) - Stream chat with model
- [async-chat.py](async-chat.py) - Async chat with model
### Generate
- [generate.py](generate.py) - Generate text with model
- [generate-stream.py](generate-stream.py) - Stream generate text with model
- [async-generate.py](async-generate.py) - Async generate text with model
### List
- [list.py](list.py) - List all downloaded models and their properties
- [async-list.py](async-list.py) - Async list all downloaded models and their properties
### Fill in the middle
- [fill-in-middle.py](fill-in-middle.py) - Fill in the middle with model
### Multimodal
- [multimodal.py](multimodal.py) - Multimodal chat with model
### Pull Progress
Requirement: `pip install tqdm`
- [pull-progress.py](pull-progress.py) - Pull progress with model
### Ollama create (create a model)
- [create.py](create.py) - Create a model
### Ollama ps (show model status - cpu/gpu usage)
- [ollama-ps.py](ollama-ps.py) - Ollama ps
### Tools/Function Calling
- [tools.py](tools.py) - Simple example of Tools/Function Calling
- [async-tools.py](async-tools.py) - Async example of Tools/Function Calling
## Configuring Clients
Custom parameters can be passed to the client when initializing:
```python
import ollama
client = ollama.Client(
host='http://localhost:11434',
timeout=10.0, # Default: None
follow_redirects=True, # Default: True
headers={'x-some-header': 'some-value'}
)
```
Similarly, the `AsyncClient` class can be configured with the same parameters.
-3
View File
@@ -1,3 +0,0 @@
# async-chat-stream
This example demonstrates how to create a conversation history using an asynchronous Ollama client and the chat endpoint. The streaming response is outputted to `stdout` as well as a TTS if enabled with `--speak` and available. Supported TTS are `say` on macOS and `espeak` on Linux.
-59
View File
@@ -1,59 +0,0 @@
import shutil
import asyncio
import argparse
import ollama
async def speak(speaker, content):
if speaker:
p = await asyncio.create_subprocess_exec(speaker, content)
await p.communicate()
async def main():
parser = argparse.ArgumentParser()
parser.add_argument('--speak', default=False, action='store_true')
args = parser.parse_args()
speaker = None
if not args.speak:
...
elif say := shutil.which('say'):
speaker = say
elif (espeak := shutil.which('espeak')) or (espeak := shutil.which('espeak-ng')):
speaker = espeak
client = ollama.AsyncClient()
messages = []
while True:
if content_in := input('>>> '):
messages.append({'role': 'user', 'content': content_in})
content_out = ''
message = {'role': 'assistant', 'content': ''}
async for response in await client.chat(model='mistral', messages=messages, stream=True):
if response['done']:
messages.append(message)
content = response['message']['content']
print(content, end='', flush=True)
content_out += content
if content in ['.', '!', '?', '\n']:
await speak(speaker, content_out)
content_out = ''
message['content'] += content
if content_out:
await speak(speaker, content_out)
print()
try:
asyncio.run(main())
except (KeyboardInterrupt, EOFError):
...
+35
View File
@@ -0,0 +1,35 @@
import asyncio
import ollama
async def main():
client = ollama.AsyncClient()
messages = []
print("Chat with the model (type 'exit' to quit)")
while True:
# Get user input
user_input = input('You: ')
if user_input.lower() == 'exit':
break
# Add user message to history
messages.append({'role': 'user', 'content': user_input})
# Stream the response
print('Assistant: ', end='', flush=True)
async for chunk in await client.chat(model='llama3.1', messages=messages, stream=True):
# Print the response chunk
print(chunk['message']['content'], end='', flush=True)
# Update message history with complete response
if chunk['done']:
messages.append(chunk['message'])
print('\n')
if __name__ == '__main__':
try:
asyncio.run(main())
except KeyboardInterrupt:
print('\nGoodbye!')
+15
View File
@@ -0,0 +1,15 @@
import asyncio
import ollama
async def main():
client = ollama.AsyncClient()
response = await client.generate('llama3.1', 'Why is the sky blue?')
print(response['response'])
if __name__ == '__main__':
try:
asyncio.run(main())
except KeyboardInterrupt:
print('\nGoodbye!')
+37
View File
@@ -0,0 +1,37 @@
import asyncio
import ollama
async def main():
client = ollama.AsyncClient()
response = await client.list()
models = response['models']
models_data = []
for model in models:
if model.get('details'): # Check if details exist
models_data.append(
(
model.get('name', 'N/A'),
model.get('size', 0) / 1024 / 1024, # Convert to MB
model.get('details', {}).get('format', 'N/A'),
model.get('details', {}).get('family', 'N/A'),
model.get('details', {}).get('parameter_size', 'N/A'),
model.get('details', {}).get('quantization_level', 'N/A'),
)
)
print(f'\n{len(models)} models found!')
print('\nDetailed model information:')
for model in models_data:
print(f'Name: {model[0]}')
print(f'Size (MB): {model[1]:.2f}')
print(f'Format: {model[2]}')
print(f'Family: {model[3]}')
print(f'Parameter Size: {model[4]}')
print(f'Quantization Level: {model[5]}')
print('-' * 50)
if __name__ == '__main__':
asyncio.run(main())
+40
View File
@@ -0,0 +1,40 @@
import asyncio
from ollama import AsyncClient
async def main():
client = AsyncClient()
response = await client.pull('llama3.1', stream=True)
progress_states = set()
async for progress in response:
if progress.get('status') in progress_states:
continue
progress_states.add(progress.get('status'))
print(progress.get('status'))
print('\n')
response = await client.chat('llama3.1', messages=[{'role': 'user', 'content': 'Hello!'}])
print(response['message']['content'])
print('\n')
response = await client.ps()
name = response['models'][0]['name']
size = response['models'][0]['size']
size_vram = response['models'][0]['size_vram']
if size == size_vram:
print(f'{name}: 100% GPU')
elif not size_vram:
print(f'{name}: 100% CPU')
else:
size_cpu = size - size_vram
cpu_percent = round(size_cpu / size * 100)
print(f'{name}: {cpu_percent}% CPU/{100 - cpu_percent}% GPU')
if __name__ == '__main__':
asyncio.run(main())
@@ -6,6 +6,16 @@ import asyncio
# Simulates an API call to get flight times
# In a real application, this would fetch data from a live database or API
def get_flight_times(departure: str, arrival: str) -> str:
"""
Get the flight times between two cities
Args:
departure (str): The departure city (airport code)
arrival (str): The arrival city (airport code)
Returns:
str: The flight times between the two cities
"""
flights = {
'NYC-LAX': {'departure': '08:00 AM', 'arrival': '11:30 AM', 'duration': '5h 30m'},
'LAX-NYC': {'departure': '02:00 PM', 'arrival': '10:30 PM', 'duration': '5h 30m'},
@@ -28,29 +38,7 @@ async def run(model: str):
response = await client.chat(
model=model,
messages=messages,
tools=[
{
'type': 'function',
'function': {
'name': 'get_flight_times',
'description': 'Get the flight times between two cities',
'parameters': {
'type': 'object',
'properties': {
'departure': {
'type': 'string',
'description': 'The departure city (airport code)',
},
'arrival': {
'type': 'string',
'description': 'The arrival city (airport code)',
},
},
'required': ['departure', 'arrival'],
},
},
},
],
tools=[get_flight_times],
)
# Add the model's response to the conversation history
@@ -80,8 +68,8 @@ async def run(model: str):
# Second API call: Get final response from the model
final_response = await client.chat(model=model, messages=messages)
print(final_response['message']['content'])
print(final_response.message.content)
# Run the async function
asyncio.run(run('mistral'))
asyncio.run(run('llama3.1'))
@@ -8,8 +8,7 @@ messages = [
},
]
for part in chat('mistral', messages=messages, stream=True):
for part in chat('llama3.1', messages=messages, stream=True):
print(part['message']['content'], end='', flush=True)
# end with a newline
print()
+1 -2
View File
@@ -1,6 +1,5 @@
from ollama import chat
messages = [
{
'role': 'user',
@@ -8,5 +7,5 @@ messages = [
},
]
response = chat('mistral', messages=messages)
response = chat('llama3.1', messages=messages)
print(response['message']['content'])
@@ -1,5 +1,5 @@
from ollama import generate
for part in generate('mistral', 'Why is the sky blue?', stream=True):
for part in generate('llama3.1', 'Why is the sky blue?', stream=True):
print(part['response'], end='', flush=True)
@@ -1,5 +1,5 @@
from ollama import generate
response = generate('mistral', 'Why is the sky blue?')
response = generate('llama3.1', 'Why is the sky blue?')
print(response['response'])
+14
View File
@@ -0,0 +1,14 @@
from ollama import list
from ollama._types import ListResponse
response: ListResponse = list()
for model in response.models:
if model.details:
print(f'Name: {model.model}')
print(f'Size (MB): {(model.size.real / 1024 / 1024):.2f}')
print(f'Format: {model.details.format}')
print(f'Family: {model.details.family}')
print(f'Parameter Size: {model.details.parameter_size}')
print(f'Quantization Level: {model.details.quantization_level}')
print('-' * 50)
@@ -4,7 +4,6 @@ import httpx
from ollama import generate
latest = httpx.get('https://xkcd.com/info.0.json')
latest.raise_for_status()
+2 -2
View File
@@ -1,6 +1,6 @@
from ollama import ps, pull, chat
response = pull('mistral', stream=True)
response = pull('llama3.1', stream=True)
progress_states = set()
for progress in response:
if progress.get('status') in progress_states:
@@ -10,7 +10,7 @@ for progress in response:
print('\n')
response = chat('mistral', messages=[{'role': 'user', 'content': 'Hello!'}])
response = chat('llama3.1', messages=[{'role': 'user', 'content': 'Hello!'}])
print(response['message']['content'])
print('\n')
@@ -3,7 +3,7 @@ from ollama import pull
current_digest, bars = '', {}
for progress in pull('mistral', stream=True):
for progress in pull('llama3.1', stream=True):
digest = progress.get('digest', '')
if digest != current_digest and current_digest in bars:
bars[current_digest].close()
-9
View File
@@ -1,9 +0,0 @@
# pull-progress
This example emulates `ollama pull` using the Python library and [`tqdm`](https://tqdm.github.io/).
## Setup
```shell
pip install -r requirements.txt
```
-1
View File
@@ -1 +0,0 @@
tqdm==4.66.1
+67
View File
@@ -0,0 +1,67 @@
from ollama import chat
from ollama._types import ChatResponse
def add_two_numbers(a: int, b: int) -> int:
"""
Add two numbers
Args:
a (int): The first number
b (int): The second number
Returns:
int: The sum of the two numbers
"""
return a + b
def subtract_two_numbers(a: int, b: int) -> int:
"""
Subtract two numbers
"""
return a - b
# Tools can still be manually defined and passed into chat
subtract_two_numbers_tool = {
'type': 'function',
'function': {
'name': 'subtract_two_numbers',
'description': 'Subtract two numbers',
'parameters': {
'type': 'object',
'required': ['a', 'b'],
'properties': {
'a': {'type': 'integer', 'description': 'The first number'},
'b': {'type': 'integer', 'description': 'The second number'},
},
},
},
}
prompt = 'What is three minus one?'
print(f'Prompt: {prompt}')
response: ChatResponse = chat(
'llama3.1',
messages=[{'role': 'user', 'content': prompt}],
tools=[add_two_numbers, subtract_two_numbers_tool],
)
available_functions = {
'add_two_numbers': add_two_numbers,
'subtract_two_numbers': subtract_two_numbers,
}
if response.message.tool_calls:
# There may be multiple tool calls in the response
for tool in response.message.tool_calls:
# Ensure the function is available, and then call it
if tool.function.name in available_functions:
print(f'Calling function {tool.function.name}')
print(f'Arguments: {tool.function.arguments}')
function_to_call = available_functions[tool.function.name]
print(f'Function output: {function_to_call(**tool.function.arguments)}')
else:
print(f'Function {tool.function.name} not found')
-3
View File
@@ -1,3 +0,0 @@
# tools
This example demonstrates how to utilize tool calls with an asynchronous Ollama client and the chat endpoint.