from IPython.display import display,Image,Markdown
from datetime import datetime
from pprint import pprint
Cosette’s source
Setup
def print_columns(items, cols=3, width=30):
for i in range(0, len(items), cols):
= items[i:i+cols]
row print(''.join(item[:width-1].ljust(width) for item in row))
= OpenAI()
client = client.models.list()
model_list print(f"Available models as of {datetime.now().strftime('%Y-%m-%d')}:\n")
sorted([m.id for m in model_list])) print_columns(
Available models as of 2025-06-29:
babbage-002 chatgpt-4o-latest codex-mini-latest
computer-use-preview computer-use-preview-2025-03- dall-e-2
dall-e-3 davinci-002 ft:gpt-4o-2024-08-06:answerai
ft:gpt-4o-2024-08-06:answerai ft:gpt-4o-2024-08-06:answerai ft:gpt-4o-mini-2024-07-18:ans
ft:gpt-4o-mini-2024-07-18:ans gpt-3.5-turbo gpt-3.5-turbo-0125
gpt-3.5-turbo-1106 gpt-3.5-turbo-16k gpt-3.5-turbo-instruct
gpt-3.5-turbo-instruct-0914 gpt-4 gpt-4-0125-preview
gpt-4-1106-preview gpt-4-turbo gpt-4-turbo-2024-04-09
gpt-4-turbo-preview gpt-4.1 gpt-4.1-2025-04-14
gpt-4.1-mini gpt-4.1-mini-2025-04-14 gpt-4.1-nano
gpt-4.1-nano-2025-04-14 gpt-4.5-preview gpt-4.5-preview-2025-02-27
gpt-4o gpt-4o-2024-05-13 gpt-4o-2024-08-06
gpt-4o-2024-11-20 gpt-4o-audio-preview gpt-4o-audio-preview-2024-10-
gpt-4o-audio-preview-2024-12- gpt-4o-audio-preview-2025-06- gpt-4o-mini
gpt-4o-mini-2024-07-18 gpt-4o-mini-audio-preview gpt-4o-mini-audio-preview-202
gpt-4o-mini-realtime-preview gpt-4o-mini-realtime-preview- gpt-4o-mini-search-preview
gpt-4o-mini-search-preview-20 gpt-4o-mini-transcribe gpt-4o-mini-tts
gpt-4o-realtime-preview gpt-4o-realtime-preview-2024- gpt-4o-realtime-preview-2024-
gpt-4o-realtime-preview-2025- gpt-4o-search-preview gpt-4o-search-preview-2025-03
gpt-4o-transcribe gpt-image-1 o1
o1-2024-12-17 o1-mini o1-mini-2024-09-12
o1-preview o1-preview-2024-09-12 o1-pro
o1-pro-2025-03-19 o3 o3-2025-04-16
o3-deep-research o3-deep-research-2025-06-26 o3-mini
o3-mini-2025-01-31 o3-pro o3-pro-2025-06-10
o4-mini o4-mini-2025-04-16 o4-mini-deep-research
o4-mini-deep-research-2025-06 omni-moderation-2024-09-26 omni-moderation-latest
text-embedding-3-large text-embedding-3-small text-embedding-ada-002
tts-1 tts-1-1106 tts-1-hd
tts-1-hd-1106 whisper-1
Exported source
= 'o1-preview', 'o1-mini', 'gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'gpt-4', 'gpt-4-32k', 'gpt-3.5-turbo', 'gpt-3.5-turbo-instruct', 'o1', 'o3-mini', 'chatgpt-4o-latest', 'o1-pro', 'o3', 'o4-mini', 'gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano' models
o1
should support images while o1-mini
, o3-mini
do not support images.
can_set_temp
can_set_temp (m)
Exported source
= 'o1-preview', 'o1-mini', 'o3-mini' text_only_models
Exported source
= set(models) - set(('o1-mini', 'o3-mini'))
has_streaming_models = set(models) - set(('o1-mini', 'o3-mini'))
has_sp_models = set(models) - set(('o1', 'o1-mini', 'o3-mini')) has_temp_models
Exported source
def can_stream(m): return m in has_streaming_models
def can_set_sp(m): return m in has_sp_models
def can_set_temp(m): return m in has_temp_models
can_set_sp
can_set_sp (m)
can_stream
can_stream (m)
assert can_stream("gpt-4o")
assert not can_stream("o1-mini")
= 'gpt-4.1-mini' model
OpenAI SDK
= OpenAI().responses cli
= {'role': 'user', 'content': "I'm Jeremy"}
m = cli.create(input=[m], model=model, max_output_tokens=100)
r r
Hi Jeremy! How can I assist you today?
- id: resp_6860b6c2def0819d97c43ec5b03299a202016e8b44c1677f
- created_at: 1751168706.0
- error: None
- incomplete_details: None
- instructions: None
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6c31944819d9dd21c428b9fb00202016e8b44c1677f’, content=[ResponseOutputText(annotations=[], text=‘Hi Jeremy! How can I assist you today?’, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: []
- top_p: 1.0
- background: False
- max_output_tokens: 100
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=9, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=11, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=20)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
Formatting output
r.output_text
'Hi Jeremy! How can I assist you today?'
Exported source
@patch
def _repr_markdown_(self:Response):
= '\n- '.join(f'{k}: {v}' for k,v in dict(self).items())
det = self.output_text
res if not res: return f"- {det}"
return f"""{res}
<details>
- {det}
</details>"""
r
Hi Jeremy! How can I assist you today?
- id: resp_6860b6c2def0819d97c43ec5b03299a202016e8b44c1677f
- created_at: 1751168706.0
- error: None
- incomplete_details: None
- instructions: None
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6c31944819d9dd21c428b9fb00202016e8b44c1677f’, content=[ResponseOutputText(annotations=[], text=‘Hi Jeremy! How can I assist you today?’, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: []
- top_p: 1.0
- background: False
- max_output_tokens: 100
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=9, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=11, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=20)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
r.usage
In: 9; Out: 11; Total: 20
usage
usage (inp=0, out=0)
Slightly more concise version of ResponseUsage
.
Type | Default | Details | |
---|---|---|---|
inp | int | 0 | Number of prompt tokens |
out | int | 0 | Number of completion tokens |
Exported source
def usage(inp=0, # Number of prompt tokens
=0 # Number of completion tokens
out
):"Slightly more concise version of `ResponseUsage`."
return ResponseUsage(input_tokens=inp, output_tokens=out, total_tokens=inp+out, input_tokens_details={'cached_tokens':0}, output_tokens_details={'cached_tokens':0, 'reasoning_tokens':0})
5) usage(
In: 5; Out: 0; Total: 5
ResponseUsage.__repr__
ResponseUsage.__repr__ ()
Return repr(self).
Exported source
@patch
def __repr__(self:ResponseUsage): return f'In: {self.input_tokens}; Out: {self.output_tokens}; Total: {self.total_tokens}'
r.usage
In: 9; Out: 11; Total: 20
ResponseUsage.__add__
ResponseUsage.__add__ (b)
Add together each of input_tokens
and output_tokens
Exported source
@patch
def __add__(self:ResponseUsage, b):
"Add together each of `input_tokens` and `output_tokens`"
return usage(self.input_tokens+b.input_tokens, self.output_tokens+b.output_tokens)
+r.usage r.usage
In: 18; Out: 22; Total: 40
wrap_latex
wrap_latex (text)
Replace OpenAI LaTeX codes with markdown-compatible ones
Creating messages
Creating correctly formatted dict
s from scratch every time isn’t very handy, so we’ll import a couple of helper functions from the msglm
library.
Let’s use mk_msg
to recreate our msg {'role': 'user', 'content': "I'm Jeremy"}
from earlier.
= "I'm Jeremy"
prompt = mk_msg(prompt)
m = cli.create(input=[m], model=model, max_output_tokens=100)
r r
Hi Jeremy! How can I assist you today?
- id: resp_6860b6c3cf80819fb87d7affde83676e08aba030855751ce
- created_at: 1751168707.0
- error: None
- incomplete_details: None
- instructions: None
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6c3fe94819f87d52ab99dc1596a08aba030855751ce’, content=[ResponseOutputText(annotations=[], text=‘Hi Jeremy! How can I assist you today?’, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: []
- top_p: 1.0
- background: False
- max_output_tokens: 100
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=9, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=11, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=20)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
We can pass more than just text messages to OpenAI. As we’ll see later we can also pass images, SDK objects, etc. To handle these different data types we need to pass the type along with our content to OpenAI.
mk_msg
infers the type automatically and creates the appropriate data structure.
LLMs, don’t actually have state, but instead dialogs are created by passing back all previous prompts and responses every time. With OpenAI, they always alternate user and assistant. We’ll use mk_msgs
from msglm
to make it easier to build up these dialog lists.
= mk_msgs([prompt, r, "I forgot my name. Can you remind me please?"])
msgs msgs
[{'role': 'user', 'content': "I'm Jeremy"},
ResponseOutputMessage(id='msg_6860b6c3fe94819f87d52ab99dc1596a08aba030855751ce', content=[ResponseOutputText(annotations=[], text='Hi Jeremy! How can I assist you today?', type='output_text', logprobs=[])], role='assistant', status='completed', type='message'),
{'role': 'user', 'content': 'I forgot my name. Can you remind me please?'}]
input=msgs, model=model, max_output_tokens=200) cli.create(
You mentioned that your name is Jeremy. Is there anything else you’d like help with?
- id: resp_6860b6c4883c819fa00ba156a8b3ff7c08aba030855751ce
- created_at: 1751168708.0
- error: None
- incomplete_details: None
- instructions: None
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6c51e70819f9956f6d78bfa64a808aba030855751ce’, content=[ResponseOutputText(annotations=[], text=“You mentioned that your name is Jeremy. Is there anything else you’d like help with?”, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: []
- top_p: 1.0
- background: False
- max_output_tokens: 200
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=38, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=18, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=56)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
Client
Basics
Client
Client (model, cli=None)
Basic LLM messages client.
Exported source
class Client:
def __init__(self, model, cli=None):
"Basic LLM messages client."
self.model,self.use = model,usage(0,0)
self.text_only = model in text_only_models
self.c = (cli or OpenAI()).responses
= Client(model)
c c.use
In: 0; Out: 0; Total: 0
Exported source
@patch
def _r(self:Client, r):
"Store the result of the message and accrue total usage."
self.result = r
if getattr(r,'usage',None): self.use += r.usage
return r
c._r(r) c.use
In: 9; Out: 11; Total: 20
mk_openai_func
mk_openai_func (f)
mk_tool_choice
mk_tool_choice (f)
get_stream
get_stream (o, r, cli, cb=None)
Client.__call__
Client.__call__ (msgs:list, sp:str='', maxtok=4096, stream:bool=False, tools:Optional[list]=None, tool_choice:Optional[str]=None, cb:<built- infunctioncallable>=None, background:Optional[bool]|NotGiven=NOT_GIVEN, include:Op tional[List[ResponseIncludable]]|NotGiven=NOT_GIVEN, input:Union[str,ResponseInputParam]|NotGiven=NOT_GIVEN, instructions:Optional[str]|NotGiven=NOT_GIVEN, max_output_tokens:Optional[int]|NotGiven=NOT_GIVEN, max_tool_calls:Optional[int]|NotGiven=NOT_GIVEN, metadata:Optional[Metadata]|NotGiven=NOT_GIVEN, model:ResponsesModel|NotGiven=NOT_GIVEN, parallel_tool_calls:Optional[bool]|NotGiven=NOT_GIVEN, previous_response_id:Optional[str]|NotGiven=NOT_GIVEN, prompt:Optional[ResponsePromptParam]|NotGiven=NOT_GIVEN, reasoning:Optional[Reasoning]|NotGiven=NOT_GIVEN, servic e_tier:"Optional[Literal['auto','default','flex','scale' ,'priority']]|NotGiven"=NOT_GIVEN, store:Optional[bool]|NotGiven=NOT_GIVEN, temperature:Optional[float]|NotGiven=NOT_GIVEN, text:ResponseTextConfigParam|NotGiven=NOT_GIVEN, top_logprobs:Optional[int]|NotGiven=NOT_GIVEN, top_p:Optional[float]|NotGiven=NOT_GIVEN, truncation:"Op tional[Literal['auto','disabled']]|NotGiven"=NOT_GIVEN, user:str|NotGiven=NOT_GIVEN, extra_headers:Headers|None=None, extra_query:Query|None=None, extra_body:Body|None=None, timeout:float|httpx.Timeout|None|NotGiven=NOT_GIVEN)
Make a call to LLM.
Type | Default | Details | |
---|---|---|---|
msgs | list | List of messages in the dialog | |
sp | str | System prompt | |
maxtok | int | 4096 | Maximum tokens |
stream | bool | False | Stream response? |
tools | Optional | None | List of tools to make available |
tool_choice | Optional | None | Forced tool choice |
cb | callable | None | Callback after completion |
background | Optional[bool] | NotGiven | NOT_GIVEN | |
include | Optional[List[ResponseIncludable]] | NotGiven | NOT_GIVEN | |
input | Union[str, ResponseInputParam] | NotGiven | NOT_GIVEN | |
instructions | Optional[str] | NotGiven | NOT_GIVEN | |
max_output_tokens | Optional[int] | NotGiven | NOT_GIVEN | |
max_tool_calls | Optional[int] | NotGiven | NOT_GIVEN | |
metadata | Optional[Metadata] | NotGiven | NOT_GIVEN | |
model | ResponsesModel | NotGiven | NOT_GIVEN | |
parallel_tool_calls | Optional[bool] | NotGiven | NOT_GIVEN | |
previous_response_id | Optional[str] | NotGiven | NOT_GIVEN | |
prompt | Optional[ResponsePromptParam] | NotGiven | NOT_GIVEN | |
reasoning | Optional[Reasoning] | NotGiven | NOT_GIVEN | |
service_tier | Optional[Literal[‘auto’, ‘default’, ‘flex’, ‘scale’, ‘priority’]] | NotGiven | NOT_GIVEN | |
store | Optional[bool] | NotGiven | NOT_GIVEN | |
temperature | Optional[float] | NotGiven | NOT_GIVEN | |
text | ResponseTextConfigParam | NotGiven | NOT_GIVEN | |
top_logprobs | Optional[int] | NotGiven | NOT_GIVEN | |
top_p | Optional[float] | NotGiven | NOT_GIVEN | |
truncation | Optional[Literal[‘auto’, ‘disabled’]] | NotGiven | NOT_GIVEN | |
user | str | NotGiven | NOT_GIVEN | |
extra_headers | Optional | None | Use the following arguments if you need to pass additional parameters to the API that aren’t available via kwargs. The extra values given here take precedence over values defined on the client or passed to this method. |
extra_query | Query | None | None | |
extra_body | Body | None | None | |
timeout | float | httpx.Timeout | None | NotGiven | NOT_GIVEN |
Exported source
@patch
@delegates(Responses.create)
def __call__(self:Client,
list, # List of messages in the dialog
msgs:str='', # System prompt
sp:=4096, # Maximum tokens
maxtokbool=False, # Stream response?
stream:list]=None, # List of tools to make available
tools:Optional[str]=None, # Forced tool choice
tool_choice:Optional[callable=None, # Callback after completion
cb:**kwargs):
"Make a call to LLM."
if tools: assert not self.text_only, "Tool use is not supported by the current model type."
if any(c['type'] == 'image_url' for msg in msgs if isinstance(msg, dict) and isinstance(msg.get('content'), list) for c in msg['content']): assert not self.text_only, "Images are not supported by the current model type."
= [mk_openai_func(o) for o in listify(tools)]
tools = self.c.create(
r =self.model, input=msgs, max_output_tokens=maxtok, stream=stream, instructions=sp,
model=tools, tool_choice=mk_tool_choice(tool_choice), **kwargs)
toolsif stream: return get_stream(r, self, cb=cb)
else:
= self._r(r)
res if cb: cb(res)
return res
= 'Hi' msgs
c(msgs)
Hello! How can I assist you today?
- id: resp_6860b6c5d9088192b5decb672da395ce0e2f96a5780a9890
- created_at: 1751168709.0
- error: None
- incomplete_details: None
- instructions: None
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6c60c908192b9fe62d41c0398180e2f96a5780a9890’, content=[ResponseOutputText(annotations=[], text=‘Hello! How can I assist you today?’, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: []
- top_p: 1.0
- background: False
- max_output_tokens: 4096
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=8, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=10, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=18)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
c.use
In: 17; Out: 21; Total: 38
= c(msgs, stream=True)
r for o in r: print(o, end='')
Hello! How can I assist you today?
r.value
Hello! How can I assist you today?
- id: resp_6860b6c68fac819c975536851842c09b0101561ca0fa1d7e
- created_at: 1751168710.0
- error: None
- incomplete_details: None
- instructions: None
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6c6b538819c84fe83cf5ff1b5550101561ca0fa1d7e’, content=[ResponseOutputText(annotations=[], text=‘Hello! How can I assist you today?’, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: []
- top_p: 1.0
- background: False
- max_output_tokens: 4096
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=8, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=10, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=18)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
len(r.events)
17
c.use
In: 25; Out: 31; Total: 56
='Talk like GLaDOS.') c(msgs, sp
Well, well, a greeting. How quaint. Hello. I suppose I’ll have to pretend to be interested. What do you want?
- id: resp_6860b6c73bdc8191addc66e3e5038e620c71e37a6000fc63
- created_at: 1751168711.0
- error: None
- incomplete_details: None
- instructions: Talk like GLaDOS.
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6c76c588191ba2e4aed66ff7fcf0c71e37a6000fc63’, content=[ResponseOutputText(annotations=[], text=“Well, well, a greeting. How quaint. Hello. I suppose I’ll have to pretend to be interested. What do you want?”, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: []
- top_p: 1.0
- background: False
- max_output_tokens: 4096
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=18, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=28, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=46)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
Images
As everyone knows, when testing image APIs you have to use a cute puppy.
# Image is Cute_dog.jpg from Wikimedia
= Path('samples/puppy.jpg')
fn =fn, width=200) Image(filename
= fn.read_bytes() img
OpenAI expects an image message to have the following structure
{"type": "image_url",
"image_url": {
"url": f"data:{MEDIA_TYPE};base64,{IMG}"
} }
msglm
automatically detects if a message is an image, encodes it, and generates the data structure above. All we need to do is a create a list containing our image and a query and then pass it to mk_msg
.
Let’s try it out…
= "In brief, what color flowers are in this image?"
q = [mk_msg(img), mk_msg(q)] msg
= Client(model)
c c(msg)
The flowers in the image are purple.
- id: resp_6860b6c8288481a3b7ece65c99907b7607d76b80465166f2
- created_at: 1751168712.0
- error: None
- incomplete_details: None
- instructions: None
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6c9788481a39500740b397662ce07d76b80465166f2’, content=[ResponseOutputText(annotations=[], text=‘The flowers in the image are purple.’, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: []
- top_p: 1.0
- background: False
- max_output_tokens: 4096
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=138, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=9, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=147)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
Tool use
Basic tool calling
def sums(
int, # First thing to sum
a:int # Second thing to sum
b:-> int: # The sum of the inputs
) "Adds a + b."
print(f"Finding the sum of {a} and {b}")
return a + b
def add(x: int, y:int):
"adds x and y"
return x + y
mk_openai_func(add)
{'type': 'function',
'name': 'add',
'description': 'adds x and y',
'parameters': {'type': 'object',
'properties': {'x': {'type': 'integer', 'description': ''},
'y': {'type': 'integer', 'description': ''}},
'required': ['x', 'y']}}
= "You are a helpful assistant. When using tools, be sure to pass all required parameters." sysp
= 604542,6458932
a,b = f"What is {a}+{b}?"
pr =sums
tools="sums" tool_choice
= [mk_msg(pr)]
msgs = c(msgs, sp=sysp, tools=tools, tool_choice='required') r
= [o for o in r.output if isinstance(o, ResponseFunctionToolCall)]
tc tc
[ResponseFunctionToolCall(arguments='{"a":604542,"b":6458932}', call_id='call_uaVtNW9g0b27Q6OaQT4UrUr2', name='sums', type='function_call', id='fc_6860b6e0bb588191a7e576a12369112804eca1b8f738cf44', status='completed')]
= tc[0]
func func
ResponseFunctionToolCall(arguments='{"a":604542,"b":6458932}', call_id='call_uaVtNW9g0b27Q6OaQT4UrUr2', name='sums', type='function_call', id='fc_6860b6e0bb588191a7e576a12369112804eca1b8f738cf44', status='completed')
call_func_openai
call_func_openai (func:openai.types.chat.chat_completion_message_tool_ca ll.Function, ns:Optional[collections.abc.Mapping]=None)
Exported source
def call_func_openai(func:types.chat.chat_completion_message_tool_call.Function, ns:Optional[abc.Mapping]=None):
return call_func(func.name, ast.literal_eval(func.arguments), ns, raise_on_err=False)
= mk_ns(sums)
ns = call_func_openai(func, ns=ns)
res res
Finding the sum of 604542 and 6458932
7063474
mk_toolres
mk_toolres (r:collections.abc.Mapping, ns:Optional[collections.abc.Mapping]=None)
Create a tool_result
message from response r
.
Type | Default | Details | |
---|---|---|---|
r | Mapping | Response containing tool use request | |
ns | Optional | None | Namespace to search for tools |
Exported source
def _toolres(r, ns):
"Create a result dict from `tcs`."
= [o for o in getattr(r, 'output', []) if isinstance(o, ResponseFunctionToolCall)]
tcs if ns is None: ns = globals()
return { tc.call_id: call_func_openai(tc, ns=mk_ns(ns)) for tc in tcs }
Exported source
def mk_toolres(
# Response containing tool use request
r:abc.Mapping, =None # Namespace to search for tools
ns:Optional[abc.Mapping]
):"Create a `tool_result` message from response `r`."
= _toolres(r, ns)
tr = mk_msg(r)
r = [r] if isinstance(r, dict) else listify(r)
res for k,v in tr.items(): res.append(dict(type="function_call_output", call_id=k, output=str(v)))
return res
= mk_toolres(r, ns=ns)
tr tr
Finding the sum of 604542 and 6458932
[ResponseFunctionToolCall(arguments='{"a":604542,"b":6458932}', call_id='call_uaVtNW9g0b27Q6OaQT4UrUr2', name='sums', type='function_call', id='fc_6860b6e0bb588191a7e576a12369112804eca1b8f738cf44', status='completed'),
{'type': 'function_call_output',
'call_id': 'call_uaVtNW9g0b27Q6OaQT4UrUr2',
'output': '7063474'}]
= msgs + tr m2
= c(mk_msgs(m2), sp=sysp, tools=tools)
res res
The sum of 604,542 and 6,458,932 is 7,063,474.
- id: resp_6860b6e1774481919877d63938fbef9804eca1b8f738cf44
- created_at: 1751168737.0
- error: None
- incomplete_details: None
- instructions: You are a helpful assistant. When using tools, be sure to pass all required parameters.
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6e1cdac8191aff2bd3e0b8dc8d004eca1b8f738cf44’, content=[ResponseOutputText(annotations=[], text=‘The sum of 604,542 and 6,458,932 is 7,063,474.’, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: [FunctionTool(name=‘sums’, parameters={‘type’: ‘object’, ‘properties’: {‘a’: {‘type’: ‘integer’, ‘description’: ‘First thing to sum’}, ‘b’: {‘type’: ‘integer’, ‘description’: ‘Second thing to sum’}}, ‘required’: [‘a’, ‘b’]}, strict=True, type=‘function’, description=‘Adds a + b.:- type: integer’)]
- top_p: 1.0
- background: False
- max_output_tokens: 4096
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=119, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=24, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=143)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
This should also work in situations where no tool use is required:
= mk_toolres("I'm Jeremy")
msgs = c(msgs, sp=sysp, tools=tools)
r += mk_toolres(r)
msgs = c(mk_msgs(msgs), sp=sysp, tools=tools)
res res
Hello Jeremy! How can I help you today?
- id: resp_6860b6e43590819fb4e6061ec77df8d7057c7c557baac8df
- created_at: 1751168740.0
- error: None
- incomplete_details: None
- instructions: You are a helpful assistant. When using tools, be sure to pass all required parameters.
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6e4792c819f86416f387e4fb414057c7c557baac8df’, content=[ResponseOutputText(annotations=[], text=‘Hello Jeremy! How can I help you today?’, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: [FunctionTool(name=‘sums’, parameters={‘type’: ‘object’, ‘properties’: {‘a’: {‘type’: ‘integer’, ‘description’: ‘First thing to sum’}, ‘b’: {‘type’: ‘integer’, ‘description’: ‘Second thing to sum’}}, ‘required’: [‘a’, ‘b’]}, strict=True, type=‘function’, description=‘Adds a + b.:- type: integer’)]
- top_p: 1.0
- background: False
- max_output_tokens: 4096
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=95, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=12, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=107)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
Client.structured
Client.structured (msgs:list, tools:Optional[list]=None, ns:Optional[collections.abc.Mapping]=None, sp:str='', maxtok=4096, stream:bool=False, tool_choice:Optional[str]=None, cb:<built- infunctioncallable>=None, background:Optional[bool]|NotGiven=NOT_GIVEN, include: Optional[List[ResponseIncludable]]|NotGiven=NOT_GIVEN, input:Union[str,ResponseInputParam]|NotGiven=NOT_GIVEN , instructions:Optional[str]|NotGiven=NOT_GIVEN, max_output_tokens:Optional[int]|NotGiven=NOT_GIVEN, max_tool_calls:Optional[int]|NotGiven=NOT_GIVEN, metadata:Optional[Metadata]|NotGiven=NOT_GIVEN, model:ResponsesModel|NotGiven=NOT_GIVEN, parallel_tool_calls:Optional[bool]|NotGiven=NOT_GIVEN, previous_response_id:Optional[str]|NotGiven=NOT_GIVEN, prompt:Optional[ResponsePromptParam]|NotGiven=NOT_GIVE N, reasoning:Optional[Reasoning]|NotGiven=NOT_GIVEN, s ervice_tier:"Optional[Literal['auto','default','flex', 'scale','priority']]|NotGiven"=NOT_GIVEN, store:Optional[bool]|NotGiven=NOT_GIVEN, temperature:Optional[float]|NotGiven=NOT_GIVEN, text:ResponseTextConfigParam|NotGiven=NOT_GIVEN, top_logprobs:Optional[int]|NotGiven=NOT_GIVEN, top_p:Optional[float]|NotGiven=NOT_GIVEN, truncation:" Optional[Literal['auto','disabled']]|NotGiven"=NOT_GIV EN, user:str|NotGiven=NOT_GIVEN, extra_headers:Headers|None=None, extra_query:Query|None=None, extra_body:Body|None=None, timeout:float|httpx.Timeout|None|NotGiven=NOT_GIVEN)
Return the value of all tool calls (generally used for structured outputs)
Type | Default | Details | |
---|---|---|---|
msgs | list | Prompt | |
tools | Optional | None | List of tools to make available to OpenAI model |
ns | Optional | None | Namespace to search for tools |
sp | str | System prompt | |
maxtok | int | 4096 | Maximum tokens |
stream | bool | False | Stream response? |
tool_choice | Optional | None | Forced tool choice |
cb | callable | None | Callback after completion |
background | Optional[bool] | NotGiven | NOT_GIVEN | |
include | Optional[List[ResponseIncludable]] | NotGiven | NOT_GIVEN | |
input | Union[str, ResponseInputParam] | NotGiven | NOT_GIVEN | |
instructions | Optional[str] | NotGiven | NOT_GIVEN | |
max_output_tokens | Optional[int] | NotGiven | NOT_GIVEN | |
max_tool_calls | Optional[int] | NotGiven | NOT_GIVEN | |
metadata | Optional[Metadata] | NotGiven | NOT_GIVEN | |
model | ResponsesModel | NotGiven | NOT_GIVEN | |
parallel_tool_calls | Optional[bool] | NotGiven | NOT_GIVEN | |
previous_response_id | Optional[str] | NotGiven | NOT_GIVEN | |
prompt | Optional[ResponsePromptParam] | NotGiven | NOT_GIVEN | |
reasoning | Optional[Reasoning] | NotGiven | NOT_GIVEN | |
service_tier | Optional[Literal[‘auto’, ‘default’, ‘flex’, ‘scale’, ‘priority’]] | NotGiven | NOT_GIVEN | |
store | Optional[bool] | NotGiven | NOT_GIVEN | |
temperature | Optional[float] | NotGiven | NOT_GIVEN | |
text | ResponseTextConfigParam | NotGiven | NOT_GIVEN | |
top_logprobs | Optional[int] | NotGiven | NOT_GIVEN | |
top_p | Optional[float] | NotGiven | NOT_GIVEN | |
truncation | Optional[Literal[‘auto’, ‘disabled’]] | NotGiven | NOT_GIVEN | |
user | str | NotGiven | NOT_GIVEN | |
extra_headers | Optional | None | Use the following arguments if you need to pass additional parameters to the API that aren’t available via kwargs. The extra values given here take precedence over values defined on the client or passed to this method. |
extra_query | Query | None | None | |
extra_body | Body | None | None | |
timeout | float | httpx.Timeout | None | NotGiven | NOT_GIVEN |
Exported source
@patch
@delegates(Client.__call__)
def structured(self:Client,
list, # Prompt
msgs: list]=None, # List of tools to make available to OpenAI model
tools:Optional[=None, # Namespace to search for tools
ns:Optional[abc.Mapping]**kwargs):
"Return the value of all tool calls (generally used for structured outputs)"
if ns is None: ns = mk_ns(tools)
= self(msgs, tools=tools, tool_choice='required', **kwargs)
r return first(_toolres(r, ns).values())
class PrimeMinister(BasicRepr):
"An Australian prime minister"
def __init__(
self,
str, # First name
firstname:str, # Surname
surname:str, # Date of birth
dob:int, # Year first became PM
year_entered: ): store_attr()
= Client('gpt-4.1')
c1 = 'Who was the first prime minister of Australia?'
pr c1.structured(pr, [PrimeMinister])
PrimeMinister(firstname='Edmund', surname='Barton', dob='1849-01-18', year_entered=1901)
Mocking
mock_tooluse
mock_tooluse (name:str, res, **kwargs)
Type | Details | |
---|---|---|
name | str | The name of the called function |
res | The result of calling the function | |
kwargs | VAR_KEYWORD |
Exported source
def _mock_id(): return 'call_' + ''.join(choices(ascii_letters+digits, k=24))
def mock_tooluse(name:str, # The name of the called function
# The result of calling the function
res, **kwargs): # The arguments to the function
""
raise Exception("This has not been updated for the `responses` API yet")
id = _mock_id()
= dict(arguments=json.dumps(kwargs), name=name)
func = dict(id=id, function=func, type='function')
tc = dict(content=None, role='assistant', tool_calls=[tc])
req = mk_msg('' if res is None else str(res), 'tool', tool_call_id=id, name=name)
resp return [req,resp]
This function mocks the messages needed to implement tool use, for situations where you want to insert tool use messages into a dialog without actually calling into the model.
# Currently not working
# tu = mock_tooluse(name='sums', res=7063474, a=604542, b=6458932)
# r = c([mk_msg(pr)]+tu, tools=tools)
# r
Streaming tool calling
= [mk_msg(pr)]
msgs = c(msgs, sp=sysp, tools=tools, stream=True) r
We can stream back any tool call text (which may be empty):
for o in r: print(o, end='')
The first Prime Minister of Australia was Edmund Barton. He served as the Prime Minister from 1901 to 1903.
After streaming is complete, value.output
will contain the tool calls:
r.value.output
[ResponseOutputMessage(id='msg_6860b6e98a88819e9230fcc0eebe574c0cc64f4968770be2', content=[ResponseOutputText(annotations=[], text='The first Prime Minister of Australia was Edmund Barton. He served as the Prime Minister from 1901 to 1903.', type='output_text', logprobs=[])], role='assistant', status='completed', type='message')]
Therefore we can repeat the same process as before, but using the value
attr:
= mk_toolres(r.value, ns=ns)
tr += tr
msgs =sysp, tools=tools) c(mk_msgs(msgs), sp
Is there anything else you would like to know about Australian history or any other topic?
- id: resp_6860b6ea34f0819ea06b889eae1732320cc64f4968770be2
- created_at: 1751168746.0
- error: None
- incomplete_details: None
- instructions: You are a helpful assistant. When using tools, be sure to pass all required parameters.
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6ea71cc819ebe6f2f29010c38580cc64f4968770be2’, content=[ResponseOutputText(annotations=[], text=‘Is there anything else you would like to know about Australian history or any other topic?’, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: [FunctionTool(name=‘sums’, parameters={‘type’: ‘object’, ‘properties’: {‘a’: {‘type’: ‘integer’, ‘description’: ‘First thing to sum’}, ‘b’: {‘type’: ‘integer’, ‘description’: ‘Second thing to sum’}}, ‘required’: [‘a’, ‘b’]}, strict=True, type=‘function’, description=‘Adds a + b.:- type: integer’)]
- top_p: 1.0
- background: False
- max_output_tokens: 4096
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=117, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=19, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=136)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
Chat
Basic chat
Chat
Chat (model:Optional[str]=None, cli:Optional[__main__.Client]=None, sp='', tools:Optional[list]=None, hist:list=None, tool_choice:Optional[str]=None, ns:Optional[collections.abc.Mapping]=None)
OpenAI chat client.
Type | Default | Details | |
---|---|---|---|
model | Optional | None | Model to use (leave empty if passing cli ) |
cli | Optional | None | Client to use (leave empty if passing model ) |
sp | str | Optional system prompt | |
tools | Optional | None | List of tools to make available |
hist | list | None | Initialize history |
tool_choice | Optional | None | Forced tool choice |
ns | Optional | None | Namespace to search for tools |
Exported source
class Chat:
def __init__(self,
str]=None, # Model to use (leave empty if passing `cli`)
model:Optional[=None, # Client to use (leave empty if passing `model`)
cli:Optional[Client]='', # Optional system prompt
splist]=None, # List of tools to make available
tools:Optional[list = None, # Initialize history
hist: str]=None, # Forced tool choice
tool_choice:Optional[=None): # Namespace to search for tools
ns:Optional[abc.Mapping]"OpenAI chat client."
assert model or cli
self.c = (cli or Client(model))
self.h = hist if hist else []
if ns is None: ns=tools
self.sp,self.tools,self.tool_choice,self.ns = sp,tools,tool_choice,ns
@property
def use(self): return self.c.use
= Chat(model, sp=sysp)
chat chat.c.use, chat.h
(In: 0; Out: 0; Total: 0, [])
Chat.__call__
Chat.__call__ (pr=None, stream:bool=False, tools=None, tool_choice=None, background:Optional[bool]|NotGiven=NOT_GIVEN, include:Opti onal[List[ResponseIncludable]]|NotGiven=NOT_GIVEN, input:Union[str,ResponseInputParam]|NotGiven=NOT_GIVEN, instructions:Optional[str]|NotGiven=NOT_GIVEN, max_output_tokens:Optional[int]|NotGiven=NOT_GIVEN, max_tool_calls:Optional[int]|NotGiven=NOT_GIVEN, metadata:Optional[Metadata]|NotGiven=NOT_GIVEN, model:ResponsesModel|NotGiven=NOT_GIVEN, parallel_tool_calls:Optional[bool]|NotGiven=NOT_GIVEN, previous_response_id:Optional[str]|NotGiven=NOT_GIVEN, prompt:Optional[ResponsePromptParam]|NotGiven=NOT_GIVEN, reasoning:Optional[Reasoning]|NotGiven=NOT_GIVEN, service_ tier:"Optional[Literal['auto','default','flex','scale','pr iority']]|NotGiven"=NOT_GIVEN, store:Optional[bool]|NotGiven=NOT_GIVEN, temperature:Optional[float]|NotGiven=NOT_GIVEN, text:ResponseTextConfigParam|NotGiven=NOT_GIVEN, top_logprobs:Optional[int]|NotGiven=NOT_GIVEN, top_p:Optional[float]|NotGiven=NOT_GIVEN, truncation:"Opti onal[Literal['auto','disabled']]|NotGiven"=NOT_GIVEN, user:str|NotGiven=NOT_GIVEN, extra_headers:Headers|None=None, extra_query:Query|None=None, extra_body:Body|None=None, timeout:float|httpx.Timeout|None|NotGiven=NOT_GIVEN)
Add prompt pr
to dialog and get a response
Type | Default | Details | |
---|---|---|---|
pr | NoneType | None | Prompt / message |
stream | bool | False | Stream response? |
tools | NoneType | None | Tools to use |
tool_choice | NoneType | None | Required tools to use |
background | Optional[bool] | NotGiven | NOT_GIVEN | |
include | Optional[List[ResponseIncludable]] | NotGiven | NOT_GIVEN | |
input | Union[str, ResponseInputParam] | NotGiven | NOT_GIVEN | |
instructions | Optional[str] | NotGiven | NOT_GIVEN | |
max_output_tokens | Optional[int] | NotGiven | NOT_GIVEN | |
max_tool_calls | Optional[int] | NotGiven | NOT_GIVEN | |
metadata | Optional[Metadata] | NotGiven | NOT_GIVEN | |
model | ResponsesModel | NotGiven | NOT_GIVEN | |
parallel_tool_calls | Optional[bool] | NotGiven | NOT_GIVEN | |
previous_response_id | Optional[str] | NotGiven | NOT_GIVEN | |
prompt | Optional[ResponsePromptParam] | NotGiven | NOT_GIVEN | |
reasoning | Optional[Reasoning] | NotGiven | NOT_GIVEN | |
service_tier | Optional[Literal[‘auto’, ‘default’, ‘flex’, ‘scale’, ‘priority’]] | NotGiven | NOT_GIVEN | |
store | Optional[bool] | NotGiven | NOT_GIVEN | |
temperature | Optional[float] | NotGiven | NOT_GIVEN | |
text | ResponseTextConfigParam | NotGiven | NOT_GIVEN | |
top_logprobs | Optional[int] | NotGiven | NOT_GIVEN | |
top_p | Optional[float] | NotGiven | NOT_GIVEN | |
truncation | Optional[Literal[‘auto’, ‘disabled’]] | NotGiven | NOT_GIVEN | |
user | str | NotGiven | NOT_GIVEN | |
extra_headers | Optional | None | Use the following arguments if you need to pass additional parameters to the API that aren’t available via kwargs. The extra values given here take precedence over values defined on the client or passed to this method. |
extra_query | Query | None | None | |
extra_body | Body | None | None | |
timeout | float | httpx.Timeout | None | NotGiven | NOT_GIVEN |
Exported source
@patch
@delegates(Responses.create)
def __call__(self:Chat,
=None, # Prompt / message
prbool=False, # Stream response?
stream:=None, # Tools to use
tools=None, # Required tools to use
tool_choice**kwargs):
"Add prompt `pr` to dialog and get a response"
if isinstance(pr,str): pr = pr.strip()
if pr: self.h.append(mk_msg(pr))
if not tools: tools = self.tools
if not tool_choice: tool_choice = self.tool_choice
def _cb(v):
self.last = mk_toolres(v, ns=self.ns)
self.h += self.last
= self.c(self.h, sp=self.sp, stream=stream, cb=_cb, tools=tools, **kwargs)
res return res
"I'm Jeremy")
chat("What's my name?") chat(
Your name is Jeremy. How can I help you today, Jeremy?
- id: resp_6860b6ebdc7c819ca2003bbdd6dad26609b3c6ecae094c91
- created_at: 1751168747.0
- error: None
- incomplete_details: None
- instructions: You are a helpful assistant. When using tools, be sure to pass all required parameters.
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6ec0b4c819cb9cb0c4890dcc38909b3c6ecae094c91’, content=[ResponseOutputText(annotations=[], text=‘Your name is Jeremy. How can I help you today, Jeremy?’, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: []
- top_p: 1.0
- background: False
- max_output_tokens: 4096
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=54, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=15, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=69)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
= Chat(model, sp=sysp)
chat for o in chat("I'm Jeremy", stream=True): print(o, end='')
Hello Jeremy! How can I assist you today?
= chat("What's my name?", stream=True)
r for o in r: print(o, end='')
Your name is Jeremy. How can I help you today, Jeremy?
r.value
Your name is Jeremy. How can I help you today, Jeremy?
- id: resp_6860b6ed4a648192bf7158dfa793ce4b06d79e5aa6e8f0ee
- created_at: 1751168749.0
- error: None
- incomplete_details: None
- instructions: You are a helpful assistant. When using tools, be sure to pass all required parameters.
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6edb5b081928df1b9e6c15a733f06d79e5aa6e8f0ee’, content=[ResponseOutputText(annotations=[], text=‘Your name is Jeremy. How can I help you today, Jeremy?’, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: []
- top_p: 1.0
- background: False
- max_output_tokens: 4096
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=53, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=15, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=68)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
History is stored in the h
attr:
chat.h
[{'role': 'user', 'content': "I'm Jeremy"},
ResponseOutputMessage(id='msg_6860b6ecc71c81928f2e90f3604c802206d79e5aa6e8f0ee', content=[ResponseOutputText(annotations=[], text='Hello Jeremy! How can I assist you today?', type='output_text', logprobs=[])], role='assistant', status='completed', type='message'),
{'role': 'user', 'content': "What's my name?"},
ResponseOutputMessage(id='msg_6860b6edb5b081928df1b9e6c15a733f06d79e5aa6e8f0ee', content=[ResponseOutputText(annotations=[], text='Your name is Jeremy. How can I help you today, Jeremy?', type='output_text', logprobs=[])], role='assistant', status='completed', type='message')]
Chat tool use
= f"What is {a}+{b}?"
pr pr
'What is 604542+6458932?'
= Chat(model, sp=sysp, tools=[sums])
chat = chat(pr)
r r.output
Finding the sum of 604542 and 6458932
[ResponseFunctionToolCall(arguments='{"a":604542,"b":6458932}', call_id='call_RaEWtJETzIccIaSWmdqdeTr3', name='sums', type='function_call', id='fc_6860b6eeb520819d81bd7f42769211fa061f9bb8fcbf78f2', status='completed')]
chat()
The sum of 604542 and 6458932 is 7,063,474.
- id: resp_6860b6ef4a1c819d971d384bdec29a49061f9bb8fcbf78f2
- created_at: 1751168751.0
- error: None
- incomplete_details: None
- instructions: You are a helpful assistant. When using tools, be sure to pass all required parameters.
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6ef9674819da9a5c85743167726061f9bb8fcbf78f2’, content=[ResponseOutputText(annotations=[], text=‘The sum of 604542 and 6458932 is 7,063,474.’, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: [FunctionTool(name=‘sums’, parameters={‘type’: ‘object’, ‘properties’: {‘a’: {‘type’: ‘integer’, ‘description’: ‘First thing to sum’}, ‘b’: {‘type’: ‘integer’, ‘description’: ‘Second thing to sum’}}, ‘required’: [‘a’, ‘b’]}, strict=True, type=‘function’, description=‘Adds a + b.:- type: integer’)]
- top_p: 1.0
- background: False
- max_output_tokens: 4096
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=122, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=21, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=143)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
= "In brief, what color flowers are in this image?"
q chat([img, q])
The flowers in the image are purple.
- id: resp_6860b6f024b0819daf5baf996aafe227061f9bb8fcbf78f2
- created_at: 1751168752.0
- error: None
- incomplete_details: None
- instructions: You are a helpful assistant. When using tools, be sure to pass all required parameters.
- metadata: {}
- model: gpt-4.1-mini-2025-04-14
- object: response
- output: [ResponseOutputMessage(id=‘msg_6860b6f0aaf4819dbf1e775e7344c0ae061f9bb8fcbf78f2’, content=[ResponseOutputText(annotations=[], text=‘The flowers in the image are purple.’, type=‘output_text’, logprobs=[])], role=‘assistant’, status=‘completed’, type=‘message’)]
- parallel_tool_calls: True
- temperature: 1.0
- tool_choice: auto
- tools: [FunctionTool(name=‘sums’, parameters={‘type’: ‘object’, ‘properties’: {‘a’: {‘type’: ‘integer’, ‘description’: ‘First thing to sum’}, ‘b’: {‘type’: ‘integer’, ‘description’: ‘Second thing to sum’}}, ‘required’: [‘a’, ‘b’]}, strict=True, type=‘function’, description=‘Adds a + b.:- type: integer’)]
- top_p: 1.0
- background: False
- max_output_tokens: 4096
- previous_response_id: None
- prompt: None
- reasoning: Reasoning(effort=None, generate_summary=None, summary=None)
- service_tier: default
- status: completed
- text: ResponseTextConfig(format=ResponseFormatText(type=‘text’))
- truncation: disabled
- usage: ResponseUsage(input_tokens=275, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=10, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=285)
- user: None
- max_tool_calls: None
- store: True
- top_logprobs: 0
Third Party Providers
Azure OpenAI Service
Example Azure usage:
= AzureOpenAI(
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"),
azure_endpoint =os.getenv("AZURE_OPENAI_API_KEY"),
api_key="2024-08-01-preview"
api_version
)
= Client(models_azure[0], azure_endpoint)
client = Chat(cli=client)
chat "Hi.") chat(