jarvis-ai-assistant 0.1.134__py3-none-any.whl → 0.1.138__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 jarvis-ai-assistant might be problematic. Click here for more details.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +201 -79
- jarvis/jarvis_agent/builtin_input_handler.py +16 -6
- jarvis/jarvis_agent/file_input_handler.py +9 -9
- jarvis/jarvis_agent/jarvis.py +10 -10
- jarvis/jarvis_agent/main.py +12 -11
- jarvis/jarvis_agent/output_handler.py +3 -3
- jarvis/jarvis_agent/patch.py +86 -62
- jarvis/jarvis_agent/shell_input_handler.py +5 -3
- jarvis/jarvis_code_agent/code_agent.py +134 -99
- jarvis/jarvis_code_agent/file_select.py +24 -24
- jarvis/jarvis_dev/main.py +45 -51
- jarvis/jarvis_git_details/__init__.py +0 -0
- jarvis/jarvis_git_details/main.py +179 -0
- jarvis/jarvis_git_squash/main.py +7 -7
- jarvis/jarvis_lsp/base.py +11 -11
- jarvis/jarvis_lsp/cpp.py +14 -14
- jarvis/jarvis_lsp/go.py +13 -13
- jarvis/jarvis_lsp/python.py +8 -8
- jarvis/jarvis_lsp/registry.py +21 -21
- jarvis/jarvis_lsp/rust.py +15 -15
- jarvis/jarvis_methodology/main.py +101 -0
- jarvis/jarvis_multi_agent/__init__.py +11 -11
- jarvis/jarvis_multi_agent/main.py +6 -6
- jarvis/jarvis_platform/__init__.py +1 -1
- jarvis/jarvis_platform/ai8.py +67 -89
- jarvis/jarvis_platform/base.py +14 -13
- jarvis/jarvis_platform/kimi.py +25 -28
- jarvis/jarvis_platform/ollama.py +24 -26
- jarvis/jarvis_platform/openai.py +15 -19
- jarvis/jarvis_platform/oyi.py +48 -50
- jarvis/jarvis_platform/registry.py +27 -28
- jarvis/jarvis_platform/yuanbao.py +38 -42
- jarvis/jarvis_platform_manager/main.py +81 -81
- jarvis/jarvis_platform_manager/openai_test.py +21 -21
- jarvis/jarvis_rag/file_processors.py +18 -18
- jarvis/jarvis_rag/main.py +261 -277
- jarvis/jarvis_smart_shell/main.py +12 -12
- jarvis/jarvis_tools/ask_codebase.py +28 -28
- jarvis/jarvis_tools/ask_user.py +8 -8
- jarvis/jarvis_tools/base.py +4 -4
- jarvis/jarvis_tools/chdir.py +9 -9
- jarvis/jarvis_tools/code_review.py +19 -19
- jarvis/jarvis_tools/create_code_agent.py +15 -15
- jarvis/jarvis_tools/execute_python_script.py +3 -3
- jarvis/jarvis_tools/execute_shell.py +11 -11
- jarvis/jarvis_tools/execute_shell_script.py +3 -3
- jarvis/jarvis_tools/file_analyzer.py +29 -29
- jarvis/jarvis_tools/file_operation.py +22 -20
- jarvis/jarvis_tools/find_caller.py +25 -25
- jarvis/jarvis_tools/find_methodolopy.py +65 -0
- jarvis/jarvis_tools/find_symbol.py +24 -24
- jarvis/jarvis_tools/function_analyzer.py +27 -27
- jarvis/jarvis_tools/git_commiter.py +9 -9
- jarvis/jarvis_tools/lsp_get_diagnostics.py +19 -19
- jarvis/jarvis_tools/methodology.py +23 -62
- jarvis/jarvis_tools/project_analyzer.py +29 -33
- jarvis/jarvis_tools/rag.py +15 -15
- jarvis/jarvis_tools/read_code.py +24 -22
- jarvis/jarvis_tools/read_webpage.py +31 -31
- jarvis/jarvis_tools/registry.py +72 -52
- jarvis/jarvis_tools/tool_generator.py +18 -18
- jarvis/jarvis_utils/config.py +23 -23
- jarvis/jarvis_utils/embedding.py +83 -83
- jarvis/jarvis_utils/git_utils.py +20 -20
- jarvis/jarvis_utils/globals.py +18 -6
- jarvis/jarvis_utils/input.py +10 -9
- jarvis/jarvis_utils/methodology.py +140 -136
- jarvis/jarvis_utils/output.py +11 -11
- jarvis/jarvis_utils/utils.py +22 -70
- {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/METADATA +1 -1
- jarvis_ai_assistant-0.1.138.dist-info/RECORD +85 -0
- {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/entry_points.txt +2 -0
- jarvis/jarvis_tools/select_code_files.py +0 -62
- jarvis_ai_assistant-0.1.134.dist-info/RECORD +0 -82
- {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/top_level.txt +0 -0
|
@@ -26,7 +26,7 @@ _methodology_index_cache: Optional[Tuple[faiss.IndexIDMap, List[Dict[str, str]],
|
|
|
26
26
|
def _get_cache_directory() -> str:
|
|
27
27
|
"""
|
|
28
28
|
获取缓存目录路径,如果不存在则创建
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
返回:
|
|
31
31
|
str: 缓存目录的路径
|
|
32
32
|
"""
|
|
@@ -41,7 +41,7 @@ def _get_cache_directory() -> str:
|
|
|
41
41
|
def _get_embeddings_cache_path() -> str:
|
|
42
42
|
"""
|
|
43
43
|
获取嵌入向量缓存文件的路径
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
返回:
|
|
46
46
|
str: 嵌入向量缓存文件的路径
|
|
47
47
|
"""
|
|
@@ -50,7 +50,7 @@ def _get_embeddings_cache_path() -> str:
|
|
|
50
50
|
def _get_index_cache_path() -> str:
|
|
51
51
|
"""
|
|
52
52
|
获取索引缓存文件的路径
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
返回:
|
|
55
55
|
str: 索引缓存文件的路径
|
|
56
56
|
"""
|
|
@@ -59,7 +59,7 @@ def _get_index_cache_path() -> str:
|
|
|
59
59
|
def _get_index_metadata_path() -> str:
|
|
60
60
|
"""
|
|
61
61
|
获取索引元数据文件的路径
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
返回:
|
|
64
64
|
str: 索引元数据文件的路径
|
|
65
65
|
"""
|
|
@@ -68,14 +68,14 @@ def _get_index_metadata_path() -> str:
|
|
|
68
68
|
def _load_embeddings_cache() -> Dict[int, np.ndarray]:
|
|
69
69
|
"""
|
|
70
70
|
从文件系统加载嵌入向量缓存
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
返回:
|
|
73
73
|
Dict[int, np.ndarray]: 嵌入向量缓存字典
|
|
74
74
|
"""
|
|
75
75
|
cache_path = _get_embeddings_cache_path()
|
|
76
76
|
if not os.path.exists(cache_path):
|
|
77
77
|
return {}
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
try:
|
|
80
80
|
with open(cache_path, "rb") as f:
|
|
81
81
|
embeddings_cache = pickle.load(f)
|
|
@@ -86,18 +86,18 @@ def _load_embeddings_cache() -> Dict[int, np.ndarray]:
|
|
|
86
86
|
def _save_embeddings_cache(cache: Dict[int, np.ndarray]) -> bool:
|
|
87
87
|
"""
|
|
88
88
|
将嵌入向量缓存保存到文件系统
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
参数:
|
|
91
91
|
cache: 要保存的嵌入向量缓存字典
|
|
92
|
-
|
|
92
|
+
|
|
93
93
|
返回:
|
|
94
94
|
bool: 保存是否成功
|
|
95
95
|
"""
|
|
96
96
|
if not cache:
|
|
97
97
|
return False
|
|
98
|
-
|
|
98
|
+
|
|
99
99
|
cache_path = _get_embeddings_cache_path()
|
|
100
|
-
|
|
100
|
+
|
|
101
101
|
try:
|
|
102
102
|
with open(cache_path, "wb") as f:
|
|
103
103
|
pickle.dump(cache, f)
|
|
@@ -109,62 +109,62 @@ def _save_embeddings_cache(cache: Dict[int, np.ndarray]) -> bool:
|
|
|
109
109
|
def _load_index_cache() -> Optional[Tuple[faiss.IndexIDMap, List[Dict[str, str]], str]]:
|
|
110
110
|
"""
|
|
111
111
|
从文件系统加载索引缓存
|
|
112
|
-
|
|
112
|
+
|
|
113
113
|
返回:
|
|
114
114
|
Optional[Tuple[faiss.IndexIDMap, List[Dict[str, str]], str]]: 索引缓存元组
|
|
115
115
|
"""
|
|
116
116
|
index_path = _get_index_cache_path()
|
|
117
117
|
metadata_path = _get_index_metadata_path()
|
|
118
|
-
|
|
118
|
+
|
|
119
119
|
if not os.path.exists(index_path) or not os.path.exists(metadata_path):
|
|
120
120
|
return None
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
try:
|
|
123
123
|
# 加载索引
|
|
124
124
|
index = faiss.read_index(index_path)
|
|
125
|
-
|
|
125
|
+
|
|
126
126
|
# 加载元数据
|
|
127
127
|
with open(metadata_path, "rb") as f:
|
|
128
128
|
metadata = pickle.load(f)
|
|
129
|
-
|
|
129
|
+
|
|
130
130
|
methodology_data = metadata.get("methodology_data", [])
|
|
131
131
|
methodology_hash = metadata.get("methodology_hash", "")
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
if isinstance(index, faiss.IndexIDMap) and methodology_data and methodology_hash:
|
|
134
134
|
return index, methodology_data, methodology_hash
|
|
135
135
|
except Exception as e:
|
|
136
136
|
PrettyOutput.print(f"加载索引缓存失败: {str(e)}", OutputType.WARNING)
|
|
137
|
-
|
|
137
|
+
|
|
138
138
|
return None
|
|
139
139
|
|
|
140
140
|
def _save_index_cache(index: faiss.IndexIDMap, methodology_data: List[Dict[str, str]], methodology_hash: str) -> bool:
|
|
141
141
|
"""
|
|
142
142
|
将索引缓存保存到文件系统
|
|
143
|
-
|
|
143
|
+
|
|
144
144
|
参数:
|
|
145
145
|
index: FAISS索引
|
|
146
146
|
methodology_data: 方法论数据列表
|
|
147
147
|
methodology_hash: 方法论文件哈希值
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
返回:
|
|
150
150
|
bool: 保存是否成功
|
|
151
151
|
"""
|
|
152
152
|
index_path = _get_index_cache_path()
|
|
153
153
|
metadata_path = _get_index_metadata_path()
|
|
154
|
-
|
|
154
|
+
|
|
155
155
|
try:
|
|
156
156
|
# 保存索引
|
|
157
157
|
faiss.write_index(index, index_path)
|
|
158
|
-
|
|
158
|
+
|
|
159
159
|
# 保存元数据
|
|
160
160
|
metadata = {
|
|
161
161
|
"methodology_data": methodology_data,
|
|
162
162
|
"methodology_hash": methodology_hash
|
|
163
163
|
}
|
|
164
|
-
|
|
164
|
+
|
|
165
165
|
with open(metadata_path, "wb") as f:
|
|
166
166
|
pickle.dump(metadata, f)
|
|
167
|
-
|
|
167
|
+
|
|
168
168
|
return True
|
|
169
169
|
except Exception as e:
|
|
170
170
|
PrettyOutput.print(f"保存索引缓存失败: {str(e)}", OutputType.WARNING)
|
|
@@ -173,11 +173,11 @@ def _save_index_cache(index: faiss.IndexIDMap, methodology_data: List[Dict[str,
|
|
|
173
173
|
def _create_methodology_embedding(embedding_model: Any, methodology_text: str) -> np.ndarray:
|
|
174
174
|
"""
|
|
175
175
|
为方法论文本创建嵌入向量。
|
|
176
|
-
|
|
176
|
+
|
|
177
177
|
参数:
|
|
178
178
|
embedding_model: 使用的嵌入模型
|
|
179
179
|
methodology_text: 要创建嵌入的文本
|
|
180
|
-
|
|
180
|
+
|
|
181
181
|
返回:
|
|
182
182
|
np.ndarray: 嵌入向量
|
|
183
183
|
"""
|
|
@@ -186,21 +186,21 @@ def _create_methodology_embedding(embedding_model: Any, methodology_text: str) -
|
|
|
186
186
|
cache_key = hash(methodology_text)
|
|
187
187
|
if cache_key in _methodology_embeddings_cache:
|
|
188
188
|
return _methodology_embeddings_cache[cache_key]
|
|
189
|
-
|
|
189
|
+
|
|
190
190
|
# 截断长文本
|
|
191
191
|
max_length = 512
|
|
192
192
|
text = ' '.join(methodology_text.split()[:max_length])
|
|
193
|
-
|
|
193
|
+
|
|
194
194
|
# 使用sentence_transformers模型获取嵌入向量
|
|
195
|
-
embedding = embedding_model.encode([text],
|
|
195
|
+
embedding = embedding_model.encode([text],
|
|
196
196
|
convert_to_tensor=True,
|
|
197
197
|
normalize_embeddings=True)
|
|
198
198
|
vector = np.array(embedding.cpu().numpy(), dtype=np.float32)
|
|
199
199
|
result = vector[0] # 返回第一个向量,因为我们只编码了一个文本
|
|
200
|
-
|
|
200
|
+
|
|
201
201
|
# 缓存嵌入向量以便后续使用
|
|
202
202
|
_methodology_embeddings_cache[cache_key] = result
|
|
203
|
-
|
|
203
|
+
|
|
204
204
|
return result
|
|
205
205
|
except Exception as e:
|
|
206
206
|
PrettyOutput.print(f"创建方法论嵌入向量失败: {str(e)}", OutputType.ERROR)
|
|
@@ -209,14 +209,14 @@ def _create_methodology_embedding(embedding_model: Any, methodology_text: str) -
|
|
|
209
209
|
def make_methodology_prompt(data: Dict[str, str]) -> str:
|
|
210
210
|
"""
|
|
211
211
|
从方法论数据生成格式化提示
|
|
212
|
-
|
|
212
|
+
|
|
213
213
|
参数:
|
|
214
214
|
data: 方法论数据字典
|
|
215
|
-
|
|
215
|
+
|
|
216
216
|
返回:
|
|
217
217
|
str: 格式化后的提示字符串
|
|
218
218
|
"""
|
|
219
|
-
ret = """这是处理以往问题的标准方法论,如果当前任务类似,可以参考使用,如果不相关,请忽略:\n"""
|
|
219
|
+
ret = """这是处理以往问题的标准方法论,如果当前任务类似,可以参考使用,如果不相关,请忽略:\n"""
|
|
220
220
|
for key, value in data.items():
|
|
221
221
|
ret += f"问题: {key}\n方法论: {value}\n"
|
|
222
222
|
return ret
|
|
@@ -224,7 +224,7 @@ def make_methodology_prompt(data: Dict[str, str]) -> str:
|
|
|
224
224
|
def _get_methodology_directory() -> str:
|
|
225
225
|
"""
|
|
226
226
|
获取方法论目录路径,如果不存在则创建
|
|
227
|
-
|
|
227
|
+
|
|
228
228
|
返回:
|
|
229
229
|
str: 方法论目录的路径
|
|
230
230
|
"""
|
|
@@ -239,46 +239,46 @@ def _get_methodology_directory() -> str:
|
|
|
239
239
|
def _get_methodology_files_hash() -> str:
|
|
240
240
|
"""
|
|
241
241
|
计算所有方法论文件的组合哈希值,用于检测文件变化
|
|
242
|
-
|
|
242
|
+
|
|
243
243
|
返回:
|
|
244
244
|
str: 所有方法论文件的组合哈希值
|
|
245
245
|
"""
|
|
246
246
|
methodology_dir = _get_methodology_directory()
|
|
247
247
|
if not os.path.exists(methodology_dir):
|
|
248
248
|
return ""
|
|
249
|
-
|
|
249
|
+
|
|
250
250
|
# 获取所有方法论文件的路径和修改时间
|
|
251
251
|
files_data = []
|
|
252
252
|
for filepath in glob.glob(os.path.join(methodology_dir, "*.json")):
|
|
253
253
|
mtime = os.path.getmtime(filepath)
|
|
254
254
|
files_data.append((filepath, mtime))
|
|
255
|
-
|
|
255
|
+
|
|
256
256
|
# 按路径排序,保证哈希值的一致性
|
|
257
257
|
files_data.sort(key=lambda x: x[0])
|
|
258
|
-
|
|
258
|
+
|
|
259
259
|
# 计算组合哈希值
|
|
260
260
|
if not files_data:
|
|
261
261
|
return ""
|
|
262
|
-
|
|
262
|
+
|
|
263
263
|
hasher = hashlib.md5()
|
|
264
264
|
for filepath, mtime in files_data:
|
|
265
265
|
hasher.update(f"{filepath}:{mtime}".encode("utf-8"))
|
|
266
|
-
|
|
266
|
+
|
|
267
267
|
return hasher.hexdigest()
|
|
268
268
|
|
|
269
269
|
def _load_all_methodologies() -> Dict[str, str]:
|
|
270
270
|
"""
|
|
271
271
|
加载所有方法论文件
|
|
272
|
-
|
|
272
|
+
|
|
273
273
|
返回:
|
|
274
274
|
Dict[str, str]: 方法论字典,键为问题类型,值为方法论内容
|
|
275
275
|
"""
|
|
276
276
|
methodology_dir = _get_methodology_directory()
|
|
277
277
|
all_methodologies = {}
|
|
278
|
-
|
|
278
|
+
|
|
279
279
|
if not os.path.exists(methodology_dir):
|
|
280
280
|
return all_methodologies
|
|
281
|
-
|
|
281
|
+
|
|
282
282
|
for filepath in glob.glob(os.path.join(methodology_dir, "*.json")):
|
|
283
283
|
try:
|
|
284
284
|
with open(filepath, "r", encoding="utf-8", errors="ignore") as f:
|
|
@@ -290,7 +290,7 @@ def _load_all_methodologies() -> Dict[str, str]:
|
|
|
290
290
|
except Exception as e:
|
|
291
291
|
filename = os.path.basename(filepath)
|
|
292
292
|
PrettyOutput.print(f"加载方法论文件 {filename} 失败: {str(e)}", OutputType.WARNING)
|
|
293
|
-
|
|
293
|
+
|
|
294
294
|
return all_methodologies
|
|
295
295
|
|
|
296
296
|
def _migrate_from_old_format():
|
|
@@ -300,34 +300,34 @@ def _migrate_from_old_format():
|
|
|
300
300
|
old_format_file = os.path.expanduser("~/.jarvis/methodology")
|
|
301
301
|
if not os.path.exists(old_format_file):
|
|
302
302
|
return
|
|
303
|
-
|
|
303
|
+
|
|
304
304
|
try:
|
|
305
305
|
# 加载旧格式文件
|
|
306
306
|
with open(old_format_file, "r", encoding="utf-8", errors="ignore") as f:
|
|
307
307
|
old_data = yaml.safe_load(f) or {}
|
|
308
|
-
|
|
308
|
+
|
|
309
309
|
if not old_data:
|
|
310
310
|
return
|
|
311
|
-
|
|
311
|
+
|
|
312
312
|
# 创建新目录
|
|
313
313
|
methodology_dir = _get_methodology_directory()
|
|
314
|
-
|
|
314
|
+
|
|
315
315
|
# 迁移每个方法论
|
|
316
316
|
migrated_count = 0
|
|
317
317
|
for problem_type, content in old_data.items():
|
|
318
318
|
# 为每个方法论创建文件名(使用问题类型的MD5哈希作为文件名)
|
|
319
319
|
safe_filename = hashlib.md5(problem_type.encode('utf-8')).hexdigest()
|
|
320
320
|
file_path = os.path.join(methodology_dir, f"{safe_filename}.json")
|
|
321
|
-
|
|
321
|
+
|
|
322
322
|
# 保存为新格式
|
|
323
323
|
with open(file_path, "w", encoding="utf-8", errors="ignore") as f:
|
|
324
324
|
json.dump({
|
|
325
325
|
"problem_type": problem_type,
|
|
326
326
|
"content": content
|
|
327
327
|
}, f, ensure_ascii=False, indent=2)
|
|
328
|
-
|
|
328
|
+
|
|
329
329
|
migrated_count += 1
|
|
330
|
-
|
|
330
|
+
|
|
331
331
|
if migrated_count > 0:
|
|
332
332
|
# 备份旧文件
|
|
333
333
|
backup_path = old_format_file + ".bak"
|
|
@@ -342,15 +342,15 @@ def _migrate_from_old_format():
|
|
|
342
342
|
def load_methodology(user_input: str) -> str:
|
|
343
343
|
"""
|
|
344
344
|
加载方法论并构建向量索引以进行相似性搜索。
|
|
345
|
-
|
|
345
|
+
|
|
346
346
|
参数:
|
|
347
347
|
user_input: 要搜索方法论的输入文本
|
|
348
|
-
|
|
348
|
+
|
|
349
349
|
返回:
|
|
350
350
|
str: 相关的方法论提示,如果未找到方法论则返回空字符串
|
|
351
351
|
"""
|
|
352
352
|
from yaspin import yaspin
|
|
353
|
-
|
|
353
|
+
|
|
354
354
|
# 加载嵌入向量缓存
|
|
355
355
|
global _methodology_embeddings_cache
|
|
356
356
|
if not _methodology_embeddings_cache:
|
|
@@ -358,22 +358,22 @@ def load_methodology(user_input: str) -> str:
|
|
|
358
358
|
_methodology_embeddings_cache = _load_embeddings_cache()
|
|
359
359
|
spinner.text = f"加载嵌入向量缓存完成 ({len(_methodology_embeddings_cache)} 个向量)"
|
|
360
360
|
spinner.ok("✅")
|
|
361
|
-
|
|
361
|
+
|
|
362
362
|
# 检查是否需要从旧格式迁移
|
|
363
363
|
with yaspin(text="检查方法论格式...", color="yellow") as spinner:
|
|
364
364
|
_migrate_from_old_format()
|
|
365
365
|
spinner.text = "检查方法论格式完成"
|
|
366
366
|
spinner.ok("✅")
|
|
367
|
-
|
|
367
|
+
|
|
368
368
|
# 获取方法论目录
|
|
369
369
|
methodology_dir = _get_methodology_directory()
|
|
370
370
|
if not os.path.exists(methodology_dir) or not glob.glob(os.path.join(methodology_dir, "*.json")):
|
|
371
371
|
return ""
|
|
372
|
-
|
|
372
|
+
|
|
373
373
|
try:
|
|
374
374
|
# 获取文件的修改时间戳组合哈希,用于检测文件是否被修改
|
|
375
375
|
methodology_hash = _get_methodology_files_hash()
|
|
376
|
-
|
|
376
|
+
|
|
377
377
|
# 检查缓存的索引是否可用且方法论文件未被修改
|
|
378
378
|
global _methodology_index_cache
|
|
379
379
|
if _methodology_index_cache is None:
|
|
@@ -386,7 +386,7 @@ def load_methodology(user_input: str) -> str:
|
|
|
386
386
|
else:
|
|
387
387
|
spinner.text = "没有可用的索引缓存"
|
|
388
388
|
spinner.fail("❌")
|
|
389
|
-
|
|
389
|
+
|
|
390
390
|
if _methodology_index_cache is not None:
|
|
391
391
|
cached_index, cached_data, cache_hash = _methodology_index_cache
|
|
392
392
|
if cache_hash == methodology_hash:
|
|
@@ -396,12 +396,12 @@ def load_methodology(user_input: str) -> str:
|
|
|
396
396
|
methodology_data = cached_data
|
|
397
397
|
spinner.text = "使用缓存的方法论索引完成"
|
|
398
398
|
spinner.ok("✅")
|
|
399
|
-
|
|
399
|
+
|
|
400
400
|
with yaspin(text="加载嵌入模型...", color="yellow") as spinner:
|
|
401
401
|
embedding_model = load_embedding_model()
|
|
402
402
|
spinner.text = "加载嵌入模型完成"
|
|
403
403
|
spinner.ok("✅")
|
|
404
|
-
|
|
404
|
+
|
|
405
405
|
with yaspin(text="执行搜索...", color="yellow") as spinner:
|
|
406
406
|
# 使用缓存构造输入文本的嵌入
|
|
407
407
|
query_embedding = _create_methodology_embedding(embedding_model, user_input)
|
|
@@ -411,7 +411,7 @@ def load_methodology(user_input: str) -> str:
|
|
|
411
411
|
) # type: ignore
|
|
412
412
|
spinner.text = "执行搜索完成"
|
|
413
413
|
spinner.ok("✅")
|
|
414
|
-
|
|
414
|
+
|
|
415
415
|
with yaspin(text="处理搜索结果...", color="yellow") as spinner:
|
|
416
416
|
relevant_methodologies = {}
|
|
417
417
|
for dist, idx in zip(distances[0], indices[0]):
|
|
@@ -422,10 +422,12 @@ def load_methodology(user_input: str) -> str:
|
|
|
422
422
|
relevant_methodologies[methodology["key"]] = methodology["value"]
|
|
423
423
|
spinner.text = "处理搜索结果完成"
|
|
424
424
|
spinner.ok("✅")
|
|
425
|
-
|
|
425
|
+
|
|
426
426
|
if relevant_methodologies:
|
|
427
|
+
spinner.text = f"找到相关方法论: {', '.join(relevant_methodologies.keys())}"
|
|
428
|
+
spinner.ok("✅")
|
|
427
429
|
return make_methodology_prompt(relevant_methodologies)
|
|
428
|
-
|
|
430
|
+
|
|
429
431
|
# 如果缓存无效,从头构建索引
|
|
430
432
|
with yaspin(text="初始化数据结构...", color="yellow") as spinner:
|
|
431
433
|
methodology_data: List[Dict[str, str]] = []
|
|
@@ -433,83 +435,85 @@ def load_methodology(user_input: str) -> str:
|
|
|
433
435
|
ids: List[int] = []
|
|
434
436
|
spinner.text = "初始化数据结构完成"
|
|
435
437
|
spinner.ok("✅")
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
438
|
+
|
|
439
|
+
with yaspin(text="加载嵌入模型...", color="yellow") as spinner:
|
|
440
|
+
embedding_model = load_embedding_model()
|
|
441
|
+
spinner.text = "加载嵌入模型完成"
|
|
442
|
+
spinner.ok("✅")
|
|
443
|
+
|
|
444
|
+
with yaspin(text="创建测试嵌入...", color="yellow") as spinner:
|
|
445
|
+
test_embedding = _create_methodology_embedding(embedding_model, "test")
|
|
446
|
+
embedding_dimension = len(test_embedding)
|
|
447
|
+
spinner.text = "创建测试嵌入完成"
|
|
448
|
+
spinner.ok("✅")
|
|
449
|
+
|
|
450
|
+
with yaspin(text="加载方法论文件...", color="yellow") as spinner:
|
|
451
|
+
data = _load_all_methodologies()
|
|
452
|
+
spinner.text = "加载方法论文件完成"
|
|
453
|
+
spinner.ok("✅")
|
|
454
|
+
|
|
455
|
+
with yaspin(text="处理方法论数据...", color="yellow") as spinner:
|
|
456
|
+
for i, (key, value) in enumerate(data.items()):
|
|
457
|
+
methodology_text = f"{key}\n{value}"
|
|
458
|
+
embedding = _create_methodology_embedding(embedding_model, methodology_text)
|
|
459
|
+
vectors.append(embedding)
|
|
460
|
+
ids.append(i)
|
|
461
|
+
methodology_data.append({"key": key, "value": value})
|
|
462
|
+
spinner.text = "处理方法论数据完成"
|
|
463
|
+
spinner.ok("✅")
|
|
464
|
+
|
|
465
|
+
if vectors:
|
|
466
|
+
with yaspin(text="构建索引...", color="yellow") as spinner:
|
|
467
|
+
vectors_array = np.vstack(vectors)
|
|
468
|
+
hnsw_index = faiss.IndexHNSWFlat(embedding_dimension, 16)
|
|
469
|
+
hnsw_index.hnsw.efConstruction = 40
|
|
470
|
+
hnsw_index.hnsw.efSearch = 16
|
|
471
|
+
methodology_index = faiss.IndexIDMap(hnsw_index)
|
|
472
|
+
methodology_index.add_with_ids(vectors_array, np.array(ids)) # type: ignore
|
|
473
|
+
# 缓存构建好的索引和数据以及时间戳哈希
|
|
474
|
+
_methodology_index_cache = (methodology_index, methodology_data, methodology_hash)
|
|
475
|
+
|
|
476
|
+
# 将索引和嵌入向量缓存保存到文件系统
|
|
477
|
+
_save_index_cache(methodology_index, methodology_data, methodology_hash)
|
|
478
|
+
|
|
479
|
+
spinner.text = "构建索引完成"
|
|
446
480
|
spinner.ok("✅")
|
|
447
481
|
|
|
448
|
-
with yaspin(text="
|
|
449
|
-
|
|
450
|
-
|
|
482
|
+
with yaspin(text="执行搜索...", color="yellow") as spinner:
|
|
483
|
+
query_embedding = _create_methodology_embedding(embedding_model, user_input)
|
|
484
|
+
k = min(10, len(methodology_data))
|
|
485
|
+
distances, indices = methodology_index.search(
|
|
486
|
+
query_embedding.reshape(1, -1), k
|
|
487
|
+
) # type: ignore
|
|
488
|
+
spinner.text = "执行搜索完成"
|
|
451
489
|
spinner.ok("✅")
|
|
452
|
-
|
|
453
|
-
with yaspin(text="
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
490
|
+
|
|
491
|
+
with yaspin(text="处理搜索结果...", color="yellow") as spinner:
|
|
492
|
+
relevant_methodologies = {}
|
|
493
|
+
for dist, idx in zip(distances[0], indices[0]):
|
|
494
|
+
if idx >= 0:
|
|
495
|
+
similarity = 1.0 / (1.0 + float(dist))
|
|
496
|
+
methodology = methodology_data[idx]
|
|
497
|
+
if similarity >= 0.5:
|
|
498
|
+
relevant_methodologies[methodology["key"]] = methodology["value"]
|
|
499
|
+
spinner.text = "处理搜索结果完成"
|
|
461
500
|
spinner.ok("✅")
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
hnsw_index.hnsw.efConstruction = 40
|
|
468
|
-
hnsw_index.hnsw.efSearch = 16
|
|
469
|
-
methodology_index = faiss.IndexIDMap(hnsw_index)
|
|
470
|
-
methodology_index.add_with_ids(vectors_array, np.array(ids)) # type: ignore
|
|
471
|
-
# 缓存构建好的索引和数据以及时间戳哈希
|
|
472
|
-
_methodology_index_cache = (methodology_index, methodology_data, methodology_hash)
|
|
473
|
-
|
|
474
|
-
# 将索引和嵌入向量缓存保存到文件系统
|
|
475
|
-
_save_index_cache(methodology_index, methodology_data, methodology_hash)
|
|
476
|
-
|
|
477
|
-
spinner.text = "构建索引完成"
|
|
478
|
-
spinner.ok("✅")
|
|
479
|
-
|
|
480
|
-
with yaspin(text="执行搜索...", color="yellow") as spinner:
|
|
481
|
-
query_embedding = _create_methodology_embedding(embedding_model, user_input)
|
|
482
|
-
k = min(10, len(methodology_data))
|
|
483
|
-
distances, indices = methodology_index.search(
|
|
484
|
-
query_embedding.reshape(1, -1), k
|
|
485
|
-
) # type: ignore
|
|
486
|
-
spinner.text = "执行搜索完成"
|
|
487
|
-
spinner.ok("✅")
|
|
488
|
-
|
|
489
|
-
with yaspin(text="处理搜索结果...", color="yellow") as spinner:
|
|
490
|
-
relevant_methodologies = {}
|
|
491
|
-
for dist, idx in zip(distances[0], indices[0]):
|
|
492
|
-
if idx >= 0:
|
|
493
|
-
similarity = 1.0 / (1.0 + float(dist))
|
|
494
|
-
methodology = methodology_data[idx]
|
|
495
|
-
if similarity >= 0.5:
|
|
496
|
-
relevant_methodologies[methodology["key"]] = methodology["value"]
|
|
497
|
-
spinner.text = "处理搜索结果完成"
|
|
501
|
+
|
|
502
|
+
# 保存嵌入向量缓存到文件系统
|
|
503
|
+
with yaspin(text="保存嵌入向量缓存...", color="yellow") as spinner:
|
|
504
|
+
if _save_embeddings_cache(_methodology_embeddings_cache):
|
|
505
|
+
spinner.text = f"保存嵌入向量缓存完成 ({len(_methodology_embeddings_cache)} 个向量)"
|
|
498
506
|
spinner.ok("✅")
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
if relevant_methodologies:
|
|
510
|
-
return make_methodology_prompt(relevant_methodologies)
|
|
511
|
-
|
|
512
|
-
return make_methodology_prompt(data)
|
|
507
|
+
else:
|
|
508
|
+
spinner.text = "保存嵌入向量缓存失败"
|
|
509
|
+
spinner.fail("❌")
|
|
510
|
+
|
|
511
|
+
if relevant_methodologies:
|
|
512
|
+
spinner.write(f"找到相关方法论: {', '.join(relevant_methodologies.keys())}")
|
|
513
|
+
return make_methodology_prompt(relevant_methodologies)
|
|
514
|
+
spinner.write(f"未找到相关的方法论")
|
|
515
|
+
spinner.fail("❌")
|
|
516
|
+
return ""
|
|
513
517
|
except Exception as e:
|
|
514
518
|
PrettyOutput.print(f"加载方法论失败: {str(e)}", OutputType.ERROR)
|
|
515
519
|
return ""
|
jarvis/jarvis_utils/output.py
CHANGED
|
@@ -21,7 +21,7 @@ from jarvis.jarvis_utils.globals import console, get_agent_list
|
|
|
21
21
|
class OutputType(Enum):
|
|
22
22
|
"""
|
|
23
23
|
输出类型枚举,用于分类和样式化不同类型的消息。
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
属性:
|
|
26
26
|
SYSTEM: AI助手消息
|
|
27
27
|
CODE: 代码相关输出
|
|
@@ -51,7 +51,7 @@ class OutputType(Enum):
|
|
|
51
51
|
class PrettyOutput:
|
|
52
52
|
"""
|
|
53
53
|
使用rich库格式化和显示富文本输出的类。
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
提供以下方法:
|
|
56
56
|
- 使用适当的样式格式化不同类型的输出
|
|
57
57
|
- 代码块的语法高亮
|
|
@@ -110,11 +110,11 @@ class PrettyOutput:
|
|
|
110
110
|
def _detect_language(text: str, default_lang: str = 'markdown') -> str:
|
|
111
111
|
"""
|
|
112
112
|
检测给定文本的编程语言。
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
参数:
|
|
115
115
|
text: 要分析的文本
|
|
116
116
|
default_lang: 如果检测失败,默认返回的语言
|
|
117
|
-
|
|
117
|
+
|
|
118
118
|
返回:
|
|
119
119
|
str: 检测到的语言名称
|
|
120
120
|
"""
|
|
@@ -128,11 +128,11 @@ class PrettyOutput:
|
|
|
128
128
|
def _format(output_type: OutputType, timestamp: bool = True) -> Text:
|
|
129
129
|
"""
|
|
130
130
|
使用时间戳和图标格式化输出头。
|
|
131
|
-
|
|
131
|
+
|
|
132
132
|
参数:
|
|
133
133
|
output_type: 输出类型
|
|
134
134
|
timestamp: 是否包含时间戳
|
|
135
|
-
|
|
135
|
+
|
|
136
136
|
返回:
|
|
137
137
|
Text: 格式化后的rich Text对象
|
|
138
138
|
"""
|
|
@@ -149,7 +149,7 @@ class PrettyOutput:
|
|
|
149
149
|
def print(text: str, output_type: OutputType, timestamp: bool = True, lang: Optional[str] = None, traceback: bool = False):
|
|
150
150
|
"""
|
|
151
151
|
使用样式和语法高亮打印格式化输出。
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
参数:
|
|
154
154
|
text: 要打印的文本内容
|
|
155
155
|
output_type: 输出类型(影响样式)
|
|
@@ -192,7 +192,7 @@ class PrettyOutput:
|
|
|
192
192
|
def section(title: str, output_type: OutputType = OutputType.INFO):
|
|
193
193
|
"""
|
|
194
194
|
在样式化面板中打印章节标题。
|
|
195
|
-
|
|
195
|
+
|
|
196
196
|
参数:
|
|
197
197
|
title: 章节标题文本
|
|
198
198
|
output_type: 输出类型(影响样式)
|
|
@@ -208,7 +208,7 @@ class PrettyOutput:
|
|
|
208
208
|
def print_stream(text: str, is_thinking: bool = False):
|
|
209
209
|
"""
|
|
210
210
|
打印流式输出,不带换行符。
|
|
211
|
-
|
|
211
|
+
|
|
212
212
|
参数:
|
|
213
213
|
text: 要打印的文本
|
|
214
214
|
"""
|
|
@@ -228,10 +228,10 @@ class PrettyOutput:
|
|
|
228
228
|
def _get_style(output_type: OutputType) -> RichStyle:
|
|
229
229
|
"""
|
|
230
230
|
获取预定义的RichStyle用于输出类型。
|
|
231
|
-
|
|
231
|
+
|
|
232
232
|
参数:
|
|
233
233
|
output_type: 要获取样式的输出类型
|
|
234
|
-
|
|
234
|
+
|
|
235
235
|
返回:
|
|
236
236
|
RichStyle: 对应的样式
|
|
237
237
|
"""
|