auto-coder 0.1.287__py3-none-any.whl → 0.1.289__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.
Potentially problematic release.
This version of auto-coder might be problematic. Click here for more details.
- {auto_coder-0.1.287.dist-info → auto_coder-0.1.289.dist-info}/METADATA +1 -1
- {auto_coder-0.1.287.dist-info → auto_coder-0.1.289.dist-info}/RECORD +26 -17
- autocoder/chat_auto_coder.py +265 -82
- autocoder/chat_auto_coder_lang.py +25 -21
- autocoder/commands/auto_web.py +1062 -0
- autocoder/common/__init__.py +1 -2
- autocoder/common/anything2img.py +113 -43
- autocoder/common/auto_coder_lang.py +40 -1
- autocoder/common/computer_use.py +931 -0
- autocoder/common/mcp_hub.py +99 -77
- autocoder/common/mcp_server.py +162 -61
- autocoder/index/filter/quick_filter.py +373 -3
- autocoder/plugins/__init__.py +1123 -0
- autocoder/plugins/dynamic_completion_example.py +148 -0
- autocoder/plugins/git_helper_plugin.py +252 -0
- autocoder/plugins/sample_plugin.py +160 -0
- autocoder/plugins/token_helper_plugin.py +343 -0
- autocoder/plugins/utils.py +9 -0
- autocoder/rag/long_context_rag.py +22 -9
- autocoder/rag/relevant_utils.py +1 -1
- autocoder/rag/searchable.py +58 -0
- autocoder/version.py +1 -1
- {auto_coder-0.1.287.dist-info → auto_coder-0.1.289.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.287.dist-info → auto_coder-0.1.289.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.287.dist-info → auto_coder-0.1.289.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.287.dist-info → auto_coder-0.1.289.dist-info}/top_level.txt +0 -0
autocoder/common/__init__.py
CHANGED
|
@@ -329,8 +329,7 @@ class AutoCoderArgs(pydantic.BaseModel):
|
|
|
329
329
|
rag_build_name: Optional[str] = None
|
|
330
330
|
disable_auto_window: bool = False
|
|
331
331
|
filter_batch_size: Optional[int] = 5
|
|
332
|
-
disable_segment_reorder: bool = False
|
|
333
|
-
rag_doc_filter_relevance: int = 5
|
|
332
|
+
disable_segment_reorder: bool = False
|
|
334
333
|
tokenizer_path: Optional[str] = None
|
|
335
334
|
skip_confirm: Optional[bool] = False
|
|
336
335
|
silence: Optional[bool] = False
|
autocoder/common/anything2img.py
CHANGED
|
@@ -11,6 +11,9 @@ from spire.doc import Document
|
|
|
11
11
|
from spire.doc import ImageType
|
|
12
12
|
from PIL import Image
|
|
13
13
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
14
|
+
import json
|
|
15
|
+
from byzerllm.utils.client import code_utils
|
|
16
|
+
|
|
14
17
|
class ImageInfo(pydantic.BaseModel):
|
|
15
18
|
"""
|
|
16
19
|
图片信息
|
|
@@ -35,7 +38,10 @@ class Anything2Img:
|
|
|
35
38
|
keep_conversion: bool = False,
|
|
36
39
|
):
|
|
37
40
|
self.llm = llm
|
|
38
|
-
|
|
41
|
+
if llm.get_sub_client("vl_model"):
|
|
42
|
+
self.vl_model = llm.get_sub_client("vl_model")
|
|
43
|
+
else:
|
|
44
|
+
self.vl_model = self.llm
|
|
39
45
|
self.args = args
|
|
40
46
|
self.output_dir = args.output
|
|
41
47
|
os.makedirs(self.output_dir, exist_ok=True)
|
|
@@ -45,28 +51,59 @@ class Anything2Img:
|
|
|
45
51
|
def analyze_image(self, image_path: str) -> str:
|
|
46
52
|
"""
|
|
47
53
|
{{ image }}
|
|
48
|
-
|
|
49
|
-
|
|
54
|
+
图片中一般可能包含文字,图片,图表三种元素,给出每种元素的bounding box坐标。
|
|
55
|
+
bouding box 使用 (xmin, ymin, xmax, ymax) 来表示,其中xmin, ymin: 表示矩形左上角的坐标
|
|
56
|
+
xmax, ymax: 表示矩形右下角的坐标
|
|
50
57
|
|
|
58
|
+
最后按如下格式返回:
|
|
51
59
|
```json
|
|
52
60
|
{
|
|
53
|
-
"
|
|
54
|
-
|
|
61
|
+
"objects": [
|
|
62
|
+
{
|
|
63
|
+
"type": "image",
|
|
64
|
+
"bounding_box": [xmin, ymin, xmax, ymax],
|
|
65
|
+
"text": "图片描述"
|
|
66
|
+
},
|
|
55
67
|
{
|
|
56
|
-
"
|
|
57
|
-
"
|
|
68
|
+
"type": "text",
|
|
69
|
+
"bounding_box": [xmin, ymin, xmax, ymax],
|
|
70
|
+
"text": "文本内容"
|
|
58
71
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
72
|
+
,
|
|
73
|
+
{
|
|
74
|
+
"type": "table",
|
|
75
|
+
"bounding_box": [xmin, ymin, xmax, ymax],
|
|
76
|
+
"text": "表格的markdown格式"
|
|
77
|
+
}
|
|
78
|
+
...
|
|
79
|
+
]
|
|
62
80
|
}
|
|
63
81
|
```
|
|
82
|
+
"""
|
|
83
|
+
image = byzerllm.Image.load_image_from_path(image_path)
|
|
84
|
+
return {"image": image}
|
|
85
|
+
|
|
86
|
+
@byzerllm.prompt()
|
|
87
|
+
def detect_objects(self, image_path: str) -> str:
|
|
88
|
+
"""
|
|
89
|
+
{{ image }}
|
|
90
|
+
请分析这张图片,识别图片中图片,并给出每个图片的bounding box坐标。
|
|
91
|
+
bouding box 使用 (xmin, ymin, xmax, ymax) 来表示,其中xmin, ymin: 表示矩形左上角的坐标
|
|
92
|
+
xmax, ymax: 表示矩形右下角的坐标
|
|
64
93
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
94
|
+
最后按如下格式返回:
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"objects": [
|
|
98
|
+
{
|
|
99
|
+
"bounding_box": [xmin, ymin, xmax, ymax],
|
|
100
|
+
"text": "图片描述"
|
|
101
|
+
},
|
|
102
|
+
...
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
70
107
|
"""
|
|
71
108
|
image = byzerllm.Image.load_image_from_path(image_path)
|
|
72
109
|
return {"image": image}
|
|
@@ -141,12 +178,12 @@ class Anything2Img:
|
|
|
141
178
|
else:
|
|
142
179
|
image_paths = self.convert(file_path)[0:size]
|
|
143
180
|
|
|
144
|
-
|
|
181
|
+
pages_results = []
|
|
145
182
|
# 使用线程池并行分析图片
|
|
146
183
|
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
147
184
|
futures = {
|
|
148
185
|
executor.submit(
|
|
149
|
-
self.analyze_image.with_llm(self.vl_model).
|
|
186
|
+
self.analyze_image.with_llm(self.vl_model).run,
|
|
150
187
|
image_path
|
|
151
188
|
): image_path for image_path in image_paths
|
|
152
189
|
}
|
|
@@ -155,7 +192,11 @@ class Anything2Img:
|
|
|
155
192
|
image_path = futures[future]
|
|
156
193
|
try:
|
|
157
194
|
result = future.result()
|
|
158
|
-
|
|
195
|
+
# 解析JSON结果
|
|
196
|
+
result_json = code_utils.extract_code(result)[-1][1]
|
|
197
|
+
result_dict = json.loads(result_json)
|
|
198
|
+
# 存储结果和对应的图像路径
|
|
199
|
+
pages_results.append((result_dict, image_path))
|
|
159
200
|
logger.info(f"Analyzed {image_path}")
|
|
160
201
|
except Exception as e:
|
|
161
202
|
logger.error(f"Failed to analyze {image_path}: {str(e)}")
|
|
@@ -163,34 +204,63 @@ class Anything2Img:
|
|
|
163
204
|
# 生成Markdown内容
|
|
164
205
|
markdown_content = []
|
|
165
206
|
|
|
166
|
-
#
|
|
167
|
-
for
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
207
|
+
# 遍历每个页面的分析结果
|
|
208
|
+
for page_result, image_path in pages_results:
|
|
209
|
+
page_markdown = []
|
|
210
|
+
|
|
211
|
+
# 按照对象类型分别处理文本、图片和表格
|
|
212
|
+
text_objects = []
|
|
213
|
+
image_objects = []
|
|
214
|
+
table_objects = []
|
|
215
|
+
|
|
216
|
+
for obj in page_result.get("objects", []):
|
|
217
|
+
obj_type = obj.get("type", "")
|
|
218
|
+
if obj_type == "text":
|
|
219
|
+
text_objects.append(obj)
|
|
220
|
+
elif obj_type == "image":
|
|
221
|
+
image_objects.append(obj)
|
|
222
|
+
elif obj_type == "table":
|
|
223
|
+
table_objects.append(obj)
|
|
224
|
+
|
|
225
|
+
# 按照垂直位置排序所有对象
|
|
226
|
+
all_objects = text_objects + image_objects + table_objects
|
|
227
|
+
all_objects.sort(key=lambda x: x.get("bounding_box", [0, 0, 0, 0])[1]) # 按y坐标排序
|
|
228
|
+
|
|
229
|
+
# 处理所有对象并生成markdown
|
|
230
|
+
for obj in all_objects:
|
|
231
|
+
obj_type = obj.get("type", "")
|
|
232
|
+
bbox = obj.get("bounding_box", [0, 0, 0, 0])
|
|
233
|
+
content = obj.get("text", "")
|
|
181
234
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
235
|
+
if obj_type == "text":
|
|
236
|
+
# 直接添加文本内容
|
|
237
|
+
page_markdown.append(content)
|
|
185
238
|
|
|
186
|
-
|
|
187
|
-
|
|
239
|
+
elif obj_type == "image":
|
|
240
|
+
# 处理图片
|
|
241
|
+
original_image = Image.open(image_path)
|
|
242
|
+
|
|
243
|
+
# 提取图片区域
|
|
244
|
+
x1, y1, x2, y2 = [int(coord) for coord in bbox]
|
|
245
|
+
cropped_image = original_image.crop((x1, y1, x2, y2))
|
|
246
|
+
|
|
247
|
+
# 生成唯一文件名
|
|
248
|
+
image_filename = f"img_{os.path.basename(image_path)}_{x1}_{y1}_{x2}_{y2}.png"
|
|
249
|
+
cropped_image_path = os.path.join(images_dir, image_filename)
|
|
250
|
+
cropped_image.save(cropped_image_path)
|
|
251
|
+
|
|
252
|
+
# 添加图片的markdown
|
|
253
|
+
image_markdown = f""
|
|
254
|
+
page_markdown.append(image_markdown)
|
|
188
255
|
|
|
189
|
-
|
|
190
|
-
|
|
256
|
+
elif obj_type == "table":
|
|
257
|
+
# 对表格内容进行处理,它已经是markdown格式
|
|
258
|
+
page_markdown.append(content)
|
|
191
259
|
|
|
192
|
-
#
|
|
193
|
-
|
|
260
|
+
# 将页面内容合并为字符串
|
|
261
|
+
page_content = "\n\n".join(page_markdown)
|
|
262
|
+
markdown_content.append(page_content)
|
|
194
263
|
|
|
195
264
|
# 将所有页面内容合并为一个Markdown文档
|
|
196
|
-
return '\n\n'.join(markdown_content)
|
|
265
|
+
return '\n\n---\n\n'.join(markdown_content)
|
|
266
|
+
|
|
@@ -172,7 +172,26 @@ MESSAGES = {
|
|
|
172
172
|
"file_snippet_procesed": "{{ file_path }} processed with tokens: {{ tokens }} => {{ snippet_tokens }}. Current total tokens: {{ total_tokens }}",
|
|
173
173
|
"tool_ask_user": "Your Reply: ",
|
|
174
174
|
"tool_ask_user_accept":"Your Response received",
|
|
175
|
-
|
|
175
|
+
"auto_web_analyzing": "Analyzing web automation task...",
|
|
176
|
+
"auto_web_analyzed": "Web automation task analysis completed",
|
|
177
|
+
"executing_web_action": "Executing action: {{action}} - {{description}}",
|
|
178
|
+
"executing_step": "Executing step {{step}}: {{description}}",
|
|
179
|
+
"operation_cancelled": "Operation cancelled",
|
|
180
|
+
"element_not_found": "Element not found: {{element}}",
|
|
181
|
+
"analyzing_results": "Analyzing execution results...",
|
|
182
|
+
"next_steps_determined": "Next steps determined",
|
|
183
|
+
"max_iterations_reached": "Max iterations reached ({max_iterations})",
|
|
184
|
+
"action_verification_failed": "Action verification failed: {{action}} - {{reason}}",
|
|
185
|
+
"action_succeeded": "Action succeeded: {{action}}",
|
|
186
|
+
"replanned_actions": "Replanned {{count}} actions",
|
|
187
|
+
"web_automation_ask_user": "Your answer: ",
|
|
188
|
+
"filter_mode_normal": "Using normal filter mode for index processing...",
|
|
189
|
+
"filter_mode_big": "Index file is large ({{ tokens_len }} tokens), using big_filter mode for processing...",
|
|
190
|
+
"filter_mode_super_big": "Index file is very large ({{ tokens_len }} tokens), using super_big_filter mode for processing...",
|
|
191
|
+
"super_big_filter_failed": "❌ Super big filter failed: {{ error }}.",
|
|
192
|
+
"super_big_filter_stats": "{{ model_names }} Super big filter completed in {{ elapsed_time }} seconds, input tokens: {{ input_tokens }}, output tokens: {{ output_tokens }}, input cost: {{ input_cost }}, output cost: {{ output_cost }}, speed: {{ speed }} tokens/s, chunk_index: {{ chunk_index }}",
|
|
193
|
+
"super_big_filter_splitting": "⚠️ Index file is extremely large ({{ tokens_len }}/{{ max_tokens }}). The query will be split into {{ split_size }} chunks for processing.",
|
|
194
|
+
"super_big_filter_title": "{{ model_name }} is analyzing how to filter extremely large context..."
|
|
176
195
|
},
|
|
177
196
|
"zh": {
|
|
178
197
|
"file_sliding_window_processing": "文件 {{ file_path }} 过大 ({{ tokens }} tokens),正在使用滑动窗口处理...",
|
|
@@ -342,6 +361,26 @@ MESSAGES = {
|
|
|
342
361
|
"file_snippet_procesed": "文件 {{ file_path }} 处理后token数: {{ tokens }} => {{ snippet_tokens }} 当前总token数: {{ total_tokens }}",
|
|
343
362
|
"tool_ask_user": "您的回复: ",
|
|
344
363
|
"tool_ask_user_accept":"收到您的回复",
|
|
364
|
+
"auto_web_analyzing": "正在分析网页自动化任务...",
|
|
365
|
+
"auto_web_analyzed": "网页自动化任务分析完成",
|
|
366
|
+
"executing_web_action": "执行操作: {{action}} - {{description}}",
|
|
367
|
+
"executing_step": "执行步骤 {{step}}: {{description}}",
|
|
368
|
+
"operation_cancelled": "操作已取消",
|
|
369
|
+
"element_not_found": "未找到元素: {{element}}",
|
|
370
|
+
"analyzing_results": "分析执行结果...",
|
|
371
|
+
"next_steps_determined": "已确定下一步操作",
|
|
372
|
+
"max_iterations_reached": "已达到最大迭代次数 {{max_iterations}}",
|
|
373
|
+
"action_verification_failed": "操作验证失败: {{action}} - {{reason}}",
|
|
374
|
+
"action_succeeded": "操作成功: {{action}}",
|
|
375
|
+
"replanned_actions": "已重新规划 {{count}} 个操作",
|
|
376
|
+
"web_automation_ask_user": "您的回答: ",
|
|
377
|
+
"filter_mode_normal": "正在使用普通过滤模式处理索引...",
|
|
378
|
+
"filter_mode_big": "索引文件较大 ({{ tokens_len }} tokens),正在使用 big_filter 模式处理...",
|
|
379
|
+
"filter_mode_super_big": "索引文件非常大 ({{ tokens_len }} tokens),正在使用 super_big_filter 模式处理...",
|
|
380
|
+
"super_big_filter_failed": "❌ 超大过滤器失败: {{ error }}.",
|
|
381
|
+
"super_big_filter_stats": "{{ model_names }} 超大过滤器完成耗时 {{ elapsed_time }} 秒,输入token数: {{ input_tokens }}, 输出token数: {{ output_tokens }}, 输入成本: {{ input_cost }}, 输出成本: {{ output_cost }}, 速度: {{ speed }} tokens/秒, 块索引: {{ chunk_index }}",
|
|
382
|
+
"super_big_filter_splitting": "⚠️ 索引文件极其庞大 ({{ tokens_len }}/{{ max_tokens }})。查询将被分成 {{ split_size }} 个部分进行处理。",
|
|
383
|
+
"super_big_filter_title": "{{ model_name }} 正在分析如何过滤极大规模上下文..."
|
|
345
384
|
}}
|
|
346
385
|
|
|
347
386
|
|