|
| 1 | +import os |
| 2 | +import subprocess |
| 3 | +import urllib |
| 4 | +from dataclasses import dataclass, field |
| 5 | + |
| 6 | +import networkx as nx |
| 7 | +import openai |
| 8 | +from loguru import logger |
| 9 | +from openai.types.beta.thread import Thread |
| 10 | +from openai.types.beta.threads.run import Run |
| 11 | + |
| 12 | +from sweepai.config.client import SweepConfig |
| 13 | +from sweepai.config.server import DEFAULT_GPT4_32K_MODEL |
| 14 | +from sweepai.core.chat import ChatGPT |
| 15 | +from sweepai.core.context_dfs import modify_context |
| 16 | +from sweepai.core.entities import Message, Snippet |
| 17 | +from sweepai.logn.cache import file_cache |
| 18 | +from sweepai.utils.chat_logger import ChatLogger, discord_log_error |
| 19 | +from sweepai.utils.code_tree import CodeTree |
| 20 | +from sweepai.utils.convert_openai_anthropic import MockFunctionCall |
| 21 | +from sweepai.utils.event_logger import posthog |
| 22 | +from sweepai.utils.github_utils import ClonedRepo |
| 23 | +from sweepai.utils.modify_utils import post_process_rg_output |
| 24 | +from sweepai.utils.openai_proxy import get_client |
| 25 | +from sweepai.utils.progress import AssistantConversation, TicketProgress |
| 26 | +from sweepai.utils.str_utils import FASTER_MODEL_MESSAGE |
| 27 | +from sweepai.utils.tree_utils import DirectoryTree |
| 28 | + |
| 29 | +state_eval_prompt = """You are helping contractors on a task that involves finding all of the relevant files needed to resolve an issue. This task does not involve writing or modifying code. The contractors' goal is to identify all necessary files, not actually implement the solution. Getting the files or adjacent code is sufficient, as long as all of the files have been found. |
| 30 | +Respond using the following structured format: |
| 31 | +<judgement_on_task> |
| 32 | +Provide clear criteria for evaluating the contractor's performance, such as: |
| 33 | +- Did they identify all relevant files needed to solve the issue? |
| 34 | +- Did they avoid including unnecessary or unrelated files? |
| 35 | +- Did they demonstrate an understanding of the codebase and problem? |
| 36 | +Examine each step and specifically call out anything done incorrectly with an explanation of the correct approach. |
| 37 | +</judgement_on_task> |
| 38 | +<overall_score> |
| 39 | +Provide a clear rubric for the 1-10 scale, such as: |
| 40 | +1-3: Failed to identify relevant files or understand the issue |
| 41 | +4-5: Identified some but not all required files |
| 42 | +6-7: Found most relevant files but included some unnecessary ones |
| 43 | +8-10: Successfully identified all and only the files needed to resolve the issue |
| 44 | +</overall_score> |
| 45 | +<message_to_contractor> |
| 46 | +Provide a single sentence of extremely specific and actionable feedback, addressed directly to the contractor: |
| 47 | +9-10: Great work identifying all the necessary files! |
| 48 | +4-8: Focus on [specific files] and avoid [unnecessary files] to improve. |
| 49 | +1-3: [Specific files] are not relevant. Look at [other files] instead. |
| 50 | +</message_to_contractor>""" |
| 51 | + |
| 52 | +def modify_context( |
| 53 | + chat_gpt: ChatGPT, |
| 54 | + user_prompt: str, |
| 55 | + repo_context_manager: RepoContextManager, |
| 56 | + ticket_progress: TicketProgress, |
| 57 | + model: str = "gpt-4-0125-preview", |
| 58 | +) -> bool | None: |
| 59 | + max_iterations = 40 |
| 60 | + repo_context_manager.current_top_snippets = [] |
| 61 | + bad_call_count = 0 |
| 62 | + # initial function call |
| 63 | + function_calls_string = chat_gpt.chat_anthropic( |
| 64 | + content=user_prompt, |
| 65 | + stop_sequences=["</function_call>"], |
| 66 | + model = CLAUDE_MODEL, |
| 67 | + message_key="user_request", |
| 68 | + ) |
| 69 | + for _ in range(max_iterations): |
| 70 | + function_outputs = [] |
| 71 | + function_calls = validate_and_parse_function_calls(function_calls_string, chat_gpt) |
| 72 | + for function_call in function_calls: |
| 73 | + function_output = handle_function_call(repo_context_manager, function_call) |
| 74 | + if PLAN_SUBMITTED_MESSAGE in function_output: |
| 75 | + return |
| 76 | + function_outputs.append(function_output) |
| 77 | + if len(function_calls) == 0: |
| 78 | + function_outputs.append("No function calls were made or your last function call was incorrectly formatted. The correct syntax for function calling is this:\n" |
| 79 | + + "<function_call>\n<tool_name>tool_name</tool_name>\n<parameters>\n<param_name>param_value</param_name>\n</parameters>\n</function_calls>") |
| 80 | + bad_call_count += 1 |
| 81 | + if bad_call_count >= 3: |
| 82 | + return |
| 83 | + function_calls_string = chat_gpt.chat_anthropic( |
| 84 | + content="\n\n".join(function_outputs), |
| 85 | + model=CLAUDE_MODEL, |
| 86 | + stop_sequences=["</function_call>"], |
| 87 | + ) |
| 88 | + # if there is a message with a non-null key that's not saved, we can delete both it and it's preceding message |
| 89 | + else: |
| 90 | + logger.warning( |
| 91 | + f"Context pruning iteration taking too long. Stopping after {max_iterations} iterations." |
| 92 | + ) |
| 93 | + logger.info( |
| 94 | + f"Context Management End:\ncurrent snippets to modify: {repo_context_manager.top_snippet_paths}\n current read only snippets: {repo_context_manager.relevant_read_only_snippet_paths}" |
| 95 | + ) |
| 96 | + repo_context_manager.current_top_snippets = [ |
| 97 | + snippet |
| 98 | + for snippet in repo_context_manager.current_top_snippets |
| 99 | + if snippet.file_path != "sweep.yaml" |
| 100 | + ] |
| 101 | + return |
| 102 | + |
| 103 | +# general framework for a dfs search |
| 104 | +# 1. sample trajectory |
| 105 | +# 2. for each trajectory, run the assistant until it hits an error or end state |
| 106 | +# - in either case perform self-reflection |
| 107 | +# - update reflections section with current reflections |
| 108 | +# 3. update the reflections section with the new reflections |
0 commit comments