|
2 | 2 | from aicodebot.config import read_config |
3 | 3 | from aicodebot.helpers import logger |
4 | 4 | from langchain import PromptTemplate |
| 5 | +from langchain.output_parsers import PydanticOutputParser |
5 | 6 | from pathlib import Path |
| 7 | +from pydantic import BaseModel, Field |
6 | 8 | from types import SimpleNamespace |
7 | 9 | import functools, os |
8 | 10 |
|
@@ -266,47 +268,73 @@ def generate_files_context(files): |
266 | 268 | + get_personality_prompt() |
267 | 269 | + """ |
268 | 270 |
|
269 | | - DO NOT give comments that discuss formatting, as those will be handled with pre-commit hooks. |
270 | | - DO NOT respond with line numbers, use function names or file names instead. |
271 | | -
|
272 | 271 | Here's the diff context: |
273 | 272 |
|
274 | 273 | BEGIN DIFF |
275 | 274 | {diff_context} |
276 | 275 | END DIFF |
277 | 276 |
|
278 | 277 | Remember: |
279 | | - - Lines starting with "-" are being removed. |
280 | | - - Lines starting with "+" are being added. |
281 | | - - Lines starting with " " are unchanged. |
| 278 | + * Lines starting with "-" are being removed. |
| 279 | + * Lines starting with "+" are being added. |
| 280 | + * Lines starting with " " are unchanged. |
| 281 | + * Consider the file names for context (e.g., "README.md" is a markdown file, "*.py" is a Python file). |
| 282 | + * Understand the difference between code and comments. Comment lines start with ##, #, or //. |
| 283 | + * Point out obvious spelling mistakes in plain text files if you see them, but don't check for spelling in code. |
| 284 | + * Do not talk about minor changes. It's better to be terse and focus on issues. |
| 285 | + * Do not talk about formatting, as that will be handled with pre-commit hooks. |
| 286 | +
|
| 287 | + The main focus is to tell the developer how to make the code better. |
| 288 | +
|
| 289 | + The review_status can be one of the following: |
| 290 | + * "PASSED" (looks good to me) - there were no serious issues found, |
| 291 | + * "COMMENTS" - there were some issues found, but they should not block the build and are informational only |
| 292 | + * "FAILED" - there were serious, blocking issues found that should be fixed before merging the code |
| 293 | +
|
| 294 | + The review_message should be a markdown-formatted string for display with rich.Markdown or GitHub markdown. |
| 295 | +""" |
| 296 | +) |
282 | 297 |
|
283 | | - Consider the file names for context (e.g., "README.md" is a markdown file, "*.py" is a Python file). |
284 | | - Understand the difference between code and comments. Comment lines start with ##, #, or //. |
285 | 298 |
|
286 | | - The main focus is to tell me how I could make the code better. |
| 299 | +def get_prompt(command, structured_output=False): |
| 300 | + """Generates a prompt for the sidekick workflow.""" |
287 | 301 |
|
288 | | - Point out spelling mistakes in plain text files if you see them, but don't try to spell |
289 | | - function and variable names correctly. |
| 302 | + if command == "review": |
| 303 | + if structured_output: |
| 304 | + parser = PydanticOutputParser(pydantic_object=ReviewResult) |
| 305 | + return PromptTemplate( |
| 306 | + template=REVIEW_TEMPLATE + "\n{format_instructions}", |
| 307 | + input_variables=["diff_context"], |
| 308 | + partial_variables={"format_instructions": parser.get_format_instructions()}, |
| 309 | + output_parser=parser, |
| 310 | + ) |
| 311 | + else: |
| 312 | + return PromptTemplate( |
| 313 | + template=REVIEW_TEMPLATE + "\nRespond in markdown format", input_variables=["diff_context"] |
| 314 | + ) |
290 | 315 |
|
291 | | - If the changes look good overall and don't require any feedback, then just respond with "LGTM" (looks good to me). |
| 316 | + else: |
| 317 | + prompt_map = { |
| 318 | + "alignment": PromptTemplate(template=ALIGNMENT_TEMPLATE, input_variables=[]), |
| 319 | + "commit": PromptTemplate(template=COMMIT_TEMPLATE, input_variables=["diff_context"]), |
| 320 | + "debug": PromptTemplate(template=DEBUG_TEMPLATE, input_variables=["command_output"]), |
| 321 | + "fun_fact": PromptTemplate(template=FUN_FACT_TEMPLATE, input_variables=["topic"]), |
| 322 | + "sidekick": PromptTemplate(template=SIDEKICK_TEMPLATE, input_variables=["chat_history", "task", "context"]), |
| 323 | + } |
292 | 324 |
|
293 | | - Respond in markdown format. |
294 | | -""" |
295 | | -) |
| 325 | + try: |
| 326 | + return prompt_map[command] |
| 327 | + except KeyError as e: |
| 328 | + raise ValueError(f"Unable to find prompt for command {command}") from e |
296 | 329 |
|
297 | 330 |
|
298 | | -def get_prompt(command): |
299 | | - """Generates a prompt for the sidekick workflow.""" |
300 | | - prompt_map = { |
301 | | - "alignment": PromptTemplate(template=ALIGNMENT_TEMPLATE, input_variables=[]), |
302 | | - "commit": PromptTemplate(template=COMMIT_TEMPLATE, input_variables=["diff_context"]), |
303 | | - "debug": PromptTemplate(template=DEBUG_TEMPLATE, input_variables=["command_output"]), |
304 | | - "fun_fact": PromptTemplate(template=FUN_FACT_TEMPLATE, input_variables=["topic"]), |
305 | | - "review": PromptTemplate(template=REVIEW_TEMPLATE, input_variables=["diff_context"]), |
306 | | - "sidekick": PromptTemplate(template=SIDEKICK_TEMPLATE, input_variables=["chat_history", "task", "context"]), |
307 | | - } |
308 | | - |
309 | | - try: |
310 | | - return prompt_map[command] |
311 | | - except KeyError as e: |
312 | | - raise ValueError(f"Unable to find prompt for command {command}") from e |
| 331 | +# ---------------------------------------------------------------------------- # |
| 332 | +# Output Parsers # |
| 333 | +# ---------------------------------------------------------------------------- # |
| 334 | + |
| 335 | + |
| 336 | +class ReviewResult(BaseModel): |
| 337 | + """Review result from the sidekick.""" |
| 338 | + |
| 339 | + review_status: str = Field(description="The status of the review: PASSED, COMMENTS, or FAILED") |
| 340 | + review_comments: str = Field(description="The comments from the review") |
0 commit comments