Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Agent Prototyping

notebooks/agent-prototyping.livemd

Agent Prototyping

Mix.install([
  {:magus, path: "#{__DIR__}/.."},
  {:kino, "~> 0.12.0"}
  # {:ex_dot, "~> 0.1.0"}
])

Application.put_env(:magus, :model_provider, "openai")
Application.put_env(:magus, :openai_key, System.fetch_env!("LB_OPENAI_KEY"))

New Agent

alias LangChain.Message
alias Magus.GraphAgent
alias Magus.AgentChain

write_story_node = fn chain, state ->
  prompt = "Write a brief story about \"#{state.topic}\" that features three different characters"

  {:ok, content, _response} =
    chain
    |> AgentChain.add_message(Message.new_user!(prompt))
    |> AgentChain.run()

  %{state | story: content}
end

story_schema = %{
  "type" => "object",
  "properties" => %{
    "summary" => %{
      "type" => "string",
      "description" => "Brief summary of the story."
    },
    "characters" => %{
      "type" => "array",
      "description" => "List of characters in the story",
      "items" => %{
        "type" => "string"
      }
    }
  }
}

structure_story_node = fn chain, state ->
  prompt = """
  You are a helpful assistant responsible for summarizing stories and identifying story characters.
  The following is a short story about "#{state.topic}":

  #{state.story}
  """

  {:ok, content, _response} =
    chain
    |> AgentChain.add_message(Message.new_user!(prompt))
    |> AgentChain.ask_for_json_response(story_schema)
    |> AgentChain.run()

  %{state | structured_story: content}
end

agent =
  %GraphAgent{
    name: "Poff's Great New Agent",
    initial_state: %{}
  }
  |> GraphAgent.add_node(:write_story, write_story_node)
  |> GraphAgent.add_node(:structure_story, structure_story_node)
  |> GraphAgent.set_entry_point(:write_story)
  |> GraphAgent.add_edge(:write_story, :structure_story)
  |> GraphAgent.add_edge(:structure_story, :end)
# This only works if the ex_dot dependency is available (see the Notebook dependencies section)

agent.graph
|> Graph.Serializers.DOT.serialize()
|> case do
  {:ok, dot_graph} -> dot_graph
end
|> Dot.to_svg()
|> Kino.Image.new(:svg)
import Kino.Shorts
topic = read_text("New story topic: ")

if topic == "" do
  Kino.interrupt!(:error, "You must enter a topic")
end

initial_state = %{topic: topic, story: nil, structured_story: nil}
Magus.AgentExecutorLite.run(%{agent | initial_state: initial_state}) |> Kino.Tree.new()