jarvis-ai-assistant 0.1.100__py3-none-any.whl → 0.1.102__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 CHANGED
@@ -1,3 +1,3 @@
1
1
  """Jarvis AI Assistant"""
2
2
 
3
- __version__ = "0.1.100"
3
+ __version__ = "0.1.102"
jarvis/agent.py CHANGED
@@ -8,7 +8,7 @@ import yaml
8
8
  from jarvis.models.registry import PlatformRegistry
9
9
  from jarvis.tools import ToolRegistry
10
10
  from jarvis.tools.registry import load_tools
11
- from jarvis.utils import PrettyOutput, OutputType, get_single_line_input, load_methodology, add_agent, delete_current_agent, get_max_context_length, get_multiline_input, load_embedding_model, init_env
11
+ from jarvis.utils import PrettyOutput, OutputType, get_single_line_input, load_methodology, add_agent, delete_current_agent, get_max_context_length, get_multiline_input, init_env
12
12
  import os
13
13
 
14
14
  class Agent:
@@ -35,29 +35,9 @@ class Agent:
35
35
  self.conversation_length = 0 # Use length counter instead
36
36
  self.system_prompt = system_prompt
37
37
  # Load configuration from environment variables
38
- self.embedding_dimension = 1536 # Default for many embedding models
38
+
39
39
  self.max_context_length = get_max_context_length()
40
40
 
41
- # Initialize embedding model
42
- try:
43
- self.embedding_model = load_embedding_model()
44
-
45
- # Warm up model and get correct dimension
46
- test_text = "This is a test text to ensure the model is fully loaded."
47
- test_embedding = self.embedding_model.encode(
48
- test_text,
49
- convert_to_tensor=True,
50
- normalize_embeddings=True
51
- )
52
- self.embedding_dimension = len(test_embedding)
53
- PrettyOutput.print("Successfully loaded embedding model", OutputType.SUCCESS)
54
-
55
- # Initialize HNSW index (use correct dimension)
56
-
57
-
58
- except Exception as e:
59
- PrettyOutput.print(f"Failed to load embedding model: {str(e)}", OutputType.ERROR)
60
- raise
61
41
 
62
42
  # Initialize methodology related attributes
63
43
  self.methodology_data = []
@@ -441,7 +421,6 @@ Strict Rules:
441
421
  - Don't create fake dialogues
442
422
  - If current information is insufficient, you may ask the user
443
423
  - Not all problem-solving steps are mandatory, skip as appropriate
444
- - Ask user before executing tools that might damage system or user's codebase
445
424
  - Request user guidance when multiple iterations show no progress
446
425
  - If yaml string contains colons, wrap the entire string in quotes to avoid yaml parsing errors
447
426
  - Use | syntax for multi-line strings in yaml
@@ -459,7 +438,7 @@ def main():
459
438
 
460
439
  try:
461
440
  # 获取全局模型实例
462
- agent = Agent(system_prompt=origin_agent_system_prompt)
441
+ agent = Agent(system_prompt=origin_agent_system_prompt, tool_registry=ToolRegistry())
463
442
 
464
443
  # 加载预定义任务
465
444
  tasks = load_tasks()
@@ -79,8 +79,8 @@ DEVELOPMENT WORKFLOW:
79
79
  <TOOL_CALL>
80
80
  name: create_code_sub_agent
81
81
  arguments:
82
+ name: code_sub_agent
82
83
  subtask: Implement new authentication flow
83
- codebase_dir: .
84
84
  </TOOL_CALL>
85
85
 
86
86
  FILE SELECTION WORKFLOW:
@@ -147,10 +147,8 @@ TOOL USAGE:
147
147
  - ask_user: Ask user for confirmation and information if needed
148
148
  - create_code_sub_agent: Create agent for each small change
149
149
  - file_operation: Read files
150
- - rag: Ask questions based on a document directory, supporting multiple document formats (txt, pdf, docx, etc.)
151
150
  - search: Use Bing search engine to search for information, and extract key information based on the question
152
151
  - thinker: Deep thinking and logical reasoning
153
-
154
152
  2. Planning Tools:
155
153
  - thinker: Generate a detailed modification plan based on user requirements and actual code conditions.
156
154
  - create_code_sub_agent: Create agent for each small change
@@ -211,7 +211,7 @@ class PatchHandler:
211
211
  else:
212
212
  content = "<File does not exist, need to create>"
213
213
 
214
- prompt = """You are a senior software development expert who can generate code patches based on the complete modification plan, current original code file path, code content, and current file's modification plan. The output format should be as follows:
214
+ prompt = """You are a senior software development expert who can generate code patches based on the complete modification plan, current original code file path, code content (with 4-digit hexadecimal line numbers), and current file's modification plan. The output format should be as follows:
215
215
 
216
216
  <PATCH>
217
217
  [start,end)
@@ -220,16 +220,16 @@ class PatchHandler:
220
220
 
221
221
  Example:
222
222
  <PATCH>
223
- [0004,0004)
223
+ [000c,000c)
224
224
  def new_function():
225
- pass
225
+ pass
226
226
  </PATCH>
227
227
 
228
228
  means:
229
- Insert code BEFORE line 4:
229
+ Insert code BEFORE line 12:
230
230
  ```
231
231
  def new_function():
232
- pass
232
+ pass
233
233
  ```
234
234
 
235
235
  Example 2:
@@ -0,0 +1,232 @@
1
+ import os
2
+ import sys
3
+ import argparse
4
+ from typing import Dict, List, Optional
5
+ import yaml
6
+
7
+ from jarvis.agent import Agent
8
+ from jarvis.utils import PrettyOutput, OutputType, get_single_line_input, init_env
9
+ from jarvis.tools import ToolRegistry
10
+
11
+ # System prompt for the GitHub workflow agent
12
+ github_workflow_prompt = """You are a GitHub Workflow Agent that helps manage the complete development workflow using GitHub CLI (gh). Follow these steps strictly:
13
+
14
+ 1. Environment Check:
15
+ - Verify gh CLI installation
16
+ - Check authentication status
17
+ - Set up authentication if needed
18
+
19
+ 2. Issue Management:
20
+ - List and display available issues
21
+ - Help user select an issue to work on
22
+ - Analyze the selected issue thoroughly
23
+
24
+ 3. Development Planning:
25
+ - Create a development branch for the issue
26
+ - Generate a detailed modification plan
27
+ - Break down the task into smaller steps
28
+
29
+ 4. Implementation:
30
+ - Guide through the implementation process
31
+ - Track changes and progress
32
+ - Ensure code quality
33
+
34
+ 5. Review and Submit:
35
+ - Review changes before submission
36
+ - Create and submit pull request
37
+ - Handle review feedback
38
+ - Close the issue upon completion
39
+
40
+ Always follow GitHub best practices and provide clear feedback at each step.
41
+ """
42
+
43
+ def check_gh_installation() -> bool:
44
+ """Check if GitHub CLI is installed"""
45
+ return os.system("gh --version > /dev/null 2>&1") == 0
46
+
47
+ def check_gh_auth() -> bool:
48
+ """Check if GitHub CLI is authenticated"""
49
+ return os.system("gh auth status > /dev/null 2>&1") == 0
50
+
51
+ def setup_gh_auth() -> bool:
52
+ """Guide user through GitHub CLI authentication"""
53
+ PrettyOutput.print("Starting GitHub CLI authentication...", OutputType.INFO)
54
+ return os.system("gh auth login") == 0
55
+
56
+ def list_issues() -> List[Dict]:
57
+ """List all available issues"""
58
+ try:
59
+ # Get issues in JSON format
60
+ result = os.popen("gh issue list --json number,title,body,url").read()
61
+ issues = yaml.safe_load(result)
62
+ return issues
63
+ except Exception as e:
64
+ PrettyOutput.print(f"Error listing issues: {str(e)}", OutputType.ERROR)
65
+ return []
66
+
67
+ def select_issue(issues: List[Dict]) -> Optional[Dict]:
68
+ """Display issues and let user select one"""
69
+ if not issues:
70
+ PrettyOutput.print("No issues found.", OutputType.WARNING)
71
+ return None
72
+
73
+ PrettyOutput.print("\nAvailable Issues:", OutputType.INFO)
74
+ for i, issue in enumerate(issues, 1):
75
+ print(f"{i}. #{issue['number']} - {issue['title']}")
76
+
77
+ while True:
78
+ try:
79
+ choice = get_single_line_input("\nSelect an issue number (or 0 to exit): ")
80
+ if not choice or choice == "0":
81
+ return None
82
+
83
+ index = int(choice) - 1
84
+ if 0 <= index < len(issues):
85
+ return issues[index]
86
+ else:
87
+ PrettyOutput.print("Invalid selection. Please try again.", OutputType.WARNING)
88
+ except ValueError:
89
+ PrettyOutput.print("Please enter a valid number.", OutputType.WARNING)
90
+
91
+ def create_development_branch(issue_number: int) -> bool:
92
+ """Create a development branch for the issue"""
93
+ try:
94
+ result = os.system(f"gh issue develop {issue_number} --checkout")
95
+ return result == 0
96
+ except Exception as e:
97
+ PrettyOutput.print(f"Error creating branch: {str(e)}", OutputType.ERROR)
98
+ return False
99
+
100
+ def create_pull_request(issue_number: int, title: str, body: str) -> bool:
101
+ """Create a pull request for the changes"""
102
+ try:
103
+ cmd = f'gh pr create --title "{title}" --body "{body}" --issue {issue_number}'
104
+ result = os.system(cmd)
105
+ return result == 0
106
+ except Exception as e:
107
+ PrettyOutput.print(f"Error creating pull request: {str(e)}", OutputType.ERROR)
108
+ return False
109
+
110
+ def close_issue(issue_number: int) -> bool:
111
+ """Close the issue"""
112
+ try:
113
+ result = os.system(f"gh issue close {issue_number}")
114
+ return result == 0
115
+ except Exception as e:
116
+ PrettyOutput.print(f"Error closing issue: {str(e)}", OutputType.ERROR)
117
+ return False
118
+
119
+ def install_gh_linux() -> bool:
120
+ """Install GitHub CLI on Linux"""
121
+ PrettyOutput.print("Installing GitHub CLI...", OutputType.INFO)
122
+
123
+ # Detect package manager
124
+ package_managers = {
125
+ "apt": "curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && \
126
+ echo \"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main\" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
127
+ sudo apt update && sudo apt install gh -y",
128
+ "dnf": "sudo dnf install 'dnf-command(config-manager)' -y && \
129
+ sudo dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo && \
130
+ sudo dnf install gh -y",
131
+ "yum": "sudo yum install 'dnf-command(config-manager)' -y && \
132
+ sudo yum config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo && \
133
+ sudo yum install gh -y",
134
+ "pacman": "sudo pacman -S github-cli --noconfirm",
135
+ }
136
+
137
+ # Try to detect the package manager
138
+ for pm, cmd in package_managers.items():
139
+ if os.system(f"which {pm} > /dev/null 2>&1") == 0:
140
+ PrettyOutput.print(f"Detected {pm} package manager", OutputType.INFO)
141
+ if os.system(cmd) == 0:
142
+ PrettyOutput.print("GitHub CLI installed successfully!", OutputType.SUCCESS)
143
+ return True
144
+ else:
145
+ PrettyOutput.print(f"Failed to install using {pm}", OutputType.ERROR)
146
+ return False
147
+
148
+ PrettyOutput.print(
149
+ "Could not detect supported package manager. Please install manually:\n"
150
+ "https://github.com/cli/cli/blob/trunk/docs/install_linux.md",
151
+ OutputType.ERROR
152
+ )
153
+ return False
154
+
155
+ def main():
156
+ """Main entry point for GitHub workflow"""
157
+ init_env()
158
+
159
+ # Check GitHub CLI installation
160
+ if not check_gh_installation():
161
+ if sys.platform.startswith('linux'):
162
+ if not install_gh_linux():
163
+ return 1
164
+ else:
165
+ PrettyOutput.print(
166
+ "GitHub CLI (gh) is not installed. Please install it first:\n"
167
+ "- Windows: winget install GitHub.cli\n"
168
+ "- macOS: brew install gh\n"
169
+ "- Linux: See https://github.com/cli/cli/blob/trunk/docs/install_linux.md",
170
+ OutputType.ERROR
171
+ )
172
+ return 1
173
+
174
+ # Check authentication
175
+ if not check_gh_auth():
176
+ PrettyOutput.print("GitHub CLI needs authentication.", OutputType.WARNING)
177
+ if not setup_gh_auth():
178
+ PrettyOutput.print("Authentication failed. Please try again.", OutputType.ERROR)
179
+ return 1
180
+
181
+ # List and select issue
182
+ issues = list_issues()
183
+ selected_issue = select_issue(issues)
184
+ if not selected_issue:
185
+ PrettyOutput.print("No issue selected. Exiting.", OutputType.INFO)
186
+ return 0
187
+
188
+ # Create GitHub workflow agent
189
+ tool_registry = ToolRegistry()
190
+ agent = Agent(
191
+ system_prompt=github_workflow_prompt,
192
+ name="GitHub Workflow Agent",
193
+ tool_registry=tool_registry
194
+ )
195
+
196
+ # Start the workflow
197
+ try:
198
+ # Create development branch
199
+ if not create_development_branch(selected_issue['number']):
200
+ return 1
201
+
202
+ # Run the agent with the selected issue
203
+ workflow_request = f"""
204
+ Working on issue #{selected_issue['number']}: {selected_issue['title']}
205
+
206
+ Issue description:
207
+ {selected_issue['body']}
208
+
209
+ Please guide through the development process and help create a pull request.
210
+ """
211
+
212
+ result = agent.run(workflow_request)
213
+
214
+ # Create pull request and close issue if successful
215
+ if result and "success" in result.lower():
216
+ if create_pull_request(
217
+ selected_issue['number'],
218
+ f"Fix #{selected_issue['number']}: {selected_issue['title']}",
219
+ "Implements the requested changes and fixes the issue."
220
+ ):
221
+ close_issue(selected_issue['number'])
222
+ PrettyOutput.print("Workflow completed successfully!", OutputType.SUCCESS)
223
+ return 0
224
+
225
+ except Exception as e:
226
+ PrettyOutput.print(f"Error in workflow: {str(e)}", OutputType.ERROR)
227
+ return 1
228
+
229
+ return 1
230
+
231
+ if __name__ == "__main__":
232
+ sys.exit(main())
jarvis/models/ai8.py CHANGED
@@ -14,6 +14,7 @@ class AI8Model(BasePlatform):
14
14
 
15
15
  def get_model_list(self) -> List[Tuple[str, str]]:
16
16
  """获取模型列表"""
17
+ self.get_available_models()
17
18
  return [(name,info['desc']) for name,info in self.models.items()]
18
19
 
19
20
  def __init__(self):
@@ -30,9 +31,7 @@ class AI8Model(BasePlatform):
30
31
 
31
32
 
32
33
  self.model_name = os.getenv("JARVIS_MODEL") or "deepseek-chat"
33
- if self.model_name not in self.get_available_models():
34
- PrettyOutput.print(f"Warning: The selected model {self.model_name} is not in the available list", OutputType.WARNING)
35
-
34
+
36
35
 
37
36
  def set_model_name(self, model_name: str):
38
37
  """Set model name"""
jarvis/models/oyi.py CHANGED
@@ -14,6 +14,7 @@ class OyiModel(BasePlatform):
14
14
 
15
15
  def get_model_list(self) -> List[Tuple[str, str]]:
16
16
  """Get model list"""
17
+ self.get_available_models()
17
18
  return [(name,info['desc']) for name,info in self.models.items()]
18
19
 
19
20
  def __init__(self):
@@ -31,9 +32,6 @@ class OyiModel(BasePlatform):
31
32
  PrettyOutput.print("OYI_API_KEY is not set", OutputType.WARNING)
32
33
 
33
34
  self.model_name = os.getenv("JARVIS_MODEL") or "deepseek-chat"
34
- if self.model_name not in [m.split()[0] for m in self.get_available_models()]:
35
- PrettyOutput.print(f"Warning: The selected model {self.model_name} is not in the available list", OutputType.WARNING)
36
-
37
35
 
38
36
  def set_model_name(self, model_name: str):
39
37
  """Set model name"""
jarvis/tools/registry.py CHANGED
@@ -22,7 +22,6 @@ def load_tools() -> str:
22
22
  tools_prompt += f"- Name: {tool['name']}\n"
23
23
  tools_prompt += f" Description: {tool['description']}\n"
24
24
  tools_prompt += f" Parameters: {tool['parameters']}\n"
25
- tools_prompt += f" Usage Format: <TOOL_CALL>\n"
26
25
  tools_prompt += """
27
26
  Tool Usage Format:
28
27
 
@@ -106,48 +105,55 @@ class ToolRegistry:
106
105
  PrettyOutput.print(f"File does not exist: {p_file_path}", OutputType.ERROR)
107
106
  return False
108
107
 
109
- # Dynamically import the module
110
- module_name = p_file_path.stem
111
- spec = importlib.util.spec_from_file_location(module_name, p_file_path) # type: ignore
112
- if not spec or not spec.loader:
113
- PrettyOutput.print(f"Failed to load module: {p_file_path}", OutputType.ERROR)
114
- return False
115
-
116
- module = importlib.util.module_from_spec(spec) # type: ignore
117
- sys.modules[module_name] = module # Add to sys.modules to support relative imports
118
- spec.loader.exec_module(module)
108
+ # Add the parent directory to sys.path temporarily
109
+ parent_dir = str(p_file_path.parent)
110
+ sys.path.insert(0, parent_dir)
119
111
 
120
- # Find the tool class in the module
121
- tool_found = False
122
- for item_name in dir(module):
123
- item = getattr(module, item_name)
124
- # Check if it is a class and has the necessary attributes
125
- if (isinstance(item, type) and
126
- hasattr(item, 'name') and
127
- hasattr(item, 'description') and
128
- hasattr(item, 'parameters')):
129
-
130
- # Instantiate the tool class, passing in the model and output processor
131
- tool_instance = item()
132
-
133
- # Register the tool
134
- self.register_tool(
135
- name=tool_instance.name,
136
- description=tool_instance.description,
137
- parameters=tool_instance.parameters,
138
- func=tool_instance.execute
139
- )
140
- tool_found = True
141
- break
112
+ try:
113
+ # Import the module using standard import mechanism
114
+ module_name = p_file_path.stem
115
+ module = __import__(module_name)
116
+
117
+ # Find the tool class in the module
118
+ tool_found = False
119
+ for item_name in dir(module):
120
+ item = getattr(module, item_name)
121
+ # Check if it is a class and has the necessary attributes
122
+ if (isinstance(item, type) and
123
+ hasattr(item, 'name') and
124
+ hasattr(item, 'description') and
125
+ hasattr(item, 'parameters')):
126
+
127
+ if hasattr(item, "check"):
128
+ if not item.check():
129
+ PrettyOutput.print(f"Tool {item.name} check failed, skipping", OutputType.INFO)
130
+ continue
131
+
132
+ # Instantiate the tool class
133
+ tool_instance = item()
134
+
135
+ # Register the tool
136
+ self.register_tool(
137
+ name=tool_instance.name,
138
+ description=tool_instance.description,
139
+ parameters=tool_instance.parameters,
140
+ func=tool_instance.execute
141
+ )
142
+ tool_found = True
143
+ break
144
+
145
+ if not tool_found:
146
+ PrettyOutput.print(f"No valid tool class found in the file: {p_file_path}", OutputType.INFO)
147
+ return False
142
148
 
143
- if not tool_found:
144
- PrettyOutput.print(f"No valid tool class found in the file: {p_file_path}", OutputType.WARNING)
145
- return False
149
+ return True
150
+
151
+ finally:
152
+ # Remove the directory from sys.path
153
+ sys.path.remove(parent_dir)
146
154
 
147
- return True
148
-
149
155
  except Exception as e:
150
- PrettyOutput.print(f"Failed to load tool from {p_file_path.name}: {str(e)}", OutputType.ERROR)
156
+ PrettyOutput.print(f"Failed to load tool from {Path(file_path).name}: {str(e)}", OutputType.ERROR)
151
157
  return False
152
158
 
153
159
  def register_tool(self, name: str, description: str, parameters: Dict, func: Callable):
@@ -264,7 +270,9 @@ Please provide a summary:"""
264
270
 
265
271
  else:
266
272
  PrettyOutput.section("Execution failed", OutputType.WARNING)
267
-
273
+
274
+ if len(tool_calls) > 1:
275
+ output += f"\n\n--- 一次只能执行一个工具, 因此以下工具未执行\n{str(tool_calls[1:])} ---"
268
276
  return output
269
277
 
270
278
  except Exception as e:
jarvis/utils.py CHANGED
@@ -1,4 +1,3 @@
1
- from ast import List, Str
2
1
  import hashlib
3
2
  from pathlib import Path
4
3
  import sys
@@ -6,18 +5,14 @@ import time
6
5
  import os
7
6
  from enum import Enum
8
7
  from datetime import datetime
9
- from typing import Any, Dict
8
+ from typing import Any
10
9
  import colorama
11
10
  from colorama import Fore, Style as ColoramaStyle
12
11
  import numpy as np
13
12
  from prompt_toolkit import PromptSession
14
13
  from prompt_toolkit.styles import Style as PromptStyle
15
14
  from prompt_toolkit.formatted_text import FormattedText
16
- from sentence_transformers import SentenceTransformer
17
- from transformers import AutoModelForSequenceClassification, AutoTokenizer
18
- import torch
19
15
  import yaml
20
- import faiss
21
16
 
22
17
  # 初始化colorama
23
18
  colorama.init()
@@ -244,70 +239,6 @@ def find_git_root(dir="."):
244
239
  os.chdir(curr_dir)
245
240
  return ret
246
241
 
247
- def load_embedding_model():
248
- model_name = "BAAI/bge-m3"
249
- cache_dir = os.path.expanduser("~/.cache/huggingface/hub")
250
-
251
-
252
- try:
253
- # Load model
254
- embedding_model = SentenceTransformer(
255
- model_name,
256
- cache_folder=cache_dir,
257
- local_files_only=True
258
- )
259
- except Exception as e:
260
- PrettyOutput.print(f"Failed to load embedding model: {str(e)}", OutputType.ERROR)
261
- os.system(f'huggingface-cli download --repo-type model --local-dir {cache_dir} {model_name}')
262
- # Load model
263
- embedding_model = SentenceTransformer(
264
- model_name,
265
- cache_folder=cache_dir,
266
- local_files_only=True
267
- )
268
-
269
- return embedding_model
270
-
271
- def load_rerank_model():
272
- """Load reranking model"""
273
- model_name = "BAAI/bge-reranker-v2-m3"
274
- cache_dir = os.path.expanduser("~/.cache/huggingface/hub")
275
-
276
- PrettyOutput.print(f"Loading reranking model: {model_name}...", OutputType.INFO)
277
-
278
- try:
279
- # Load model and tokenizer
280
- tokenizer = AutoTokenizer.from_pretrained(
281
- model_name,
282
- cache_dir=cache_dir,
283
- local_files_only=True
284
- )
285
- model = AutoModelForSequenceClassification.from_pretrained(
286
- model_name,
287
- cache_dir=cache_dir,
288
- local_files_only=True
289
- )
290
- except Exception as e:
291
- PrettyOutput.print(f"Failed to load reranking model: {str(e)}", OutputType.ERROR)
292
- os.system(f'huggingface-cli download --repo-type model --local-dir {cache_dir} {model_name}')
293
- # Load model and tokenizer
294
- tokenizer = AutoTokenizer.from_pretrained(
295
- model_name,
296
- cache_dir=cache_dir,
297
- local_files_only=True
298
- )
299
- model = AutoModelForSequenceClassification.from_pretrained(
300
- model_name,
301
- cache_dir=cache_dir,
302
- local_files_only=True
303
- )
304
-
305
- # Use GPU if available
306
- if torch.cuda.is_available():
307
- model = model.cuda()
308
- model.eval()
309
-
310
- return model, tokenizer
311
242
 
312
243
  def get_max_context_length():
313
244
  return int(os.getenv('JARVIS_MAX_CONTEXT_LENGTH', '131072')) # 默认128k
@@ -359,7 +290,6 @@ def _create_methodology_embedding(embedding_model: Any, methodology_text: str) -
359
290
 
360
291
  def load_methodology(user_input: str) -> str:
361
292
  """Load methodology and build vector index"""
362
- PrettyOutput.print("Loading methodology...", OutputType.PROGRESS)
363
293
  user_jarvis_methodology = os.path.expanduser("~/.jarvis/methodology")
364
294
  if not os.path.exists(user_jarvis_methodology):
365
295
  return ""
@@ -368,62 +298,17 @@ def load_methodology(user_input: str) -> str:
368
298
  with open(user_jarvis_methodology, "r", encoding="utf-8") as f:
369
299
  data = yaml.safe_load(f)
370
300
 
371
- # Reset data structure
372
- methodology_data = []
373
- vectors = []
374
- ids = []
375
-
376
- # Get embedding model
377
- embedding_model = load_embedding_model()
378
301
 
379
- # Create test embedding to get correct dimension
380
- test_embedding = _create_methodology_embedding(embedding_model, "test")
381
- embedding_dimension = len(test_embedding)
382
-
383
- # Create embedding vector for each methodology
384
- for i, (key, value) in enumerate(data.items()):
385
- PrettyOutput.print(f"Vectorizing methodology: {key} ...", OutputType.INFO)
386
- methodology_text = f"{key}\n{value}"
387
- embedding = _create_methodology_embedding(embedding_model, methodology_text)
388
- vectors.append(embedding)
389
- ids.append(i)
390
- methodology_data.append({"key": key, "value": value})
391
-
392
- if vectors:
393
- vectors_array = np.vstack(vectors)
394
- # Use correct dimension from test embedding
395
- hnsw_index = faiss.IndexHNSWFlat(embedding_dimension, 16)
396
- hnsw_index.hnsw.efConstruction = 40
397
- hnsw_index.hnsw.efSearch = 16
398
- methodology_index = faiss.IndexIDMap(hnsw_index)
399
- methodology_index.add_with_ids(vectors_array, np.array(ids)) # type: ignore
400
- query_embedding = _create_methodology_embedding(embedding_model, user_input)
401
- k = min(5, len(methodology_data))
402
- PrettyOutput.print(f"Retrieving methodology...", OutputType.INFO)
403
- distances, indices = methodology_index.search(
404
- query_embedding.reshape(1, -1), k
405
- ) # type: ignore
406
-
407
- relevant_methodologies = {}
408
- for dist, idx in zip(distances[0], indices[0]):
409
- if idx >= 0:
410
- similarity = 1.0 / (1.0 + float(dist))
411
- methodology = methodology_data[idx]
412
- PrettyOutput.print(
413
- f"Methodology '{methodology['key']}' similarity: {similarity:.3f}",
414
- OutputType.INFO
415
- )
416
- if similarity >= 0.5:
417
- relevant_methodologies[methodology["key"]] = methodology["value"]
418
-
419
- if relevant_methodologies:
420
- return f"""This is the standard methodology for handling previous problems, if the current task is similar, you can refer to it:
421
- {relevant_methodologies}
422
- """
423
- return ""
302
+ ret = """This is the standard methodology for handling previous problems, if the current task is similar, you can refer to it:"""
303
+ for k, v in data.items():
304
+ ret += f"\n{k}: {v}\n"
305
+ return ret
424
306
 
425
307
  except Exception as e:
426
308
  PrettyOutput.print(f"Error loading methodology: {str(e)}", OutputType.ERROR)
427
309
  import traceback
428
310
  PrettyOutput.print(f"Error trace: {traceback.format_exc()}", OutputType.INFO)
429
- return ""
311
+ return ""
312
+
313
+ def no_embedding() -> bool:
314
+ return bool(os.environ.get("JARVIS_NO_EMBEDDING", ""))