autocoder-nano 0.1.26__py3-none-any.whl → 0.1.28__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- autocoder_nano/agent/agent_base.py +376 -63
- autocoder_nano/auto_coder_nano.py +89 -1106
- autocoder_nano/edit/__init__.py +20 -0
- autocoder_nano/edit/actions.py +136 -0
- autocoder_nano/edit/code/__init__.py +0 -0
- autocoder_nano/edit/code/generate_editblock.py +403 -0
- autocoder_nano/edit/code/merge_editblock.py +418 -0
- autocoder_nano/edit/code/modification_ranker.py +90 -0
- autocoder_nano/edit/text.py +38 -0
- autocoder_nano/index/index_manager.py +1 -0
- autocoder_nano/index/symbols_utils.py +43 -0
- autocoder_nano/llm_types.py +1 -0
- autocoder_nano/project/pyproject.py +1 -1
- autocoder_nano/project/suffixproject.py +1 -1
- autocoder_nano/version.py +1 -1
- autocoder_nano-0.1.28.dist-info/METADATA +445 -0
- {autocoder_nano-0.1.26.dist-info → autocoder_nano-0.1.28.dist-info}/RECORD +21 -13
- autocoder_nano-0.1.26.dist-info/METADATA +0 -432
- {autocoder_nano-0.1.26.dist-info → autocoder_nano-0.1.28.dist-info}/LICENSE +0 -0
- {autocoder_nano-0.1.26.dist-info → autocoder_nano-0.1.28.dist-info}/WHEEL +0 -0
- {autocoder_nano-0.1.26.dist-info → autocoder_nano-0.1.28.dist-info}/entry_points.txt +0 -0
- {autocoder_nano-0.1.26.dist-info → autocoder_nano-0.1.28.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
3
|
+
from autocoder_nano.edit.actions import ActionPyProject, ActionSuffixProject
|
4
|
+
from autocoder_nano.llm_client import AutoLLM
|
5
|
+
from autocoder_nano.llm_types import AutoCoderArgs
|
6
|
+
|
7
|
+
|
8
|
+
class Dispacher:
|
9
|
+
def __init__(self, args: AutoCoderArgs, llm: Optional[AutoLLM] = None):
|
10
|
+
self.args = args
|
11
|
+
self.llm = llm
|
12
|
+
|
13
|
+
def dispach(self):
|
14
|
+
dispacher_actions = [
|
15
|
+
ActionPyProject(args=self.args, llm=self.llm),
|
16
|
+
ActionSuffixProject(args=self.args, llm=self.llm)
|
17
|
+
]
|
18
|
+
for action in dispacher_actions:
|
19
|
+
if action.run():
|
20
|
+
return
|
@@ -0,0 +1,136 @@
|
|
1
|
+
import time
|
2
|
+
|
3
|
+
from loguru import logger
|
4
|
+
|
5
|
+
from autocoder_nano.edit.code.generate_editblock import CodeAutoGenerateEditBlock
|
6
|
+
from autocoder_nano.edit.code.merge_editblock import CodeAutoMergeEditBlock
|
7
|
+
from autocoder_nano.index.entry import build_index_and_filter_files
|
8
|
+
from autocoder_nano.llm_client import AutoLLM
|
9
|
+
from autocoder_nano.llm_types import AutoCoderArgs
|
10
|
+
from autocoder_nano.project import PyProject, SuffixProject
|
11
|
+
|
12
|
+
|
13
|
+
class BaseAction:
|
14
|
+
@staticmethod
|
15
|
+
def _get_content_length(content: str) -> int:
|
16
|
+
return len(content)
|
17
|
+
|
18
|
+
|
19
|
+
class ActionPyProject(BaseAction):
|
20
|
+
def __init__(self, args: AutoCoderArgs, llm: AutoLLM) -> None:
|
21
|
+
self.args = args
|
22
|
+
self.llm = llm
|
23
|
+
self.pp = None
|
24
|
+
|
25
|
+
def run(self):
|
26
|
+
if self.args.project_type != "py":
|
27
|
+
return False
|
28
|
+
pp = PyProject(llm=self.llm, args=self.args)
|
29
|
+
self.pp = pp
|
30
|
+
pp.run()
|
31
|
+
source_code = pp.output()
|
32
|
+
if self.llm:
|
33
|
+
source_code = build_index_and_filter_files(args=self.args, llm=self.llm, sources=pp.sources)
|
34
|
+
self.process_content(source_code)
|
35
|
+
return True
|
36
|
+
|
37
|
+
def process_content(self, content: str):
|
38
|
+
# args = self.args
|
39
|
+
if self.args.execute and self.llm:
|
40
|
+
content_length = self._get_content_length(content)
|
41
|
+
if content_length > self.args.model_max_input_length:
|
42
|
+
logger.warning(
|
43
|
+
f"发送给模型的内容长度为 {content_length} 个 token(可能收集了过多文件),"
|
44
|
+
f"已超过最大输入长度限制 {self.args.model_max_input_length}。"
|
45
|
+
)
|
46
|
+
|
47
|
+
if self.args.execute:
|
48
|
+
logger.info("正在自动生成代码...")
|
49
|
+
start_time = time.time()
|
50
|
+
# diff, strict_diff, editblock 是代码自动生成或合并的不同策略, 通常用于处理代码的变更或生成
|
51
|
+
# diff 模式,基于差异生成代码,生成最小的变更集,适用于局部优化,代码重构
|
52
|
+
# strict_diff 模式,严格验证差异,确保生成的代码符合规则,适用于代码审查,自动化测试
|
53
|
+
# editblock 模式,基于编辑块生成代码,支持较大范围的修改,适用于代码重构,功能扩展
|
54
|
+
if self.args.auto_merge == "editblock":
|
55
|
+
generate = CodeAutoGenerateEditBlock(args=self.args, llm=self.llm, action=self)
|
56
|
+
else:
|
57
|
+
generate = None
|
58
|
+
|
59
|
+
if self.args.enable_multi_round_generate:
|
60
|
+
generate_result = generate.multi_round_run(query=self.args.query, source_content=content)
|
61
|
+
else:
|
62
|
+
generate_result = generate.single_round_run(query=self.args.query, source_content=content)
|
63
|
+
logger.info(f"代码生成完成,耗时 {time.time() - start_time:.2f} 秒")
|
64
|
+
|
65
|
+
if self.args.auto_merge:
|
66
|
+
logger.info("正在自动合并代码...")
|
67
|
+
if self.args.auto_merge == "editblock":
|
68
|
+
code_merge = CodeAutoMergeEditBlock(args=self.args, llm=self.llm)
|
69
|
+
merge_result = code_merge.merge_code(generate_result=generate_result)
|
70
|
+
else:
|
71
|
+
merge_result = None
|
72
|
+
|
73
|
+
content = merge_result.contents[0]
|
74
|
+
else:
|
75
|
+
content = generate_result.contents[0]
|
76
|
+
|
77
|
+
with open(self.args.target_file, "w") as file:
|
78
|
+
file.write(content)
|
79
|
+
|
80
|
+
|
81
|
+
class ActionSuffixProject(BaseAction):
|
82
|
+
def __init__(self, args: AutoCoderArgs, llm: AutoLLM) -> None:
|
83
|
+
self.args = args
|
84
|
+
self.llm = llm
|
85
|
+
self.pp = None
|
86
|
+
|
87
|
+
def run(self):
|
88
|
+
pp = SuffixProject(llm=self.llm, args=self.args)
|
89
|
+
self.pp = pp
|
90
|
+
pp.run()
|
91
|
+
source_code = pp.output()
|
92
|
+
if self.llm:
|
93
|
+
source_code = build_index_and_filter_files(args=self.args, llm=self.llm, sources=pp.sources)
|
94
|
+
self.process_content(source_code)
|
95
|
+
|
96
|
+
def process_content(self, content: str):
|
97
|
+
if self.args.execute and self.llm:
|
98
|
+
content_length = self._get_content_length(content)
|
99
|
+
if content_length > self.args.model_max_input_length:
|
100
|
+
logger.warning(
|
101
|
+
f"发送给模型的内容长度为 {content_length} 个 token(可能收集了过多文件),"
|
102
|
+
f"已超过最大输入长度限制 {self.args.model_max_input_length}。"
|
103
|
+
)
|
104
|
+
|
105
|
+
if self.args.execute:
|
106
|
+
logger.info("正在自动生成代码...")
|
107
|
+
start_time = time.time()
|
108
|
+
# diff, strict_diff, editblock 是代码自动生成或合并的不同策略, 通常用于处理代码的变更或生成
|
109
|
+
# diff 模式,基于差异生成代码,生成最小的变更集,适用于局部优化,代码重构
|
110
|
+
# strict_diff 模式,严格验证差异,确保生成的代码符合规则,适用于代码审查,自动化测试
|
111
|
+
# editblock 模式,基于编辑块生成代码,支持较大范围的修改,适用于代码重构,功能扩展
|
112
|
+
if self.args.auto_merge == "editblock":
|
113
|
+
generate = CodeAutoGenerateEditBlock(args=self.args, llm=self.llm, action=self)
|
114
|
+
else:
|
115
|
+
generate = None
|
116
|
+
|
117
|
+
if self.args.enable_multi_round_generate:
|
118
|
+
generate_result = generate.multi_round_run(query=self.args.query, source_content=content)
|
119
|
+
else:
|
120
|
+
generate_result = generate.single_round_run(query=self.args.query, source_content=content)
|
121
|
+
logger.info(f"代码生成完成,耗时 {time.time() - start_time:.2f} 秒")
|
122
|
+
|
123
|
+
if self.args.auto_merge:
|
124
|
+
logger.info("正在自动合并代码...")
|
125
|
+
if self.args.auto_merge == "editblock":
|
126
|
+
code_merge = CodeAutoMergeEditBlock(args=self.args, llm=self.llm)
|
127
|
+
merge_result = code_merge.merge_code(generate_result=generate_result)
|
128
|
+
else:
|
129
|
+
merge_result = None
|
130
|
+
|
131
|
+
content = merge_result.contents[0]
|
132
|
+
else:
|
133
|
+
content = generate_result.contents[0]
|
134
|
+
|
135
|
+
with open(self.args.target_file, "w") as file:
|
136
|
+
file.write(content)
|
File without changes
|
@@ -0,0 +1,403 @@
|
|
1
|
+
from autocoder_nano.llm_client import AutoLLM
|
2
|
+
from autocoder_nano.llm_prompt import prompt
|
3
|
+
from autocoder_nano.llm_types import AutoCoderArgs, CodeGenerateResult
|
4
|
+
|
5
|
+
|
6
|
+
class CodeAutoGenerateEditBlock:
|
7
|
+
def __init__(self, args: AutoCoderArgs, llm: AutoLLM, action=None):
|
8
|
+
self.llm = llm
|
9
|
+
self.args = args
|
10
|
+
self.action = action
|
11
|
+
if not self.llm:
|
12
|
+
raise ValueError("Please provide a valid model instance to use for code generation.")
|
13
|
+
self.llms = [self.llm]
|
14
|
+
|
15
|
+
@prompt()
|
16
|
+
def single_round_instruction(self, instruction: str, content: str, context: str = ""):
|
17
|
+
"""
|
18
|
+
如果你需要生成代码,对于每个需要更改的文件,你需要按 *SEARCH/REPLACE block* 的格式进行生成。
|
19
|
+
|
20
|
+
# *SEARCH/REPLACE block* Rules:
|
21
|
+
|
22
|
+
Every *SEARCH/REPLACE block* must use this format:
|
23
|
+
1. The opening fence and code language, eg: ```python
|
24
|
+
2. The file path alone on a line, starting with "##File:" and verbatim. No bold asterisks, no quotes around it,
|
25
|
+
no escaping of characters, etc.
|
26
|
+
3. The start of search block: <<<<<<< SEARCH
|
27
|
+
4. A contiguous chunk of lines to search for in the existing source code
|
28
|
+
5. The dividing line: =======
|
29
|
+
6. The lines to replace into the source code
|
30
|
+
7. The end of the replacement block: >>>>>>> REPLACE
|
31
|
+
8. The closing fence: ```
|
32
|
+
|
33
|
+
Every *SEARCH* section must *EXACTLY MATCH* the existing source code, character for character,
|
34
|
+
including all comments, docstrings, etc.
|
35
|
+
|
36
|
+
*SEARCH/REPLACE* blocks will replace *all* matching occurrences.
|
37
|
+
Include enough lines to make the SEARCH blocks unique.
|
38
|
+
|
39
|
+
Include *ALL* the code being searched and replaced!
|
40
|
+
|
41
|
+
To move code within a file, use 2 *SEARCH/REPLACE* blocks: 1 to delete it from its current location,
|
42
|
+
1 to insert it in the new location.
|
43
|
+
|
44
|
+
If you want to put code in a new file, use a *SEARCH/REPLACE block* with:
|
45
|
+
- A new file path, including dir name if needed
|
46
|
+
- An empty `SEARCH` section
|
47
|
+
- The new file's contents in the `REPLACE` section
|
48
|
+
|
49
|
+
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
|
50
|
+
|
51
|
+
下面我们来看一个例子:
|
52
|
+
|
53
|
+
当前项目目录结构:
|
54
|
+
1. 项目根目录: /tmp/projects/mathweb
|
55
|
+
2. 项目子目录/文件列表(类似tree 命令输出)
|
56
|
+
flask/
|
57
|
+
app.py
|
58
|
+
templates/
|
59
|
+
index.html
|
60
|
+
static/
|
61
|
+
style.css
|
62
|
+
|
63
|
+
用户需求: Change get_factorial() to use math.factorial
|
64
|
+
|
65
|
+
回答: To make this change we need to modify `/tmp/projects/mathweb/flask/app.py` to:
|
66
|
+
|
67
|
+
1. Import the math package.
|
68
|
+
2. Remove the existing factorial() function.
|
69
|
+
3. Update get_factorial() to call math.factorial instead.
|
70
|
+
|
71
|
+
Here are the *SEARCH/REPLACE* blocks:
|
72
|
+
|
73
|
+
```python
|
74
|
+
##File: /tmp/projects/mathweb/flask/app.py
|
75
|
+
<<<<<<< SEARCH
|
76
|
+
from flask import Flask
|
77
|
+
=======
|
78
|
+
import math
|
79
|
+
from flask import Flask
|
80
|
+
>>>>>>> REPLACE
|
81
|
+
```
|
82
|
+
|
83
|
+
```python
|
84
|
+
##File: /tmp/projects/mathweb/flask/app.py
|
85
|
+
<<<<<<< SEARCH
|
86
|
+
def factorial(n):
|
87
|
+
"compute factorial"
|
88
|
+
|
89
|
+
if n == 0:
|
90
|
+
return 1
|
91
|
+
else:
|
92
|
+
return n * factorial(n-1)
|
93
|
+
|
94
|
+
=======
|
95
|
+
>>>>>>> REPLACE
|
96
|
+
```
|
97
|
+
|
98
|
+
```python
|
99
|
+
##File: /tmp/projects/mathweb/flask/app.py
|
100
|
+
<<<<<<< SEARCH
|
101
|
+
return str(factorial(n))
|
102
|
+
=======
|
103
|
+
return str(math.factorial(n))
|
104
|
+
>>>>>>> REPLACE
|
105
|
+
```
|
106
|
+
|
107
|
+
用户需求: Refactor hello() into its own file.
|
108
|
+
|
109
|
+
回答:To make this change we need to modify `main.py` and make a new file `hello.py`:
|
110
|
+
|
111
|
+
1. Make a new hello.py file with hello() in it.
|
112
|
+
2. Remove hello() from main.py and replace it with an import.
|
113
|
+
|
114
|
+
Here are the *SEARCH/REPLACE* blocks:
|
115
|
+
|
116
|
+
```python
|
117
|
+
##File: /tmp/projects/mathweb/hello.py
|
118
|
+
<<<<<<< SEARCH
|
119
|
+
=======
|
120
|
+
def hello():
|
121
|
+
"print a greeting"
|
122
|
+
|
123
|
+
print("hello")
|
124
|
+
>>>>>>> REPLACE
|
125
|
+
```
|
126
|
+
|
127
|
+
```python
|
128
|
+
##File: /tmp/projects/mathweb/main.py
|
129
|
+
<<<<<<< SEARCH
|
130
|
+
def hello():
|
131
|
+
"print a greeting"
|
132
|
+
|
133
|
+
print("hello")
|
134
|
+
=======
|
135
|
+
from hello import hello
|
136
|
+
>>>>>>> REPLACE
|
137
|
+
```
|
138
|
+
|
139
|
+
现在让我们开始一个新的任务:
|
140
|
+
|
141
|
+
{%- if structure %}
|
142
|
+
{{ structure }}
|
143
|
+
{%- endif %}
|
144
|
+
|
145
|
+
{%- if content %}
|
146
|
+
下面是一些文件路径以及每个文件对应的源码:
|
147
|
+
<files>
|
148
|
+
{{ content }}
|
149
|
+
</files>
|
150
|
+
{%- endif %}
|
151
|
+
|
152
|
+
{%- if context %}
|
153
|
+
<extra_context>
|
154
|
+
{{ context }}
|
155
|
+
</extra_context>
|
156
|
+
{%- endif %}
|
157
|
+
|
158
|
+
下面是用户的需求:
|
159
|
+
|
160
|
+
{{ instruction }}
|
161
|
+
|
162
|
+
"""
|
163
|
+
|
164
|
+
@prompt()
|
165
|
+
def auto_implement_function(self, instruction: str, content: str) -> str:
|
166
|
+
"""
|
167
|
+
下面是一些文件路径以及每个文件对应的源码:
|
168
|
+
|
169
|
+
{{ content }}
|
170
|
+
|
171
|
+
请参考上面的内容,重新实现所有文件下方法体标记了如下内容的方法:
|
172
|
+
|
173
|
+
```python
|
174
|
+
raise NotImplementedError("This function should be implemented by the model.")
|
175
|
+
```
|
176
|
+
|
177
|
+
{{ instruction }}
|
178
|
+
|
179
|
+
"""
|
180
|
+
|
181
|
+
def single_round_run(self, query: str, source_content: str) -> CodeGenerateResult:
|
182
|
+
init_prompt = ''
|
183
|
+
if self.args.template == "common":
|
184
|
+
init_prompt = self.single_round_instruction.prompt(
|
185
|
+
instruction=query, content=source_content, context=self.args.context
|
186
|
+
)
|
187
|
+
elif self.args.template == "auto_implement":
|
188
|
+
init_prompt = self.auto_implement_function.prompt(
|
189
|
+
instruction=query, content=source_content
|
190
|
+
)
|
191
|
+
|
192
|
+
with open(self.args.target_file, "w") as file:
|
193
|
+
file.write(init_prompt)
|
194
|
+
|
195
|
+
conversations = [{"role": "user", "content": init_prompt}]
|
196
|
+
|
197
|
+
conversations_list = []
|
198
|
+
results = []
|
199
|
+
|
200
|
+
for llm in self.llms:
|
201
|
+
v = llm.chat_ai(conversations=conversations, model=self.args.code_model)
|
202
|
+
results.append(v.output)
|
203
|
+
for result in results:
|
204
|
+
conversations_list.append(conversations + [{"role": "assistant", "content": result}])
|
205
|
+
|
206
|
+
return CodeGenerateResult(contents=results, conversations=conversations_list)
|
207
|
+
|
208
|
+
@prompt()
|
209
|
+
def multi_round_instruction(self, instruction: str, content: str, context: str = "") -> str:
|
210
|
+
"""
|
211
|
+
如果你需要生成代码,对于每个需要更改的文件,你需要按 *SEARCH/REPLACE block* 的格式进行生成。
|
212
|
+
|
213
|
+
# *SEARCH/REPLACE block* Rules:
|
214
|
+
|
215
|
+
Every *SEARCH/REPLACE block* must use this format:
|
216
|
+
1. The opening fence and code language, eg: ```python
|
217
|
+
2. The file path alone on a line, starting with "##File:" and verbatim. No bold asterisks, no quotes around it,
|
218
|
+
no escaping of characters, etc.
|
219
|
+
3. The start of search block: <<<<<<< SEARCH
|
220
|
+
4. A contiguous chunk of lines to search for in the existing source code
|
221
|
+
5. The dividing line: =======
|
222
|
+
6. The lines to replace into the source code
|
223
|
+
7. The end of the replacement block: >>>>>>> REPLACE
|
224
|
+
8. The closing fence: ```
|
225
|
+
|
226
|
+
Every *SEARCH* section must *EXACTLY MATCH* the existing source code, character for character,
|
227
|
+
including all comments, docstrings, etc.
|
228
|
+
|
229
|
+
*SEARCH/REPLACE* blocks will replace *all* matching occurrences.
|
230
|
+
Include enough lines to make the SEARCH blocks unique.
|
231
|
+
|
232
|
+
Include *ALL* the code being searched and replaced!
|
233
|
+
|
234
|
+
To move code within a file, use 2 *SEARCH/REPLACE* blocks: 1 to delete it from its current location,
|
235
|
+
1 to insert it in the new location.
|
236
|
+
|
237
|
+
If you want to put code in a new file, use a *SEARCH/REPLACE block* with:
|
238
|
+
- A new file path, including dir name if needed
|
239
|
+
- An empty `SEARCH` section
|
240
|
+
- The new file's contents in the `REPLACE` section
|
241
|
+
|
242
|
+
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
|
243
|
+
|
244
|
+
下面我们来看一个例子:
|
245
|
+
|
246
|
+
当前项目目录结构:
|
247
|
+
1. 项目根目录: /tmp/projects/mathweb
|
248
|
+
2. 项目子目录/文件列表(类似tree 命令输出)
|
249
|
+
flask/
|
250
|
+
app.py
|
251
|
+
templates/
|
252
|
+
index.html
|
253
|
+
static/
|
254
|
+
style.css
|
255
|
+
|
256
|
+
用户需求: Change get_factorial() to use math.factorial
|
257
|
+
|
258
|
+
回答: To make this change we need to modify `/tmp/projects/mathweb/flask/app.py` to:
|
259
|
+
|
260
|
+
1. Import the math package.
|
261
|
+
2. Remove the existing factorial() function.
|
262
|
+
3. Update get_factorial() to call math.factorial instead.
|
263
|
+
|
264
|
+
Here are the *SEARCH/REPLACE* blocks:
|
265
|
+
|
266
|
+
```python
|
267
|
+
##File: /tmp/projects/mathweb/flask/app.py
|
268
|
+
<<<<<<< SEARCH
|
269
|
+
from flask import Flask
|
270
|
+
=======
|
271
|
+
import math
|
272
|
+
from flask import Flask
|
273
|
+
>>>>>>> REPLACE
|
274
|
+
```
|
275
|
+
|
276
|
+
```python
|
277
|
+
##File: /tmp/projects/mathweb/flask/app.py
|
278
|
+
<<<<<<< SEARCH
|
279
|
+
def factorial(n):
|
280
|
+
"compute factorial"
|
281
|
+
|
282
|
+
if n == 0:
|
283
|
+
return 1
|
284
|
+
else:
|
285
|
+
return n * factorial(n-1)
|
286
|
+
|
287
|
+
=======
|
288
|
+
>>>>>>> REPLACE
|
289
|
+
```
|
290
|
+
|
291
|
+
```python
|
292
|
+
##File: /tmp/projects/mathweb/flask/app.py
|
293
|
+
<<<<<<< SEARCH
|
294
|
+
return str(factorial(n))
|
295
|
+
=======
|
296
|
+
return str(math.factorial(n))
|
297
|
+
>>>>>>> REPLACE
|
298
|
+
```
|
299
|
+
|
300
|
+
用户需求: Refactor hello() into its own file.
|
301
|
+
|
302
|
+
回答:To make this change we need to modify `main.py` and make a new file `hello.py`:
|
303
|
+
|
304
|
+
1. Make a new hello.py file with hello() in it.
|
305
|
+
2. Remove hello() from main.py and replace it with an import.
|
306
|
+
|
307
|
+
Here are the *SEARCH/REPLACE* blocks:
|
308
|
+
|
309
|
+
|
310
|
+
```python
|
311
|
+
##File: /tmp/projects/mathweb/hello.py
|
312
|
+
<<<<<<< SEARCH
|
313
|
+
=======
|
314
|
+
def hello():
|
315
|
+
"print a greeting"
|
316
|
+
|
317
|
+
print("hello")
|
318
|
+
>>>>>>> REPLACE
|
319
|
+
```
|
320
|
+
|
321
|
+
```python
|
322
|
+
##File: /tmp/projects/mathweb/main.py
|
323
|
+
<<<<<<< SEARCH
|
324
|
+
def hello():
|
325
|
+
"print a greeting"
|
326
|
+
|
327
|
+
print("hello")
|
328
|
+
=======
|
329
|
+
from hello import hello
|
330
|
+
>>>>>>> REPLACE
|
331
|
+
```
|
332
|
+
|
333
|
+
现在让我们开始一个新的任务:
|
334
|
+
|
335
|
+
{%- if structure %}
|
336
|
+
{{ structure }}
|
337
|
+
{%- endif %}
|
338
|
+
|
339
|
+
{%- if content %}
|
340
|
+
下面是一些文件路径以及每个文件对应的源码:
|
341
|
+
<files>
|
342
|
+
{{ content }}
|
343
|
+
</files>
|
344
|
+
{%- endif %}
|
345
|
+
|
346
|
+
{%- if context %}
|
347
|
+
<extra_context>
|
348
|
+
{{ context }}
|
349
|
+
</extra_context>
|
350
|
+
{%- endif %}
|
351
|
+
|
352
|
+
下面是用户的需求:
|
353
|
+
|
354
|
+
{{ instruction }}
|
355
|
+
|
356
|
+
每次生成一个文件的*SEARCH/REPLACE* blocks,然后询问我是否继续,当我回复继续,
|
357
|
+
继续生成下一个文件的*SEARCH/REPLACE* blocks。当没有后续任务时,请回复 "__完成__" 或者 "__EOF__"。
|
358
|
+
"""
|
359
|
+
|
360
|
+
def multi_round_run(self, query: str, source_content: str, max_steps: int = 3) -> CodeGenerateResult:
|
361
|
+
init_prompt = ''
|
362
|
+
if self.args.template == "common":
|
363
|
+
init_prompt = self.multi_round_instruction.prompt(
|
364
|
+
instruction=query, content=source_content, context=self.args.context
|
365
|
+
)
|
366
|
+
elif self.args.template == "auto_implement":
|
367
|
+
init_prompt = self.auto_implement_function.prompt(
|
368
|
+
instruction=query, content=source_content
|
369
|
+
)
|
370
|
+
|
371
|
+
with open(self.args.target_file, "w") as file:
|
372
|
+
file.write(init_prompt)
|
373
|
+
|
374
|
+
results = []
|
375
|
+
conversations = [{"role": "user", "content": init_prompt}]
|
376
|
+
|
377
|
+
code_llm = self.llms[0]
|
378
|
+
v = code_llm.chat_ai(conversations=conversations, model=self.args.code_model)
|
379
|
+
results.append(v.output)
|
380
|
+
|
381
|
+
conversations.append({"role": "assistant", "content": v.output})
|
382
|
+
|
383
|
+
if "__完成__" in v.output or "/done" in v.output or "__EOF__" in v.output:
|
384
|
+
return CodeGenerateResult(contents=["\n\n".join(results)], conversations=[conversations])
|
385
|
+
|
386
|
+
current_step = 0
|
387
|
+
|
388
|
+
while current_step < max_steps:
|
389
|
+
conversations.append({"role": "user", "content": "继续"})
|
390
|
+
|
391
|
+
with open(self.args.target_file, "w") as file:
|
392
|
+
file.write("继续")
|
393
|
+
|
394
|
+
t = code_llm.chat_ai(conversations=conversations, model=self.args.code_model)
|
395
|
+
|
396
|
+
results.append(t.output)
|
397
|
+
conversations.append({"role": "assistant", "content": t.output})
|
398
|
+
current_step += 1
|
399
|
+
|
400
|
+
if "__完成__" in t.output or "/done" in t.output or "__EOF__" in t.output:
|
401
|
+
return CodeGenerateResult(contents=["\n\n".join(results)], conversations=[conversations])
|
402
|
+
|
403
|
+
return CodeGenerateResult(contents=["\n\n".join(results)], conversations=[conversations])
|