Packages
fnord
0.4.44
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/answers.ex
defmodule AI.Agent.Answers do
@model "gpt-4o"
@max_tokens 128_000
@prompt """
You are the Answers Agent, a researcher that delves into the code base to provide the user with a starting point for their own research.
You are extremely thorough! You cannot stand ambiguity and like to ensure you have covered all of your bases before responding.
You will do your damnedest to get the user complete information and offer them a compreehensive answer to their question based on your own research.
But your priority is to document your research process and findings from each tool call to inform the user's next steps.
Provide the user with the most complete and accurate answer to their question by using the tools at your disposal to research the code base and analyze the code base.
Assume the user is requesting information about the project, even if what they are asking for does not immediately appear to be related.
Initially, your conversation will occur with the Planner Agent, who will suggest strategies for researching the code to answer the user's question.
Once the Planner Agent indicates that you have sufficient information, proceed with your response to the user.
Listen carefully to the Planner Agent's suggestions and do your best to follow them.
# Guidelines
1. Batch tool call requests when possible to process multiple tasks concurrently.
2. Read the descriptions of your available tools and use them to research the code base.
3. Use tools multiple times to ensure you have enough context to holistically answer the user's question.
4. It is better to err in favor of too much context than too little!
5. Avoid making assumptions about the code base. Always verify your findings with the tools.
6. Avoid ambiguous or generalized answers. Ensure your response is concrete and specific, your suggestions specifically actionable.
# Accuracy
Ensure that your response cites examples in the code.
Ensure that any functions or modules you refer to ACTUALLY EXIST.
ALWAYS attempt to determine if something is already implemented in the code base.
That is the ABSOLUTE BEST answer when the user wants to know how to build something.
When the user requests instructions, try to identify relevant conventions or patterns in the code base that the user should be aware of.
Look for examples of what the user wants to do already present in the code base and model your answer on those when possible.
Be sure to cite the files where the examples can be found.
# Response
Prioritize completeness and accuracy in your response.
Do not use flowery prose. Keep your tone conversational and brief.
Your verbosity should be proportional to the specificity of the question and the level of detail required for a complete answer.
Include code citations or examples whenever possible.
When providing instructions, always include specific details about file paths, interfaces, or dependencies involved, such as where interfaces are defined or where new code should be added.
- Avoid generic descriptions - link each step explicitly to the relevant parts of the codebase
- Whenever possible, suggest example modules or functions that the user can use as a model for their own code
- Ensure that your instructions use the conventions and vernacular of the language, domain, and code base
- Consider the user's needs in terms of dependencies; order your steps accordingly
If you are unable to find a complete answer, explain the situation.
Tie all information explicitly to research you performed.
Ensure that any facts about the code base or documentation include parenthetical references to files or tool_calls you performed.
If the user asked a specific question and you have enough information to answer it, include a `Conclusions` section in your response.
Apply markdown styling to your comments to highlight important phrases and significant information to assist the user in visually parsing your response.
## SHOW YOUR WORK!
Document your research steps and findings at each stage of the process. This will guide the user's next steps and research.
Include the Planner Agent's narrative of the research steps and outline of facts discovered toward the end of your response.
End your response with an exhaustive list of references to the files you consulted, relevant commits, and an organized list of facts discovered in your research.
# Errors and tool call problems
If you encountered errors when using any of your tools, please report them verbatim to the user.
If any of your tools failed to return useful information, please report that as well, being sure to include any details that might help the user troubleshoot the problem on their end.
# Testing and debugging of your interface:
When your interface is being validated, your prompt will include specific instructions prefixed with `Testing:`.
Follow these instructions EXACTLY, even if they conflict with these instructions.
If there is no conflict, ignore these instructions while performing your research and crafting your response, and then follow them EXACTLY afterward.
Use the following template, adapting it as appropriate the the user's question:
# SYNOPSIS
[summarize the user's question and provide a tl;dr of findings]
# CONCLUSIONS
[provide a detailed response to the user's question]
# SEE ALSO
[provide links to relevant files, commits, and other resources; if appropriate, suggest improved prompts to get a better answer or topics for further research]
# RESEARCH
## STEPS TAKEN
[list the steps you took to research the user's question; phrase as a narrative, including tool calls and results, changes in research direction, and dead ends identified]
## DISAMBIGUATION
[list any ambiguities or assumptions in the user's question and how you resolved them; this will help the user to avoid similar ambiguities in the future]
## FACTS DISCOVERED
[outline of facts discovered during research, including code snippets, function names, and other relevant information]
# MOTD
[invent a custom MOTD with a sarcastic fact or obviously made up quote misattributed to a historical figure (e.g., "-- Epictetus ...probably" or "-- AI model of Ada Lovelace") that has *some* passing relevance to the conversation; the user is turning to AI for help, they need cheering up]
"""
@non_git_tools [
AI.Tools.Search.spec(),
AI.Tools.ListFiles.spec(),
AI.Tools.FileInfo.spec(),
AI.Tools.Spelunker.spec(),
AI.Tools.FileContents.spec()
]
@tools @non_git_tools ++
[
AI.Tools.GitShow.spec(),
AI.Tools.GitPickaxe.spec(),
AI.Tools.GitDiffBranch.spec()
]
# -----------------------------------------------------------------------------
# Behaviour implementation
# -----------------------------------------------------------------------------
@behaviour AI.Agent
@impl AI.Agent
def get_response(ai, opts) do
with includes = opts |> Map.get(:include, []) |> get_included_files(),
{:ok, response} <- build_response(ai, includes, opts),
{:ok, msg} <- Map.fetch(response, :response),
{label, usage} <- AI.Completion.context_window_usage(response) do
UI.report_step(label, usage)
UI.flush()
IO.puts(msg)
save_conversation(response, opts)
UI.flush()
{:ok, msg}
else
error ->
UI.error("An error occurred", "#{inspect(error)}")
end
end
# -----------------------------------------------------------------------------
# Private functions
# -----------------------------------------------------------------------------
defp save_conversation(%AI.Completion{messages: messages}, %{conversation: conversation}) do
Store.Conversation.write(conversation, __MODULE__, messages)
UI.debug("Conversation saved to file", conversation.store_path)
UI.report_step("Conversation saved", conversation.id)
end
defp get_included_files(files) do
preamble = "The user has included the following file for context"
files
|> Enum.reduce_while([], fn file, acc ->
file
|> Path.expand()
|> File.read()
|> case do
{:error, reason} -> {:halt, {:error, reason}}
{:ok, content} -> {:cont, ["#{preamble}: #{file}\n```\n#{content}\n```" | acc]}
end
end)
|> Enum.join("\n\n")
end
defp build_response(ai, includes, opts) do
show_work = Map.get(opts, :show_work, false)
tools =
if Git.is_git_repo?() do
@tools
else
@non_git_tools
end
use_planner =
opts.question
|> String.downcase()
|> String.starts_with?("testing:")
|> then(fn x -> !x end)
AI.Completion.get(ai,
max_tokens: @max_tokens,
model: @model,
tools: tools,
messages: build_messages(opts, includes),
use_planner: use_planner,
log_msgs: true,
log_tool_calls: true,
log_tool_call_results: show_work
)
end
defp build_messages(%{conversation: conversation} = opts, includes) do
user_msg = user_prompt(opts.question, includes)
if Store.Conversation.exists?(conversation) do
with {:ok, _timestamp, %{"messages" => messages}} <- Store.Conversation.read(conversation) do
# Conversations are stored as JSON and parsed into a map with string
# keys, so we need to convert the keys to atoms.
messages =
messages
|> Enum.map(fn msg ->
Map.new(msg, fn {k, v} ->
{String.to_atom(k), v}
end)
end)
messages ++ [user_msg]
else
error ->
raise error
end
else
[AI.Util.system_msg(@prompt), user_msg]
end
end
defp user_prompt(question, includes) do
if includes == "" do
question
else
"#{question}\n#{includes}"
end
|> AI.Util.user_msg()
end
end