.env
file with the name WRITER_API_KEY
.def calculate_mean(numbers: list) -> float:
return sum(numbers) / len(numbers)
tools
array to pass to the model.
The tools
array describes your functions as tools available to the model. You describe tools in the form of a JSON schema. Each tool should include a type
of function
and a function
object that includes a name
, description
, and a dictionary of parameters
.
tools
array contains an object with the following parameters:
Parameter | Type | Description |
---|---|---|
type | string | The type of tool, which is function for a custom function |
function | object | An object containing the tool’s description and parameter definitions |
function.name | string | The name of the tool |
function.description | string | A description of what the tool does and when the model should use it |
function.parameters | object | An object containing the tool’s input parameters |
function.parameters.type | string | The type of the parameter, which is object for a JSON schema |
function.parameters.properties | object | An object containing the tool’s parameters in the form of a JSON schema. See below for more details. |
function.parameters.required | array | An array of the tool’s required parameters |
function.parameters.properties
object contains the tool’s parameter definitions as a JSON schema. The object’s keys should be the names of the parameters, and the values should be objects containing the parameter’s type and description.
When the model decides you should use the tool to answer the user’s question, it returns the parameters that you should use when calling the function you’ve defined.
tools
array for the calculate_mean
function:
tools = [
{
"type": "function",
"function": {
"name": "calculate_mean",
"description": "A function that calculates the mean (average) of a list of numbers. Any user request asking for the mean of a list of numbers should use this tool.",
"parameters": {
"type": "object",
"properties": {
"numbers": {
"type": "array",
"items": {"type": "number"},
"description": "List of numbers"
}
},
"required": ["numbers"]
}
}
}
]
function.description
parameter:“A function that calculates the mean of a list of numbers. Any user request asking for the mean of a list of numbers should use this tool.”
tool_choice parameter
that controls how the model decides when to use the tools you’ve defined.
Value | Description |
---|---|
auto | The model decides which tools to use, if any. |
none | The model does not use tools and only returns a generated response. |
required | The model must use at least one of the tools you’ve defined. |
calculate_mean
tool, you can set tool_choice
to {"type": "function", "function": {"name": "calculate_mean"}}
.
In this example, tool_choice
is auto
, which means the model decides which tools to use, if any, based on the message and tool descriptions.
import json
from writerai import Writer
# Initialize the Writer client. If you don't pass the `apiKey` parameter,
# the client looks for the `WRITER_API_KEY` environment variable.
client = Writer()
messages = [{"role": "user", "content": "what is the mean of [1,3,5,7,9]?"}]
response = client.chat.chat(
model="palmyra-x5",
messages=messages,
tools=tools,
tool_choice="auto"
)
streaming_content = ""
function_calls = []
for chunk in response:
choice = chunk.choices[0]
if choice.delta:
# Collect tool calls as they stream in
if choice.delta.tool_calls:
for tool_call in choice.delta.tool_calls:
if tool_call.id:
# Start a new function call
function_calls.append({
"name": "",
"arguments": "",
"call_id": tool_call.id
})
if tool_call.function:
# Append to the most recent function call
if function_calls:
function_calls[-1]["name"] += tool_call.function.name or ""
function_calls[-1]["arguments"] += tool_call.function.arguments or ""
# Collect regular content (for cases where no tools are called)
elif choice.delta.content:
streaming_content += choice.delta.content
finish_reason
to determine if tools were called, then reconstruct and append the assistant’s response to the conversation history.# Inside the streaming loop, check for finish_reason
if choice.finish_reason:
if choice.finish_reason == "stop":
# No tools were called, just regular response
messages.append({"role": "assistant", "content": streaming_content})
break
elif choice.finish_reason == "tool_calls":
# Reconstruct and append assistant message with tool calls
tool_calls_for_message = []
for func_call in function_calls:
tool_calls_for_message.append({
"id": func_call["call_id"],
"type": "function",
"function": {
"name": func_call["name"],
"arguments": func_call["arguments"]
}
})
assistant_message = {
"role": "assistant",
"content": None,
"tool_calls": tool_calls_for_message
}
messages.append(assistant_message)
function_calls
list and append the results to the messages array.# Inside the tool_calls finish_reason block
for function_call in function_calls:
function_name = function_call["name"]
if function_name == "calculate_mean":
try:
arguments_dict = json.loads(function_call["arguments"])
function_response = calculate_mean(arguments_dict["numbers"])
# Append tool result to conversation history
messages.append({
"role": "tool",
"content": str(function_response),
"tool_call_id": function_call["call_id"],
"name": function_name,
})
except Exception as e:
# Handle errors gracefully
messages.append({
"role": "tool",
"content": f"Error: {str(e)}",
"tool_call_id": function_call["call_id"],
"name": function_name,
})
# Inside the tool_calls finish_reason block, after processing all functions
final_response = client.chat.chat(
model="palmyra-x5",
messages=messages,
stream=True
)
final_content = ""
for chunk in final_response:
choice = chunk.choices[0]
if choice.delta and choice.delta.content:
final_content += choice.delta.content
# Append final response to conversation history
messages.append({
"role": "assistant",
"content": final_content
})
import json
from writerai import Writer
# Initialize the Writer client. If you don't pass the `apiKey` parameter,
# the client looks for the `WRITER_API_KEY` environment variable.
client = Writer()
def calculate_mean(numbers: list) -> float:
return sum(numbers) / len(numbers)
tools = [
{
"type": "function",
"function": {
"name": "calculate_mean",
"description": "Calculate the mean (average) of a list of numbers.",
"parameters": {
"type": "object",
"properties": {
"numbers": {
"type": "array",
"items": {"type": "number"},
"description": "List of numbers"
}
},
"required": ["numbers"]
}
}
}
]
messages = [{"role": "user", "content": "what is the mean of [1,3,5,7,9]?"}]
# Step 1: Initial request with tools
response = client.chat.chat(
model="palmyra-x5",
messages=messages,
tools=tools,
tool_choice="auto",
stream=True
)
# Step 2: Process streaming response to collect tool calls
streaming_content = ""
function_calls = []
for chunk in response:
choice = chunk.choices[0]
if choice.delta:
# Collect tool calls as they stream in
if choice.delta.tool_calls:
for tool_call in choice.delta.tool_calls:
if tool_call.id:
# Start a new function call
function_calls.append({
"name": "",
"arguments": "",
"call_id": tool_call.id
})
if tool_call.function:
# Append to the most recent function call
if function_calls:
function_calls[-1]["name"] += tool_call.function.name or ""
function_calls[-1]["arguments"] += tool_call.function.arguments or ""
# Collect regular content (for cases where no tools are called)
elif choice.delta.content:
streaming_content += choice.delta.content
# Check if streaming is complete
if choice.finish_reason:
if choice.finish_reason == "stop":
# No tools were called, just regular response
print(f"Response: {streaming_content}")
messages.append({"role": "assistant", "content": streaming_content})
break
elif choice.finish_reason == "tool_calls":
# Step 3: Reconstruct and append assistant message with tool calls
tool_calls_for_message = []
for func_call in function_calls:
tool_calls_for_message.append({
"id": func_call["call_id"],
"type": "function",
"function": {
"name": func_call["name"],
"arguments": func_call["arguments"]
}
})
assistant_message = {
"role": "assistant",
"content": None,
"tool_calls": tool_calls_for_message
}
messages.append(assistant_message) # Append assistant response
# Step 4: Execute each function and add results to messages
for function_call in function_calls:
function_name = function_call["name"]
if function_name == "calculate_mean":
try:
arguments_dict = json.loads(function_call["arguments"])
function_response = calculate_mean(arguments_dict["numbers"])
# Add tool response to messages
messages.append({
"role": "tool",
"content": str(function_response),
"tool_call_id": function_call["call_id"],
"name": function_name,
})
except Exception as e:
# Handle errors gracefully
messages.append({
"role": "tool",
"content": f"Error: {str(e)}",
"tool_call_id": function_call["call_id"],
"name": function_name,
})
# Step 5: Get the final response from the model
final_response = client.chat.chat(
model="palmyra-x5",
messages=messages,
stream=True
)
final_content = ""
for chunk in final_response:
choice = chunk.choices[0]
if choice.delta and choice.delta.content:
final_content += choice.delta.content
print(choice.delta.content, end="", flush=True)
# Step 6: Add final response to message history
messages.append({
"role": "assistant",
"content": final_content
})
break
import requests
def get_word_pronunciation(word):
url = f"https://api.dictionaryapi.dev/api/v2/entries/en/{word}"
response = requests.get(url)
if response.status_code == 200:
return json.dumps(response.json()[0]['phonetics'])
else:
return f"Failed to retrieve word pronunciation. Status code: {response.status_code}"
tools = [
{
"type": "function",
"function": {
"name": "get_word_pronunciation",
"description": "A function that will return JSON containing the phonetic pronunciation of an English word",
"parameters": {
"type": "object",
"properties": {
"word": {
"type": "string",
"description": "The word to get the phonetic pronunciation for",
}
},
"required": ["word"],
},
},
}
]
chat.chat
method with the tools
parameter set to the tools
array and tool_choice
set to auto
.
from writerai import Writer
# Initialize the Writer client. If you don't pass the `apiKey` parameter,
# the client looks for the `WRITER_API_KEY` environment variable.
client = Writer()
messages = [{"role": "user", "content": "what is the phonetic pronunciation of the word 'epitome' in English?"}]
response = client.chat.chat(
model="palmyra-x5",
messages=messages,
tools=tools,
tool_choice="auto",
stream=False
)
tool_calls
array to check for the invocation of the tool. Then, call the tool’s function with the arguments the model provided.
response_message = response.choices[0].message
messages.append(response_message)
tool_calls = response_message.tool_calls
if tool_calls:
tool_call = tool_calls[0]
tool_call_id = tool_call.id
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
if function_name == "get_word_pronunciation":
function_response = get_word_pronunciation(function_args["word"])
messages.append({
"role": "tool",
"tool_call_id": tool_call_id,
"name": function_name,
"content": function_response,
})
final_response = client.chat.chat(
model="palmyra-x5",
messages=messages,
stream=False
)
final_content = final_response.choices[0].message.content
# Append final response to conversation history
messages.append({
"role": "assistant",
"content": final_content
})
print(f"Final response: {final_content}")
# Final response: The phonetic pronunciation of the word "epitome" in English is /əˈpɪt.ə.mi/...
import requests
import json
from writerai import Writer
# Initialize the Writer client. If you don't pass the `apiKey` parameter,
# the client looks for the `WRITER_API_KEY` environment variable.
client = Writer()
def get_word_pronunciation(word):
url = f"https://api.dictionaryapi.dev/api/v2/entries/en/{word}"
try:
response = requests.get(url)
if response.status_code == 200:
return json.dumps(response.json()[0]['phonetics'])
else:
return f"Failed to retrieve word pronunciation. Status code: {response.status_code}"
except Exception as e:
return f"Error fetching word pronunciation: {str(e)}"
tools = [
{
"type": "function",
"function": {
"name": "get_word_pronunciation",
"description": "A function that will return JSON containing the phonetic pronunciation of an English word",
"parameters": {
"type": "object",
"properties": {
"word": {
"type": "string",
"description": "The word to get the phonetic pronunciation for",
}
},
"required": ["word"],
},
},
}
]
messages = [{"role": "user", "content": "what is the phonetic pronunciation of the word 'epitome' in English?"}]
# Step 1: Initial request
response = client.chat.chat(
model="palmyra-x5",
messages=messages,
tools=tools,
tool_choice="auto",
stream=False
)
# Step 2: Append assistant response
response_message = response.choices[0].message
messages.append(response_message)
tool_calls = response_message.tool_calls
# Step 3: Process tool calls
if tool_calls:
for tool_call in tool_calls:
tool_call_id = tool_call.id
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
if function_name == "get_word_pronunciation":
function_response = get_word_pronunciation(function_args["word"])
# Append tool result
messages.append({
"role": "tool",
"tool_call_id": tool_call_id,
"name": function_name,
"content": function_response,
})
# Step 4: Get final response
final_response = client.chat.chat(
model="palmyra-x5",
messages=messages,
stream=False
)
final_content = final_response.choices[0].message.content
# Step 5: Append final response
messages.append({
"role": "assistant",
"content": final_content
})
print(f"Final response: {final_content}")
# The conversation history is now complete and ready for additional turns
Was this page helpful?