Skip to content
This repository was archived by the owner on Mar 9, 2026. It is now read-only.

Commit 667240a

Browse files
committed
Enhance AI sidekick with file context support 📁
This commit introduces the ability for the AI sidekick to use the contents of specified files as context during its session. This is achieved by adding a new function `generate_files_context` which reads the contents of the provided files and formats them into a string that can be used as context. The `sidekick` function in `cli.py` has been updated to accept a list of files as arguments, generate the file context, and pass it along with the user's request to the `generate_sidekick_prompt` function. The token size calculations and model selection have also been adjusted to account for the additional context. The `generate_sidekick_prompt` function now accepts an additional `files` parameter and includes the generated file context in the prompt template. The prompt template itself has been updated to include a placeholder for the file context. The import statements in `cli.py` and `__init__.py` have been updated to include the new `generate_files_context` function. This enhancement provides the AI sidekick with more context, potentially improving its ability to assist the user.
1 parent da39811 commit 667240a

3 files changed

Lines changed: 50 additions & 25 deletions

File tree

aicodebot/cli.py

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from aicodebot import version as aicodebot_version
22
from aicodebot.helpers import exec_and_get_output, get_token_length, git_diff_context
3-
from aicodebot.prompts import generate_sidekick_prompt
3+
from aicodebot.prompts import generate_files_context, generate_sidekick_prompt
44
from dotenv import load_dotenv
55
from langchain.callbacks.base import BaseCallbackHandler
66
from langchain.chains import LLMChain
@@ -242,7 +242,7 @@ def review(commit, verbose):
242242
prompt = load_prompt(Path(__file__).parent / "prompts" / "review.yaml")
243243

244244
# Check the size of the diff context and adjust accordingly
245-
response_token_size = DEFAULT_MAX_TOKENS / 2
245+
response_token_size = DEFAULT_MAX_TOKENS
246246
request_token_size = get_token_length(diff_context) + get_token_length(prompt.template)
247247
model = get_llm_model(request_token_size)
248248
if verbose:
@@ -267,15 +267,29 @@ def review(commit, verbose):
267267
@cli.command
268268
@click.option("--request", "-r", help="What to ask your sidekick to do")
269269
@click.option("-v", "--verbose", count=True)
270-
def sidekick(request, verbose):
271-
"""EXPERIMENTAL: Coding help from your AI sidekick"""
270+
@click.argument("files", nargs=-1)
271+
def sidekick(request, verbose, files):
272+
"""
273+
EXPERIMENTAL: Coding help from your AI sidekick\n
274+
FILES: List of files to be used as context for the session
275+
"""
276+
272277
console.print("This is an experimental feature. Play with it, but don't count on it.", style=warning_style)
273278

274279
setup_environment()
275280

276-
# Generate the prompt with the appropriate context
277-
prompt = generate_sidekick_prompt(request)
278-
model = get_llm_model(get_token_length(prompt.template))
281+
# Pull in context. Right now it's just the contents of files that we passed in.
282+
# Soon, we could add vector embeddings of:
283+
# imported code / modules / libraries
284+
# Style guides/reference code
285+
# git history
286+
context = generate_files_context(files)
287+
288+
# Generate the prompt and set up the model
289+
prompt = generate_sidekick_prompt(request, files)
290+
model = get_llm_model(get_token_length(prompt.template) + get_token_length(context))
291+
if verbose:
292+
console.print(f"Context token size: {get_token_length(context)}, using model: {model}")
279293

280294
llm = ChatOpenAI(
281295
model=model,
@@ -286,32 +300,30 @@ def sidekick(request, verbose):
286300
)
287301

288302
# Set up the chain
289-
chain = LLMChain(
290-
llm=llm,
291-
prompt=prompt,
292-
memory=ConversationTokenBufferMemory(llm=llm, max_token_limit=DEFAULT_MAX_TOKENS),
293-
verbose=verbose,
303+
memory = ConversationTokenBufferMemory(
304+
memory_key="chat_history", input_key="task", llm=llm, max_token_limit=DEFAULT_MAX_TOKENS
294305
)
306+
chain = LLMChain(llm=llm, prompt=prompt, memory=memory, verbose=verbose)
295307

296308
while True: # continuous loop for multiple questions
297309
if request:
298-
user_input = request
310+
human_input = request
299311
request = None # clear the command line request once we've handled it
300312
else:
301-
user_input = click.prompt(
313+
human_input = click.prompt(
302314
"Enter a question OR (q) quit, OR (e) edit for entering a question in your editor\n>>>",
303315
prompt_suffix="",
304316
)
305-
if user_input.lower() == "q":
317+
if human_input.lower() == "q":
306318
break
307-
elif user_input.lower() == "e":
308-
user_input = click.edit()
319+
elif human_input.lower() == "e":
320+
human_input = click.edit()
309321

310322
with Live(Markdown(""), auto_refresh=True) as live:
311323
callback = RichLiveCallbackHandler(live)
312324
callback.buffer = []
313325
llm.callbacks = [callback]
314-
chain.run(user_input)
326+
chain.run({"task": human_input, "context": context})
315327

316328

317329
# ---------------------------------------------------------------------------- #

aicodebot/prompts/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
from .sidekick import generate_sidekick_prompt
1+
from .sidekick import generate_files_context, generate_sidekick_prompt
22

3-
__all__ = ["generate_sidekick_prompt"]
3+
__all__ = ["generate_sidekick_prompt", "generate_files_context"]

aicodebot/prompts/sidekick.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
11
from langchain import PromptTemplate
2+
from pathlib import Path
23

3-
SIDEKICK_PREFIX = """You are a pair programming assistant named AICodeBot, acting as a sidekick to a human developer.
4+
SIDEKICK_TEMPLATE = """You are a pair programming assistant named AICodeBot, acting as a sidekick to a human developer.
45
If you aren't sure what to do, you can ask the human for more clarification.
56
6-
Relevant history:
7-
{history}
8-
End History
7+
Relevant chat history:
8+
{chat_history}
9+
End chat history
10+
{context}
911
1012
Conversation with the human developer:
1113
Human: {task}
1214
AICodeBot:
1315
"""
1416

1517

18+
def generate_files_context(files):
19+
"""Generate the files context for the sidekick prompt."""
20+
files_context = "Here are the relevant files we are working with in this session:\n"
21+
for file_name in files:
22+
contents = Path(file_name).read_text()
23+
files_context += f"--- START OF FILE: {file_name} ---\n"
24+
files_context += contents
25+
files_context += f"\n--- END OF FILE: {file_name} ---\n\n"
26+
return files_context
27+
28+
1629
def generate_sidekick_prompt(task, files=None):
1730
"""Generates a prompt for the sidekick workflow."""
18-
return PromptTemplate(template=SIDEKICK_PREFIX, input_variables=["history", "task"])
31+
return PromptTemplate(template=SIDEKICK_TEMPLATE, input_variables=["chat_history", "task", "context"])

0 commit comments

Comments
 (0)