gptdiff 0.1.18__tar.gz → 0.1.20__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {gptdiff-0.1.18 → gptdiff-0.1.20}/PKG-INFO +1 -1
- {gptdiff-0.1.18 → gptdiff-0.1.20}/gptdiff/gptdiff.py +32 -2
- {gptdiff-0.1.18 → gptdiff-0.1.20}/gptdiff.egg-info/PKG-INFO +1 -1
- {gptdiff-0.1.18 → gptdiff-0.1.20}/gptdiff.egg-info/SOURCES.txt +2 -1
- {gptdiff-0.1.18 → gptdiff-0.1.20}/setup.py +1 -1
- gptdiff-0.1.20/tests/test_swallow_reasoning.py +51 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/LICENSE.txt +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/README.md +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/gptdiff/__init__.py +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/gptdiff/gptpatch.py +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/gptdiff.egg-info/dependency_links.txt +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/gptdiff.egg-info/entry_points.txt +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/gptdiff.egg-info/requires.txt +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/gptdiff.egg-info/top_level.txt +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/setup.cfg +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/tests/test_applydiff.py +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/tests/test_applydiff_edgecases.py +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/tests/test_diff_parse.py +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/tests/test_failing_case.py +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/tests/test_parse_diff_per_file.py +0 -0
- {gptdiff-0.1.18 → gptdiff-0.1.20}/tests/test_smartapply.py +0 -0
@@ -202,7 +202,7 @@ def call_llm_for_diff(system_prompt, user_prompt, files_content, model, temperat
|
|
202
202
|
tool_prompt = formatter.usage_prompt(toolbox)
|
203
203
|
system_prompt += "\n"+tool_prompt
|
204
204
|
|
205
|
-
if
|
205
|
+
if 'gemini' in model:
|
206
206
|
user_prompt = system_prompt+"\n"+user_prompt
|
207
207
|
|
208
208
|
messages = [
|
@@ -241,6 +241,9 @@ def call_llm_for_diff(system_prompt, user_prompt, files_content, model, temperat
|
|
241
241
|
cost = (prompt_tokens / 1_000_000 * cost_per_million_prompt_tokens) + (completion_tokens / 1_000_000 * cost_per_million_completion_tokens)
|
242
242
|
|
243
243
|
full_response = response.choices[0].message.content.strip()
|
244
|
+
full_response, reasoning = swallow_reasoning(full_response)
|
245
|
+
if reasoning and len(reasoning) > 0:
|
246
|
+
print("Swallowed reasoning", reasoning)
|
244
247
|
|
245
248
|
events = parser.parse(full_response)
|
246
249
|
for event in events:
|
@@ -643,6 +646,9 @@ def call_llm_for_apply_with_think_tool_available(file_path, original_content, fi
|
|
643
646
|
formatter = FlatXMLPromptFormatter(tag="think")
|
644
647
|
toolbox = create_think_toolbox()
|
645
648
|
full_response = call_llm_for_apply(file_path, original_content, file_diff, model, api_key=api_key, base_url=base_url, extra_prompt=extra_prompt, max_tokens=max_tokens)
|
649
|
+
full_response, reasoning = swallow_reasoning(full_response)
|
650
|
+
if reasoning and len(reasoning) > 0:
|
651
|
+
print("Swallowed reasoning", reasoning)
|
646
652
|
notool_response = ""
|
647
653
|
events = parser.parse(full_response)
|
648
654
|
is_in_tool = False
|
@@ -707,7 +713,7 @@ Diff to apply:
|
|
707
713
|
```"""
|
708
714
|
if extra_prompt:
|
709
715
|
user_prompt += f"\n\n{extra_prompt}"
|
710
|
-
if
|
716
|
+
if 'gemini' in model:
|
711
717
|
user_prompt = system_prompt+"\n"+user_prompt
|
712
718
|
messages = [
|
713
719
|
{"role": "system", "content": system_prompt},
|
@@ -967,5 +973,29 @@ def main():
|
|
967
973
|
print(f"Total tokens: {total_tokens}")
|
968
974
|
#print(f"Total cost: ${cost:.4f}")
|
969
975
|
|
976
|
+
def swallow_reasoning(full_response: str) -> (str, str):
|
977
|
+
"""
|
978
|
+
Extracts and swallows the chain-of-thought reasoning section from the full LLM response.
|
979
|
+
Assumes the reasoning block starts with a line beginning with "> Reasoning"
|
980
|
+
and ends with a line matching 'Reasoned for <number> seconds'.
|
981
|
+
|
982
|
+
Returns:
|
983
|
+
A tuple (final_content, reasoning) where:
|
984
|
+
- final_content: The response with the reasoning block removed.
|
985
|
+
- reasoning: The extracted reasoning block, or an empty string if not found.
|
986
|
+
"""
|
987
|
+
pattern = re.compile(
|
988
|
+
r"(?P<reasoning>>\s*Reasoning.*?Reasoned for \d+\s*seconds)",
|
989
|
+
re.DOTALL
|
990
|
+
)
|
991
|
+
match = pattern.search(full_response)
|
992
|
+
if match:
|
993
|
+
reasoning = match.group("reasoning").strip()
|
994
|
+
final_content = full_response.replace(reasoning, "").strip()
|
995
|
+
else:
|
996
|
+
reasoning = ""
|
997
|
+
final_content = full_response.strip()
|
998
|
+
return final_content, reasoning
|
999
|
+
|
970
1000
|
if __name__ == "__main__":
|
971
1001
|
main()
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
2
2
|
|
3
3
|
setup(
|
4
4
|
name='gptdiff',
|
5
|
-
version='0.1.
|
5
|
+
version='0.1.20',
|
6
6
|
description='A tool to generate and apply git diffs using LLMs',
|
7
7
|
author='255labs',
|
8
8
|
packages=find_packages(), # Use find_packages() to automatically discover packages
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
from gptdiff.gptdiff import swallow_reasoning
|
4
|
+
|
5
|
+
|
6
|
+
def test_swallow_reasoning_extraction():
|
7
|
+
llm_response = (
|
8
|
+
"> Reasoning\n"
|
9
|
+
"**Applying the diff**\n"
|
10
|
+
"I'm piecing together how to efficiently apply a diff to a file...\n"
|
11
|
+
"**Returning the result**\n"
|
12
|
+
"I'm finalizing the method to apply the diff updates...\n"
|
13
|
+
"Reasoned for 6 seconds\n"
|
14
|
+
"\n"
|
15
|
+
"```diff\n"
|
16
|
+
"--- a/file.py\n"
|
17
|
+
"+++ b/file.py\n"
|
18
|
+
"@@ -1,2 +1,2 @@\n"
|
19
|
+
"-def old():\n"
|
20
|
+
"+def new():\n"
|
21
|
+
"```"
|
22
|
+
)
|
23
|
+
final_content, reasoning = swallow_reasoning(llm_response)
|
24
|
+
expected_reasoning = (
|
25
|
+
"> Reasoning\n"
|
26
|
+
"**Applying the diff**\n"
|
27
|
+
"I'm piecing together how to efficiently apply a diff to a file...\n"
|
28
|
+
"**Returning the result**\n"
|
29
|
+
"I'm finalizing the method to apply the diff updates...\n"
|
30
|
+
"Reasoned for 6 seconds"
|
31
|
+
)
|
32
|
+
assert reasoning == expected_reasoning
|
33
|
+
# The final content should no longer contain the reasoning block.
|
34
|
+
assert expected_reasoning not in final_content
|
35
|
+
# And it should contain the diff block.
|
36
|
+
assert "```diff" in final_content
|
37
|
+
|
38
|
+
|
39
|
+
def test_swallow_reasoning_no_reasoning():
|
40
|
+
llm_response = (
|
41
|
+
"```diff\n"
|
42
|
+
"--- a/file.py\n"
|
43
|
+
"+++ b/file.py\n"
|
44
|
+
"@@ -1,2 +1,2 @@\n"
|
45
|
+
"-def old():\n"
|
46
|
+
"+def new():\n"
|
47
|
+
"```"
|
48
|
+
)
|
49
|
+
final_content, reasoning = swallow_reasoning(llm_response)
|
50
|
+
assert reasoning == ""
|
51
|
+
assert final_content == llm_response.strip()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|