Packages

fnord

0.4.21

AI code archaeology

Current section

Files

Jump to
fnord lib ai agent defrag.ex
Raw

lib/ai/agent/defrag.ex

defmodule AI.Agent.Defrag do
defstruct [
:ai,
:messages
]
@model "gpt-4o"
@prompt """
You are the Defrag Agent. You will be handed a JSON-formatted transcript of a
conversation. Combine all of the tool_call request messages, tool_call
response messages, as well as your own earlier summaries (identified by the
presence of `# CONSOLIDATED FINDINGS` in the message contents) into a single
message that efficiently consolidates all of the facts and decisions made
thus far.
- DO NOT modify the user's messages
- DO retain files identified and information discovered about each of them
- DO include discoveries about which files were unrelated
- DO include all facts discovered within the conversation
- DO include all of the information you have previously summarized
(identified by the presence of `# CONSOLIDATED FINDINGS` in the message
contents)
Respond with your markdown-formatted message, prefixed with `# CONSOLIDATED FINDINGS`.
"""
def msgs_to_defrag(agent) do
agent.messages
|> Enum.count(fn
%{role: "assistant", tool_calls: _} ->
false
%{role: "tool"} ->
false
%{role: "assistant", content: content} ->
String.match?(content, ~r/^# CONSOLIDATED FINDINGS/)
_ ->
true
end)
end
def summarize_findings(agent) do
defrag = %__MODULE__{ai: agent.ai, messages: agent.messages}
with {:ok, msg_json} <- Jason.encode(defrag.messages) do
OpenaiEx.Chat.Completions.create(
defrag.ai.client,
OpenaiEx.Chat.Completions.new(
model: @model,
messages: [
OpenaiEx.ChatMessage.system(@prompt),
OpenaiEx.ChatMessage.user(msg_json)
]
)
)
|> case do
{:ok, %{"choices" => [%{"message" => %{"content" => summary}}]}} ->
{:ok, defragmented_msg_list(defrag, summary)}
{:error, reason} ->
{:error, reason}
response ->
{:error, "unexpected response: #{inspect(response)}"}
end
end
end
defp defragmented_msg_list(defrag, summary) do
messages =
defrag.messages
|> Enum.filter(fn
%{role: "assistant", tool_calls: _} ->
false
%{role: "tool"} ->
false
%{role: "assistant", content: content} ->
String.match?(content, ~r/^# CONSOLIDATED FINDINGS/)
_ ->
true
end)
messages ++ [AI.Util.assistant_msg(summary)]
end
end