defmodule GenAI.Tool do
@moduledoc """
Represents a function that can be called by the model.
"""
@vsn 1.0
require GenAI.Records.Directive
import GenAI.Records.Directive
use GenAI.Graph.NodeBehaviour
@derive GenAI.Graph.NodeProtocol
# @derive GenAI.Thread.SessionProtocol
defnodestruct(parameters: nil)
defnodetype(parameters: term)
def apply_node_directives(this, graph_link, graph_container, session, context, options)
def apply_node_directives(this, _, _, session, context, options) do
entry = tool_entry(tool: this.name)
directive = GenAI.Session.State.Directive.static(entry, this, {:node, this.id})
GenAI.Thread.Session.append_directive(session, directive, context, options)
end
@doc """
Extract function from json.
"""
def from_json(json_string) when is_bitstring(json_string) do
with {:ok, json} <- Jason.decode(json_string) do
do_from_json(json)
end
end
@doc """
Extract function from yaml.
"""
def from_yaml(yaml_string) when is_bitstring(yaml_string) do
with {:ok, json} <- YamlElixir.read_from_string(yaml_string) do
do_from_json(json)
end
end
defp do_from_json(%{"type" => "function", "function" => json}) do
do_from_json(json)
end
defp do_from_json(%{"name" => _} = json) do
# parameters is json a standard object json schema entry so use it to build a map of parameters one implemented.
parameters =
with {:ok, x} <- json["parameters"] && GenAI.Tool.Schema.Type.from_json(json["parameters"]) do
x
end
{:ok,
%GenAI.Tool{
name: json["name"],
description: json["description"],
parameters: parameters
}}
end
def inspect_custom_details(subject, opts) do
["parameters:", Inspect.Algebra.to_doc(subject.parameters, opts), ", "]
end
defimpl GenAI.ToolProtocol do
def name(subject), do: {:ok, subject.name}
end
end