A model you can run for free
A browser cannot call OpenAI. So rather than stop here, you are going to write a model.
The SDK talks to a model through exactly one method, get_response. Anything that provides it is a model as far as the SDK is concerned. That is the whole opening.
What a model has to hand back
Two shapes, and no more. Either words, or a request for a tool. These two helpers build them.
def say(text):
"""Plain words, in the shape the SDK expects back."""
return ResponseOutputMessage(
id="msg_1", role="assistant", status="completed", type="message",
content=[ResponseOutputText(text=text, type="output_text", annotations=[])],
)def call(tool_name, **args):
"""A request for a tool, instead of an answer."""
return ResponseFunctionToolCall(
id="fc_1", call_id="call_1", name=tool_name,
arguments=json.dumps(args), type="function_call",
)Those are verbose because they are the real types the SDK uses, not a simplification. Write them once and you never look at them again.
The model itself
class PretendModel(Model):
async def get_response(self, system_instructions, input, model_settings, tools,
output_schema, handoffs, tracing, **kwargs):
asked = input if isinstance(input, str) else json.dumps(input)
used_a_tool = "call_1" in asked
if tools and not used_a_tool and "A17" in asked:
item = call(tools[0].name, order_id="A17")
else:
item = say("Order A17 shipped on 3 March.")
return ModelResponse(output=[item], usage=Usage(), response_id=None)Two rules. If there are tools, nothing has been called yet, and the question mentions an order id, ask for the tool. Otherwise answer with words.
A real model reads the words and predicts. This one reads the words and follows two lines you can point at. Everything else about it, the types it returns and the method it provides, is exactly what a real one does.
Run it and see both shapes
The bottom of the file builds one of each and prints them, so you can see what the SDK is going to be handed.
words = say("Order A17 shipped on 3 March.")
request = call("lookup_order", order_id="A17")
print("answering with words:", words.content[0].text)
print("asking for a tool: ", request.name, request.arguments)- Change the text in
sayand run it again. - Add a third rule that answers a greeting differently.
- Print the whole
wordsobject and look at the fields a real model fills in.
Slow is fine. Stopping is the only problem.