Skip to content

Commit 7b77628

Browse files
committed
✨ Refactor commit command with structured output
Enhance the commit command by introducing a structured output approach: - Add CommitMessage Pydantic model for structured commit messages - Implement PydanticOutputParser for improved parsing - Modify chain to use structured output - Update commit message handling for better consistency - Remove manual quote stripping, as it's no longer necessary This refactoring improves code quality and maintainability while ensuring more consistent and structured commit messages. Oh, the sweet smell of progress! 🧐
1 parent e96d8e1 commit 7b77628

File tree

1 file changed

+16
-14
lines changed

1 file changed

+16
-14
lines changed

aicodebot/commands/commit.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
from aicodebot.coder import Coder
22
from aicodebot.helpers import exec_and_get_output, logger
33
from aicodebot.lm import LanguageModelManager
4-
from aicodebot.output import OurMarkdown, RichLiveCallbackHandler, get_console
4+
from aicodebot.output import OurMarkdown, get_console
55
from aicodebot.prompts import get_prompt
66
from pathlib import Path
7-
from rich.live import Live
7+
from pydantic import BaseModel, Field
8+
from rich.panel import Panel
89
import click, os, shutil, subprocess, sys, tempfile
910

1011

12+
class CommitMessage(BaseModel):
13+
# Important to put the detail first, as it improves the quality of the summary
14+
git_message_detail: str = Field(description="A detailed explanation of the changes made in this commit")
15+
git_message_summary: str = Field(description="A brief summary of the commit message")
16+
17+
1118
@click.command()
1219
@click.option("-t", "--response-token-size", type=int, default=250)
1320
@click.option("-y", "--yes", is_flag=True, default=False, help="Don't ask for confirmation before committing.")
@@ -84,26 +91,21 @@ def commit(response_token_size, yes, skip_pre_commit, files): # noqa: PLR0915
8491
lmm = LanguageModelManager()
8592

8693
console.print("Analyzing the differences and generating a commit message")
87-
with Live(OurMarkdown(f"Talking to {lmm.model_name} via {lmm.provider}"), auto_refresh=True) as live:
88-
llm = lmm.model_factory(
89-
response_token_size=response_token_size,
90-
streaming=True,
91-
callbacks=[RichLiveCallbackHandler(live, console.bot_style)],
92-
)
93-
chain = prompt | llm
94+
with console.status(f"Generating commit message with {lmm.model_name} via {lmm.provider}", spinner="dots"):
95+
llm = lmm.model_factory(response_token_size=response_token_size)
96+
structured_llm = llm.with_structured_output(CommitMessage)
97+
chain = prompt | structured_llm
9498
response = chain.invoke({"diff_context": diff_context, "languages": languages})
95-
live.update(OurMarkdown(str(response)))
99+
100+
console.print(Panel(OurMarkdown(f"{response.git_message_summary}\n\n{response.git_message_detail}")))
96101

97102
commit_message_approved = not console.is_terminal or click.confirm(
98103
"Would you like to use this generated commit message? Type 'n' to edit it.", default=True
99104
)
100105

101106
# Write the commit message to a temporary file
102107
with tempfile.NamedTemporaryFile(mode="w", delete=False) as temp:
103-
# For some reason the response often contains quotes around the summary, even if I tell it not to
104-
# So we strip them here
105-
commit_message = str(response.content).replace('"', "").strip()
106-
108+
commit_message = f"{response.git_message_summary}\n\n{response.git_message_detail}"
107109
temp.write(commit_message)
108110
temp_file_name = temp.name
109111

0 commit comments

Comments
 (0)