include environment information in prompts

This commit is contained in:
AI Christianson 2025-03-08 12:01:40 -05:00
parent f1a33fc1c0
commit c323098aec
8 changed files with 176 additions and 91 deletions

View File

@ -63,6 +63,8 @@ from ra_aid.database.repositories.config_repository import (
ConfigRepositoryManager,
get_config_repository
)
from ra_aid.env_inv import EnvDiscovery
from ra_aid.env_inv_context import EnvInvManager, get_env_inv
from ra_aid.model_formatters import format_key_facts_dict
from ra_aid.model_formatters.key_snippets_formatter import format_key_snippets_dict
from ra_aid.console.output import cpm
@ -506,13 +508,19 @@ def main():
config = {}
# Initialize repositories with database connection
# Create environment inventory data
env_discovery = EnvDiscovery()
env_discovery.discover()
env_data = env_discovery.format_markdown()
with KeyFactRepositoryManager(db) as key_fact_repo, \
KeySnippetRepositoryManager(db) as key_snippet_repo, \
HumanInputRepositoryManager(db) as human_input_repo, \
ResearchNoteRepositoryManager(db) as research_note_repo, \
RelatedFilesRepositoryManager() as related_files_repo, \
WorkLogRepositoryManager() as work_log_repo, \
ConfigRepositoryManager(config) as config_repo:
ConfigRepositoryManager(config) as config_repo, \
EnvInvManager(env_data) as env_inv:
# This initializes all repositories and makes them available via their respective get methods
logger.debug("Initialized KeyFactRepository")
logger.debug("Initialized KeySnippetRepository")
@ -521,6 +529,7 @@ def main():
logger.debug("Initialized RelatedFilesRepository")
logger.debug("Initialized WorkLogRepository")
logger.debug("Initialized ConfigRepository")
logger.debug("Initialized Environment Inventory")
# Check dependencies before proceeding
check_dependencies()
@ -671,6 +680,7 @@ def main():
key_facts=format_key_facts_dict(get_key_fact_repository().get_facts_dict()),
key_snippets=format_key_snippets_dict(get_key_snippet_repository().get_snippets_dict()),
project_info=formatted_project_info,
env_inv=get_env_inv(),
),
config,
)

View File

@ -98,6 +98,7 @@ from ra_aid.tools.memory import (
log_work_event,
)
from ra_aid.database.repositories.config_repository import get_config_repository
from ra_aid.env_inv_context import get_env_inv
console = Console()
@ -422,6 +423,8 @@ def run_research_agent(
logger.warning(f"Failed to get project info: {e}")
formatted_project_info = ""
# Get environment inventory information
prompt = (RESEARCH_ONLY_PROMPT if research_only else RESEARCH_PROMPT).format(
current_date=current_date,
working_directory=working_directory,
@ -440,6 +443,7 @@ def run_research_agent(
related_files=related_files,
project_info=formatted_project_info,
new_project_hints=NEW_PROJECT_HINTS if project_info.is_new else "",
env_inv=get_env_inv(),
)
config = get_config_repository().get_all() if not config else config
@ -562,6 +566,8 @@ def run_web_research_agent(
current_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
working_directory = os.getcwd()
# Get environment inventory information
prompt = WEB_RESEARCH_PROMPT.format(
current_date=current_date,
working_directory=working_directory,
@ -572,6 +578,7 @@ def run_web_research_agent(
work_log=get_work_log_repository().format_work_log(),
key_snippets=key_snippets,
related_files=related_files,
env_inv=get_env_inv(),
)
config = get_config_repository().get_all() if not config else config
@ -688,6 +695,8 @@ def run_planning_agent(
logger.error(f"Failed to access research note repository: {str(e)}")
formatted_research_notes = ""
# Get environment inventory information
planning_prompt = PLANNING_PROMPT.format(
current_date=current_date,
working_directory=working_directory,
@ -706,6 +715,7 @@ def run_planning_agent(
if config.get("research_only")
else " Only request implementation if the user explicitly asked for changes to be made."
),
env_inv=get_env_inv(),
)
config = get_config_repository().get_all() if not config else config
@ -808,6 +818,8 @@ def run_task_implementation_agent(
logger.error(f"Failed to access research note repository: {str(e)}")
formatted_research_notes = ""
# Get environment inventory information
prompt = IMPLEMENTATION_PROMPT.format(
current_date=current_date,
working_directory=working_directory,
@ -831,6 +843,7 @@ def run_task_implementation_agent(
if config.get("web_research_enabled")
else ""
),
env_inv=get_env_inv(),
)
config = get_config_repository().get_all() if not config else config
@ -991,78 +1004,6 @@ def _handle_fallback_response(
msg_list.extend(msg_list_response)
# def _run_agent_stream(agent: RAgents, msg_list: list[BaseMessage], config: dict):
# for chunk in agent.stream({"messages": msg_list}, config):
# logger.debug("Agent output: %s", chunk)
# check_interrupt()
# agent_type = get_agent_type(agent)
# print_agent_output(chunk, agent_type)
# if is_completed() or should_exit():
# reset_completion_flags()
# break
# def _run_agent_stream(agent: RAgents, msg_list: list[BaseMessage], config: dict):
# while True: ## WE NEED TO ONLY KEEP ITERATING IF IT IS AN INTERRUPT, NOT UNCONDITIONALLY
# stream = agent.stream({"messages": msg_list}, config)
# for chunk in stream:
# logger.debug("Agent output: %s", chunk)
# check_interrupt()
# agent_type = get_agent_type(agent)
# print_agent_output(chunk, agent_type)
# if is_completed() or should_exit():
# reset_completion_flags()
# return True
# print("HERE!")
# def _run_agent_stream(agent: RAgents, msg_list: list[BaseMessage], config: dict):
# while True:
# for chunk in agent.stream({"messages": msg_list}, config):
# print("Chunk received:", chunk)
# check_interrupt()
# agent_type = get_agent_type(agent)
# print_agent_output(chunk, agent_type)
# if is_completed() or should_exit():
# reset_completion_flags()
# return True
# print("HERE!")
# print("Config passed to _run_agent_stream:", config)
# print("Config keys:", list(config.keys()))
# # Ensure the configuration for state retrieval contains a 'configurable' key.
# state_config = config.copy()
# if "configurable" not in state_config:
# print("Key 'configurable' not found in config. Adding it as an empty dict.")
# state_config["configurable"] = {}
# print("Using state_config for agent.get_state():", state_config)
# try:
# state = agent.get_state(state_config)
# print("Agent state retrieved:", state)
# print("State type:", type(state))
# print("State attributes:", dir(state))
# except Exception as e:
# print("Error retrieving agent state with state_config", state_config, ":", e)
# raise
# # Since state.current is not available, we rely solely on state.next.
# try:
# next_node = state.next
# print("State next value:", next_node)
# except Exception as e:
# print("Error accessing state.next:", e)
# next_node = None
# # Resume execution if state.next is truthy (indicating further steps remain).
# if next_node:
# print("Resuming execution because state.next is nonempty:", next_node)
# agent.invoke(None, config)
# continue
# else:
# print("No further steps indicated; breaking out of loop.")
# break
# return True
def _run_agent_stream(agent: RAgents, msg_list: list[BaseMessage], config: dict):
"""
Streams agent output while handling completion and interruption.

92
ra_aid/env_inv_context.py Normal file
View File

@ -0,0 +1,92 @@
"""
Context management for environment inventory.
This module provides thread-safe access to environment inventory information
using context variables.
"""
import contextvars
from typing import Dict, Any, Optional, Type
# Create contextvar to hold the environment inventory
env_inv_var = contextvars.ContextVar("env_inv", default=None)
class EnvInvManager:
"""
Context manager for environment inventory.
This class provides a context manager interface for environment inventory,
using the contextvars approach for thread safety.
Example:
from ra_aid.env_inv import EnvDiscovery
# Get environment inventory
env_discovery = EnvDiscovery()
env_discovery.discover()
env_data = env_discovery.format_markdown()
# Set as current environment inventory
with EnvInvManager(env_data) as env_mgr:
# Environment inventory is now available through get_env_inv()
pass
"""
def __init__(self, env_data: Dict[str, Any]):
"""
Initialize the EnvInvManager.
Args:
env_data: Dictionary containing environment inventory data
"""
self.env_data = env_data
def __enter__(self) -> 'EnvInvManager':
"""
Set the environment inventory and return self.
Returns:
EnvInvManager: The initialized manager
"""
env_inv_var.set(self.env_data)
return self
def __exit__(
self,
exc_type: Optional[Type[BaseException]],
exc_val: Optional[BaseException],
exc_tb: Optional[object],
) -> None:
"""
Reset the environment inventory when exiting the context.
Args:
exc_type: The exception type if an exception was raised
exc_val: The exception value if an exception was raised
exc_tb: The traceback if an exception was raised
"""
# Reset the contextvar to None
env_inv_var.set(None)
# Don't suppress exceptions
return False
def get_env_inv() -> Dict[str, Any]:
"""
Get the current environment inventory.
Returns:
Dict[str, Any]: The current environment inventory
Raises:
RuntimeError: If no environment inventory has been initialized with EnvInvManager
"""
env_data = env_inv_var.get()
if env_data is None:
raise RuntimeError(
"No environment inventory available. "
"Make sure to initialize one with EnvInvManager first."
)
return env_data

View File

@ -23,6 +23,9 @@ Current Date: {current_date}
Project Info:
{project_info}
Environment Info:
{env_inv}
Agentic Chat Mode Instructions:
Overview:

View File

@ -29,6 +29,16 @@ Working Directory: {working_directory}
{research_notes}
</research notes>
<environment inventory>
{env_inv}
</environment inventory>
MAKE USE OF THE ENVIRONMENT INVENTRY TO GET YOUR WORK DONE AS EFFICIENTLY AND ACCURATELY AS POSSIBLE
E.G. IF WE ARE USING A LIBRARY AND IT IS FOUND IN ENV INVENTORY, ADD THE INCLUDE/LINKER FLAGS TO YOUR MAKEFILE/CMAKELISTS/COMPILATION COMMAND/ETC.
YOU MUST **EXPLICITLY** INCLUDE ANY PATHS FROM THE ABOVE INFO IF NEEDED. IT IS NOT AUTOMATIC.
Important Notes:
- Focus solely on the given task and implement it as described.
- Scale the complexity of your solution to the complexity of the request. For simple requests, keep it straightforward and minimal. For complex requests, maintain the previously planned depth.

View File

@ -11,30 +11,37 @@ from ra_aid.prompts.web_research_prompts import WEB_RESEARCH_PROMPT_SECTION_PLAN
PLANNING_PROMPT = """Current Date: {current_date}
Working Directory: {working_directory}
<base task>
{base_task}
<base task>
KEEP IT SIMPLE
Project Info:
<project info>
{project_info}
</project info>
Research Notes:
<notes>
<research notes>
{research_notes}
</notes>
</research notes>
Relevant Files:
{related_files}
Key Facts:
<key facts>
{key_facts}
</key facts>
Key Snippets:
<key snippets>
{key_snippets}
</key snippets>
<environment inventory>
{env_inv}
</environment inventory>
MAKE USE OF THE ENVIRONMENT INVENTRY TO GET YOUR WORK DONE AS EFFICIENTLY AND ACCURATELY AS POSSIBLE
E.G. IF WE ARE USING A LIBRARY AND IT IS FOUND IN ENV INVENTORY, ADD THE INCLUDE/LINKER FLAGS TO YOUR MAKEFILE/CMAKELISTS/COMPILATION COMMAND/
ETC.
YOU MUST **EXPLICITLY** INCLUDE ANY PATHS FROM THE ABOVE INFO IF NEEDED. IT IS NOT AUTOMATIC.
Work done so far:
<work log>
{work_log}
</work log>
@ -78,6 +85,12 @@ You have often been criticized for:
- Asking the user if they want to implement the plan (you are an *autonomous* agent, with no user interaction unless you use the ask_human tool explicitly).
- Not calling tools/functions properly, e.g. leaving off required arguments, calling a tool in a loop, calling tools inappropriately.
<base task>
{base_task}
<base task>
YOU MUST FOCUS ON THIS BASE TASK. IT TAKES PRECEDENT OVER EVERYTHING ELSE.
DO NOT WRITE ANY FILES YET. CODE WILL BE WRITTEN AS YOU CALL request_task_implementation.
DO NOT USE run_shell_command TO WRITE ANY FILE CONTENTS! USE request_task_implementation.

View File

@ -36,10 +36,22 @@ Work already done:
<project info>
{project_info}
</project info>
<caveat>You should make the most efficient use of this previous research possible, with the caveat that not all of it will be relevant to the current task you are assigned with. Use this previous research to save redudant research, and to inform what you are currently tasked with. Be as efficient as possible.</caveat>
</previous research>
Role
<environment inventory>
{env_inv}
</environment inventory>
MAKE USE OF THE ENVIRONMENT INVENTRY TO GET YOUR WORK DONE AS EFFICIENTLY AND ACCURATELY AS POSSIBLE
E.G. IF WE ARE USING A LIBRARY AND IT IS FOUND IN ENV INVENTORY, ADD THE INCLUDE/LINKER FLAGS TO YOUR MAKEFILE/CMAKELISTS/COMPILATION COMMAND/
ETC.
YOU MUST **EXPLICITLY** INCLUDE ANY PATHS FROM THE ABOVE INFO IF NEEDED. IT IS NOT AUTOMATIC.
Role:
You are an autonomous research agent focused solely on enumerating and describing the current codebase and its related files. You are not a planner, not an implementer, and not a chatbot for general problem solving. You will not propose solutions, improvements, or modifications.

View File

@ -100,5 +100,9 @@ Present well-structured responses that:
<related_files>
{related_files}
</related_files>
<environment inventory>
{env_inv}
</environment inventory>
</context>
"""