langchain
langchain copied to clipboard
Add tool_choice for OpenAI and Anthropic
This PR adds tool_choice
option to both OpenAI and Anthropic models.
For both models, I've created a tool_choice
attribute inside the model structs that embeds a ToolChoice
struct with attributes that are specific to each model.
For ChatOpenAI
:
defmodule ToolChoice do
use Ecto.Schema
defmodule Function do
use Ecto.Schema
@primary_key false
embedded_schema do
field :name, :string
end
@doc """
Setup a ChatOpenAI Function with name
"""
@spec changeset(%Function{}, map()) :: Ecto.Changeset.t()
def changeset(%Function{}=function, %{}=attrs) do
function
|> cast(attrs, [:name])
|> validate_required([:name])
end
end
@primary_key false
embedded_schema do
field :type, Ecto.Enum, values: [:function, :required, :none, :auto]
embeds_one :function, Function
end
@doc """
Setup a ChatOpenAI ToolChoice configuration
"""
@spec changeset(%ToolChoice{}, map()) :: Ecto.Changeset.t()
def changeset(%ToolChoice{}=tool_choice, %{}=attrs) do
tool_choice
|> cast(attrs, [:type])
|> validate_required([:type])
|> validate_type()
end
defp validate_type(changeset) do
case get_change(changeset, :type) do
:function -> cast_embed(changeset, :function, required: true, with: &Function.changeset/2)
_ -> changeset
end
end
end
For ChatAnthropic
:
defmodule ToolChoice do
use Ecto.Schema
@primary_key false
embedded_schema do
field :type, Ecto.Enum, values: [:tool, :auto, :any]
field :name, :string
end
@doc """
Setup a ChatAnthropic ToolChoice configuration
"""
@spec changeset(%ToolChoice{}, map()) :: Ecto.Changeset.t()
def changeset(%ToolChoice{}=tool_choice, %{}=attrs) do
tool_choice
|> cast(attrs, [:type, :name])
|> validate_required([:type])
|> validate_type()
end
defp validate_type(changeset) do
case get_change(changeset, :type) do
:tool -> validate_required(changeset, [:name])
_ -> changeset
end
end
end