Packages
fnord
0.4.21
0.9.40
0.9.39
0.9.38
0.9.37
0.9.36
0.9.35
0.9.34
0.9.33
0.9.32
0.9.31
0.9.30
0.9.29
0.9.28
0.9.27
0.9.26
0.9.25
0.9.24
0.9.23
0.9.22
0.9.21
0.9.20
0.9.19
0.9.18
0.9.17
0.9.16
0.9.15
0.9.14
0.9.13
0.9.12
0.9.11
0.9.10
0.9.9
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.99
0.8.98
0.8.97
0.8.96
0.8.95
0.8.94
0.8.93
0.8.92
0.8.91
0.8.90
0.8.89
0.8.88
0.8.87
0.8.86
0.8.85
0.8.84
0.8.83
0.8.82
0.8.81
0.8.80
0.8.79
0.8.78
0.8.77
0.8.76
0.8.75
0.8.74
0.8.73
0.8.72
0.8.71
0.8.70
0.8.69
0.8.68
0.8.67
0.8.66
0.8.65
0.8.64
0.8.63
0.8.62
0.8.61
0.8.60
0.8.59
0.8.58
0.8.57
0.8.56
0.8.55
0.8.54
0.8.53
0.8.52
0.8.51
0.8.50
0.8.49
0.8.48
0.8.47
0.8.46
0.8.45
0.8.44
0.8.43
0.8.42
0.8.41
0.8.40
0.8.39
0.8.38
0.8.37
0.8.36
0.8.35
0.8.34
0.8.33
0.8.32
0.8.31
0.8.30
0.8.29
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.1
0.8.0
0.7.24
0.7.23
0.7.22
0.7.21
0.7.20
0.7.19
0.7.18
0.7.17
0.7.16
0.7.15
0.7.14
0.7.13
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.3
0.7.2
0.7.1
0.7.0
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.1
0.6.0
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.44
0.4.43
0.4.42
0.4.41
0.4.40
0.4.39
0.4.38
0.4.37
0.4.36
0.4.35
0.4.34
0.4.33
0.4.32
0.4.30
0.4.29
0.4.28
0.4.27
0.4.26
0.4.25
0.4.24
0.4.23
0.4.22
0.4.21
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
AI code archaeology
Current section
Files
Jump to
Current section
Files
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