jarvis-ai-assistant 0.1.67__py3-none-any.whl → 0.1.72__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.
jarvis/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """Jarvis AI Assistant"""
2
2
 
3
- __version__ = "0.1.67"
3
+ __version__ = "0.1.72"
@@ -18,18 +18,22 @@ class CodeBase:
18
18
  load_env_from_file()
19
19
  self.root_dir = root_dir
20
20
  os.chdir(self.root_dir)
21
- self.thread_count = os.environ.get("JARVIS_THREAD_COUNT") or 10
21
+ self.thread_count = int(os.environ.get("JARVIS_THREAD_COUNT") or 10)
22
22
  self.cheap_platform = os.environ.get("JARVIS_CHEAP_PLATFORM") or os.environ.get("JARVIS_PLATFORM") or "kimi"
23
23
  self.cheap_model = os.environ.get("JARVIS_CHEAP_MODEL") or os.environ.get("JARVIS_MODEL") or "kimi"
24
24
  self.normal_platform = os.environ.get("JARVIS_PLATFORM") or "kimi"
25
+ self.codegen_platform = os.environ.get("JARVIS_CODEGEN_PLATFORM") or os.environ.get("JARVIS_PLATFORM") or "kimi"
26
+ self.codegen_model = os.environ.get("JARVIS_CODEGEN_MODEL") or os.environ.get("JARVIS_MODEL") or "kimi"
25
27
  self.normal_model = os.environ.get("JARVIS_MODEL") or "kimi"
26
28
  self.embedding_model_name = os.environ.get("JARVIS_EMBEDDING_MODEL") or "BAAI/bge-large-zh-v1.5"
27
- if not self.cheap_platform or not self.cheap_model or not self.embedding_model_name or not self.normal_platform or not self.normal_model:
28
- raise ValueError("JARVIS_CHEAP_PLATFORM or JARVIS_CHEAP_MODEL or JARVIS_EMBEDDING_MODEL or JARVIS_PLATFORM or JARVIS_MODEL is not set")
29
+ if not self.cheap_platform or not self.cheap_model or not self.codegen_platform or not self.codegen_model or not self.embedding_model_name or not self.normal_platform or not self.normal_model:
30
+ raise ValueError("JARVIS_CHEAP_PLATFORM or JARVIS_CHEAP_MODEL or JARVIS_CODEGEN_PLATFORM or JARVIS_CODEGEN_MODEL or JARVIS_EMBEDDING_MODEL or JARVIS_PLATFORM or JARVIS_MODEL is not set")
29
31
 
30
32
  PrettyOutput.print(f"廉价模型使用平台: {self.cheap_platform} 模型: {self.cheap_model}", output_type=OutputType.INFO)
33
+ PrettyOutput.print(f"代码生成模型使用平台: {self.codegen_platform} 模型: {self.codegen_model}", output_type=OutputType.INFO)
31
34
  PrettyOutput.print(f"分析模型使用平台: {self.normal_platform} 模型: {self.normal_model}", output_type=OutputType.INFO)
32
35
  PrettyOutput.print(f"嵌入模型: {self.embedding_model_name}", output_type=OutputType.INFO)
36
+ PrettyOutput.print(f"索引建立线程数: {self.thread_count}", output_type=OutputType.INFO)
33
37
  PrettyOutput.print(f"检索算法:分层导航小世界算法", output_type=OutputType.INFO)
34
38
 
35
39
  # 初始化数据目录
@@ -39,6 +43,7 @@ class CodeBase:
39
43
 
40
44
  # 初始化嵌入模型,使用系统默认缓存目录
41
45
  try:
46
+ os.environ["TOKENIZERS_PARALLELISM"] = "false"
42
47
  PrettyOutput.print("正在加载/下载模型,请稍候...", output_type=OutputType.INFO)
43
48
  self.embedding_model = SentenceTransformer(self.embedding_model_name)
44
49
 
@@ -327,7 +332,67 @@ class CodeBase:
327
332
 
328
333
  PrettyOutput.print(f"成功为 {len(processed_files)} 个文件生成索引", output_type=OutputType.INFO)
329
334
 
330
- def search_similar(self, query: str, top_k: int = 5) -> List[Tuple[str, float, str]]:
335
+ def rerank_results(self, query: str, initial_results: List[Tuple[str, float, str]]) -> List[Tuple[str, float, str]]:
336
+ """使用大模型对搜索结果重新排序"""
337
+ if not initial_results:
338
+ return []
339
+
340
+ model = self.platform_registry.create_platform(self.normal_platform)
341
+ model.set_model_name(self.normal_model)
342
+ model.set_suppress_output(True)
343
+
344
+ try:
345
+ # 构建重排序的prompt
346
+ prompt = f"""请根据用户的查询,对以下代码文件进行相关性排序。对每个文件给出0-100的相关性分数,分数越高表示越相关。
347
+ 只需要输出每个文件的分数,格式为:
348
+ <RERANK_START>
349
+ 文件路径: 分数
350
+ 文件路径: 分数
351
+ <RERANK_END>
352
+
353
+ 用户查询: {query}
354
+
355
+ 待评估文件:
356
+ """
357
+ for path, _, desc in initial_results:
358
+ prompt += f"""
359
+ 文件: {path}
360
+ 描述: {desc}
361
+ ---
362
+ """
363
+
364
+ response = model.chat(prompt)
365
+
366
+ # 提取<RERANK_START>和<RERANK_END>之间的内容
367
+ start_tag = "<RERANK_START>"
368
+ end_tag = "<RERANK_END>"
369
+ if start_tag in response and end_tag in response:
370
+ response = response[response.find(start_tag) + len(start_tag):response.find(end_tag)]
371
+
372
+ # 解析响应,提取文件路径和分数
373
+ scored_results = []
374
+ for line in response.split('\n'):
375
+ if ':' not in line:
376
+ continue
377
+ try:
378
+ file_path, score_str = line.split(':', 1)
379
+ file_path = file_path.strip()
380
+ score = float(score_str.strip())
381
+ # 找到对应的原始描述
382
+ desc = next((desc for p, _, desc in initial_results if p == file_path), "")
383
+ scored_results.append((file_path, score/100.0, desc))
384
+ except:
385
+ continue
386
+
387
+ # 按分数降序排序
388
+ return sorted(scored_results, key=lambda x: x[1], reverse=True)
389
+
390
+ finally:
391
+ model.delete_chat()
392
+
393
+ return initial_results
394
+
395
+ def search_similar(self, query: str, top_k: int = 20) -> List[Tuple[str, float, str]]:
331
396
  """搜索相似文件"""
332
397
  model = self.platform_registry.create_platform(self.normal_platform)
333
398
  model.set_model_name(self.normal_model)
@@ -357,7 +422,7 @@ class CodeBase:
357
422
 
358
423
  PrettyOutput.print(f"查询 {query} 的结果: ", output_type=OutputType.INFO)
359
424
 
360
- ret = []
425
+ initial_results = []
361
426
 
362
427
  for i, distance in zip(indices[0], distances[0]):
363
428
  if i == -1: # faiss返回-1表示无效结果
@@ -369,13 +434,18 @@ class CodeBase:
369
434
 
370
435
  file_path = self.file_paths[i]
371
436
  data = self.vector_cache[file_path]
372
- ret.append((file_path, similarity, data["description"]))
373
- return ret
437
+ initial_results.append((file_path, similarity, data["description"]))
438
+
439
+ # 使用大模型重新排序
440
+ PrettyOutput.print("使用大模型重新排序...", output_type=OutputType.INFO)
441
+ reranked_results = self.rerank_results(query, initial_results)
442
+
443
+ return reranked_results
374
444
 
375
- def ask_codebase(self, query: str, top_k: int = 5) -> List[Tuple[str, float, str]]:
445
+ def ask_codebase(self, query: str, top_k: int=20) -> str:
376
446
  """查询代码库"""
377
447
  results = self.search_similar(query, top_k)
378
- PrettyOutput.print(f"找到的关联文件: ", output_type=OutputType.INFO)
448
+ PrettyOutput.print(f"找到的关联文件: ", output_type=OutputType.SUCCESS)
379
449
  for path, score, _ in results:
380
450
  PrettyOutput.print(f"文件: {path} 关联度: {score:.3f}",
381
451
  output_type=OutputType.INFO)
@@ -384,9 +454,12 @@ class CodeBase:
384
454
  """
385
455
  for path, _, _ in results:
386
456
  try:
457
+ if len(prompt) > 30 * 1024:
458
+ PrettyOutput.print(f"避免上下文超限,丢弃低相关度文件:{path}", OutputType.WARNING)
459
+ continue
387
460
  content = open(path, "r", encoding="utf-8").read()
388
461
  prompt += f"""
389
- 文件路径: {path}
462
+ 文件路径: {path}prompt
390
463
  文件内容:
391
464
  {content}
392
465
  ========================================
@@ -401,8 +474,8 @@ class CodeBase:
401
474
 
402
475
  请用专业的语言回答用户的问题,如果给出的文件内容不足以回答用户的问题,请告诉用户,绝对不要胡编乱造。
403
476
  """
404
- model = self.platform_registry.create_platform(self.normal_platform)
405
- model.set_model_name(self.normal_model)
477
+ model = self.platform_registry.create_platform(self.codegen_platform)
478
+ model.set_model_name(self.codegen_model)
406
479
  try:
407
480
  response = model.chat(prompt)
408
481
  return response
@@ -413,7 +486,7 @@ class CodeBase:
413
486
  def main():
414
487
  parser = argparse.ArgumentParser(description='Codebase management and search tool')
415
488
  parser.add_argument('--search', type=str, help='Search query to find similar code files')
416
- parser.add_argument('--top-k', type=int, default=5, help='Number of results to return (default: 5)')
489
+ parser.add_argument('--top-k', type=int, default=20, help='Number of results to return (default: 20)')
417
490
  parser.add_argument('--ask', type=str, help='Ask a question about the codebase')
418
491
  args = parser.parse_args()
419
492
 
File without changes
@@ -124,7 +124,7 @@ class JarvisCoder:
124
124
  return [patch.replace('<PATCH_START>', '').replace('<PATCH_END>', '').strip()
125
125
  for patch in patches if patch.strip()]
126
126
  except Exception as e:
127
- PrettyOutput.print(f"解析patch失败: {str(e)}", OutputType.ERROR)
127
+ PrettyOutput.print(f"解析patch失败: {str(e)}", OutputType.WARNING)
128
128
  return []
129
129
 
130
130
  def _make_patch(self, related_files: List[Dict], feature: str) -> List[str]:
@@ -138,20 +138,31 @@ class JarvisCoder:
138
138
  要替换的内容
139
139
  =======
140
140
  新的内容
141
- <<<<<<
141
+ >>>>>>
142
142
  <PATCH_END>
143
143
 
144
- 2. 如果是新文件,格式如下:
144
+ 2. 如果是新文件或者替换整个文件内容,格式如下:
145
145
  <PATCH_START>
146
146
  >>>>>> path/to/new/file
147
147
  =======
148
148
  新文件的完整内容
149
- <<<<<<
149
+ >>>>>>
150
+ <PATCH_END>
151
+
152
+ 3. 如果要删除文件中的某一段,格式如下:
153
+ <PATCH_START>
154
+ >>>>>> path/to/file
155
+ 要删除的内容
156
+ =======
157
+ >>>>>>
150
158
  <PATCH_END>
151
159
 
152
160
  文件列表如下:
153
161
  """
154
162
  for i, file in enumerate(related_files):
163
+ if len(prompt) > 30 * 1024:
164
+ PrettyOutput.print(f'避免上下文超限,丢弃低相关度文件:{file["file_path"]}', OutputType.WARNING)
165
+ continue
155
166
  prompt += f"""{i}. {file["file_path"]}\n"""
156
167
  prompt += f"""文件内容:\n"""
157
168
  prompt += f"<FILE_CONTENT_START>\n"
@@ -177,7 +188,7 @@ class JarvisCoder:
177
188
  return [patch.replace('<PATCH_START>', '').replace('<PATCH_END>', '').strip()
178
189
  for patch in patches if patch.strip()]
179
190
  except Exception as e:
180
- PrettyOutput.print(f"解析patch失败: {str(e)}", OutputType.ERROR)
191
+ PrettyOutput.print(f"解析patch失败: {str(e)}", OutputType.WARNING)
181
192
  return []
182
193
 
183
194
  def _apply_patch(self, related_files: List[Dict], patches: List[str]) -> Tuple[bool, str]:
@@ -216,7 +227,7 @@ class JarvisCoder:
216
227
  return False, "\n".join(error_info)
217
228
 
218
229
  old_content = parts[0]
219
- new_content = parts[1].split("<<<<<<")[0]
230
+ new_content = parts[1].split(">>>>>>")[0]
220
231
 
221
232
  # 处理新文件
222
233
  if not old_content:
@@ -305,9 +316,9 @@ class JarvisCoder:
305
316
  def _load_related_files(self, feature: str) -> List[Dict]:
306
317
  """加载相关文件内容"""
307
318
  ret = []
308
- related_files = self._codebase.search_similar(feature, top_k=5)
319
+ related_files = self._codebase.search_similar(feature)
309
320
  for file, score, _ in related_files:
310
- PrettyOutput.print(f"相关文件: {file} 相关度: {score:.3f}", OutputType.INFO)
321
+ PrettyOutput.print(f"相关文件: {file} 相关度: {score:.3f}", OutputType.SUCCESS)
311
322
  with open(file, "r", encoding="utf-8") as f:
312
323
  content = f.read()
313
324
  ret.append({"file_path": file, "file_content": content})
@@ -438,7 +449,7 @@ def main():
438
449
  PrettyOutput.print(result["stdout"], OutputType.SUCCESS)
439
450
  else:
440
451
  if result["stderr"]:
441
- PrettyOutput.print(result["stderr"], OutputType.ERROR)
452
+ PrettyOutput.print(result["stderr"], OutputType.WARNING)
442
453
  if result["error"]:
443
454
  PrettyOutput.print(f"错误类型: {type(result['error']).__name__}", OutputType.WARNING)
444
455
 
jarvis/models/registry.py CHANGED
@@ -121,7 +121,7 @@ class PlatformRegistry:
121
121
  # 检查平台实现
122
122
  if not PlatformRegistry.check_platform_implementation(obj):
123
123
  continue
124
-
124
+ PrettyOutput.print(f"从 {os.path.join(directory, filename)} 加载平台:{obj.platform_name}", OutputType.SUCCESS)
125
125
  platforms[obj.platform_name] = obj
126
126
  break
127
127
  except Exception as e:
jarvis/tools/registry.py CHANGED
@@ -99,7 +99,7 @@ class ToolRegistry:
99
99
  parameters=tool_instance.parameters,
100
100
  func=tool_instance.execute
101
101
  )
102
- PrettyOutput.print(f"从 {file_path} 加载工具: {tool_instance.name}: {tool_instance.description}", OutputType.INFO)
102
+ PrettyOutput.print(f"从 {file_path} 加载工具: {tool_instance.name}: {tool_instance.description}", OutputType.SUCCESS)
103
103
  tool_found = True
104
104
  break
105
105
 
jarvis/utils.py CHANGED
@@ -158,7 +158,7 @@ def get_multiline_input(tip: str) -> str:
158
158
  lines.append(line)
159
159
 
160
160
  except KeyboardInterrupt:
161
- PrettyOutput.print("\n输入已取消", OutputType.ERROR)
161
+ PrettyOutput.print("\n输入已取消", OutputType.INFO)
162
162
  return "__interrupt__"
163
163
 
164
164
  return "\n".join(lines)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.67
3
+ Version: 0.1.72
4
4
  Summary: Jarvis: An AI assistant that uses tools to interact with the system
5
5
  Home-page: https://github.com/skyfireitdiy/Jarvis
6
6
  Author: skyfire
@@ -44,9 +44,10 @@ Requires-Dist: colorama>=0.4.6
44
44
  Requires-Dist: prompt_toolkit>=3.0.0
45
45
  Requires-Dist: openai>=1.20.0
46
46
  Requires-Dist: playwright>=1.41.1
47
- Requires-Dist: numpy>=1.26.0
48
- Requires-Dist: faiss-cpu>=1.8.1
47
+ Requires-Dist: numpy>=1.24.0
48
+ Requires-Dist: faiss-cpu>=1.8.0
49
49
  Requires-Dist: sentence-transformers>=2.2.2
50
+ Requires-Dist: bs4>=0.0.1
50
51
  Provides-Extra: dev
51
52
  Requires-Dist: pytest; extra == "dev"
52
53
  Requires-Dist: black; extra == "dev"
@@ -1,17 +1,18 @@
1
- jarvis/__init__.py,sha256=YEUpLs5Xl5YrTW6S6tl7I42rz6TcpyCTJZRczXXMmi0,50
1
+ jarvis/__init__.py,sha256=MyFCehMdftT6QiIVeyWoT3cnA4reDk6ObCHGRDEr7JY,50
2
2
  jarvis/agent.py,sha256=kl6pwNrluzb-9eZKgwmsk5Jh4CpWi4F8B3RvEQNvc5U,14921
3
3
  jarvis/main.py,sha256=7EcSlxa5JFFXBujzKDWdNtwX6axLhFFdJMc2GxTjfdk,6295
4
- jarvis/utils.py,sha256=bjC0PAR58RvcXHgabIFmNmYL1L_GhhiEwMFytWurcN4,7499
4
+ jarvis/utils.py,sha256=vZV8sHj0ggZy4Rb8RxIujQhRWgeNEomhqVl4WXmpq7c,7498
5
5
  jarvis/jarvis_codebase/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- jarvis/jarvis_codebase/main.py,sha256=LdJGg4dUaK8naNkGoqF9i53OaYndKGs3jXfZQd4w-3M,18699
7
- jarvis/jarvis_coder/main.py,sha256=L_i1Zp3UJbc891WrpxKgoD4EzoqvLRnqznmLQP2ZN2U,21721
6
+ jarvis/jarvis_codebase/main.py,sha256=A-KY9WzAIsCF0QPndm4b8-rAKEz4nLlm4NkfUMpnQUM,21965
7
+ jarvis/jarvis_coder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ jarvis/jarvis_coder/main.py,sha256=uQ7aQ3hmnxecacjLSBOV0rSLkacExGLgQRc9zD1ar1E,22085
8
9
  jarvis/models/__init__.py,sha256=mrOt67nselz_H1gX9wdAO4y2DY5WPXzABqJbr5Des8k,63
9
10
  jarvis/models/ai8.py,sha256=vgy-r_3HHxGMAalZrA65VWHC1PuwBTYgtprSgHkCbrk,12557
10
11
  jarvis/models/base.py,sha256=ShV1H8Unee4RMaiFO4idROQA0Hc6wu4dyeRPX5fcszk,1433
11
12
  jarvis/models/kimi.py,sha256=1iTB0Z_WOmCML3Ufsge6jmeKOYvccr7I5lS3JUXymU4,17611
12
13
  jarvis/models/openai.py,sha256=ayaBWAN5VexMcKVrjEPDNB-Q9wx0sCV9Z4BCrvwYJ9w,4315
13
14
  jarvis/models/oyi.py,sha256=X2c5SWDIuQDCCFBcEKbzIWEz3I34eOAi0d1XAFgxlpw,15001
14
- jarvis/models/registry.py,sha256=hJyaROiOF_TkbtIXsjOD8-ArOvAvtxviawyqBFfLV6s,7617
15
+ jarvis/models/registry.py,sha256=YpooKSpk5pSWfb5cBDz5wRfPK-abb9uuUZr4WBejqwI,7762
15
16
  jarvis/tools/__init__.py,sha256=7Rqyj5hBAv5cWDVr5T9ZTZASO7ssBHeQNm2_4ZARdkA,72
16
17
  jarvis/tools/base.py,sha256=EGRGbdfbLXDLwtyoWdvp9rlxNX7bzc20t0Vc2VkwIEY,652
17
18
  jarvis/tools/codebase_qa.py,sha256=AEpusYxyWtALVVwPk1DMUH9cVI73mE1e3WFHJXDpXto,2333
@@ -19,14 +20,14 @@ jarvis/tools/coder.py,sha256=ZJfPInKms4Hj3-eQlBwamVsvZ-2nlZ-4jsqJ-tJc6mg,2040
19
20
  jarvis/tools/file_ops.py,sha256=h8g0eT9UvlJf4kt0DLXvdSsjcPj7x19lxWdDApeDfpg,3842
20
21
  jarvis/tools/generator.py,sha256=vVP3eN5cCDpRXf_fn0skETkPXAW1XZFWx9pt2_ahK48,5999
21
22
  jarvis/tools/methodology.py,sha256=UG6s5VYRcd9wrKX4cg6f7zJhet5AIcthFGMOAdevBiw,5175
22
- jarvis/tools/registry.py,sha256=mlOAmUq3yzRz-7yvwrrCwbe5Lmw8eh1v8-_Fa5sezwI,7209
23
+ jarvis/tools/registry.py,sha256=MeTYNdZNRdhlgABviVxzbDPSgLpwDp2Nx2dGzedRu8U,7212
23
24
  jarvis/tools/search.py,sha256=1EqOVvLhg2Csh-i03-XeCrusbyfmH69FZ8khwZt8Tow,6131
24
25
  jarvis/tools/shell.py,sha256=UPKshPyOaUwTngresUw-ot1jHjQIb4wCY5nkJqa38lU,2520
25
26
  jarvis/tools/sub_agent.py,sha256=rEtAmSVY2ZjFOZEKr5m5wpACOQIiM9Zr_3dT92FhXYU,2621
26
27
  jarvis/tools/webpage.py,sha256=d3w3Jcjcu1ESciezTkz3n3Zf-rp_l91PrVoDEZnckOo,2391
27
- jarvis_ai_assistant-0.1.67.dist-info/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
28
- jarvis_ai_assistant-0.1.67.dist-info/METADATA,sha256=Vpf669oYa2bpkQDzfAsgSP0bv0geylGiyuPq6ezarJY,12373
29
- jarvis_ai_assistant-0.1.67.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
30
- jarvis_ai_assistant-0.1.67.dist-info/entry_points.txt,sha256=QNUeqmUJd7nHufel2FO7cRttS1uKFfnbIyObv8eVyOY,140
31
- jarvis_ai_assistant-0.1.67.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
32
- jarvis_ai_assistant-0.1.67.dist-info/RECORD,,
28
+ jarvis_ai_assistant-0.1.72.dist-info/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
29
+ jarvis_ai_assistant-0.1.72.dist-info/METADATA,sha256=4YOsbaLCJw40e43wAL34myfveTRLOmC-MIpBrkrt2zs,12399
30
+ jarvis_ai_assistant-0.1.72.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
31
+ jarvis_ai_assistant-0.1.72.dist-info/entry_points.txt,sha256=QNUeqmUJd7nHufel2FO7cRttS1uKFfnbIyObv8eVyOY,140
32
+ jarvis_ai_assistant-0.1.72.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
33
+ jarvis_ai_assistant-0.1.72.dist-info/RECORD,,