jarvis-ai-assistant 0.1.10__tar.gz → 0.1.12__tar.gz

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.

Files changed (51) hide show
  1. {jarvis_ai_assistant-0.1.10/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.1.12}/PKG-INFO +26 -19
  2. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/README.md +25 -18
  3. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/pyproject.toml +1 -1
  4. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/setup.py +1 -1
  5. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/__init__.py +1 -1
  6. jarvis_ai_assistant-0.1.12/src/jarvis/__pycache__/__init__.cpython-313.pyc +0 -0
  7. jarvis_ai_assistant-0.1.12/src/jarvis/__pycache__/agent.cpython-313.pyc +0 -0
  8. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/__pycache__/main.cpython-313.pyc +0 -0
  9. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/agent.py +33 -79
  10. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/main.py +6 -2
  11. jarvis_ai_assistant-0.1.12/src/jarvis/models/__pycache__/base.cpython-313.pyc +0 -0
  12. jarvis_ai_assistant-0.1.12/src/jarvis/models/__pycache__/kimi.cpython-313.pyc +0 -0
  13. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/models/base.py +5 -1
  14. jarvis_ai_assistant-0.1.12/src/jarvis/models/kimi.py +258 -0
  15. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12/src/jarvis_ai_assistant.egg-info}/PKG-INFO +26 -19
  16. jarvis_ai_assistant-0.1.10/src/jarvis/__pycache__/__init__.cpython-313.pyc +0 -0
  17. jarvis_ai_assistant-0.1.10/src/jarvis/__pycache__/agent.cpython-313.pyc +0 -0
  18. jarvis_ai_assistant-0.1.10/src/jarvis/models/__pycache__/base.cpython-313.pyc +0 -0
  19. jarvis_ai_assistant-0.1.10/src/jarvis/models/__pycache__/kimi.cpython-313.pyc +0 -0
  20. jarvis_ai_assistant-0.1.10/src/jarvis/models/kimi.py +0 -135
  21. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/MANIFEST.in +0 -0
  22. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/setup.cfg +0 -0
  23. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/__pycache__/models.cpython-313.pyc +0 -0
  24. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/__pycache__/tools.cpython-313.pyc +0 -0
  25. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/__pycache__/utils.cpython-313.pyc +0 -0
  26. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/__pycache__/zte_llm.cpython-313.pyc +0 -0
  27. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/models/__init__.py +0 -0
  28. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/models/__pycache__/__init__.cpython-313.pyc +0 -0
  29. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__init__.py +0 -0
  30. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  31. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__pycache__/base.cpython-313.pyc +0 -0
  32. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__pycache__/bing_search.cpython-313.pyc +0 -0
  33. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__pycache__/file_ops.cpython-313.pyc +0 -0
  34. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__pycache__/python_script.cpython-313.pyc +0 -0
  35. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__pycache__/rag.cpython-313.pyc +0 -0
  36. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__pycache__/search.cpython-313.pyc +0 -0
  37. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__pycache__/shell.cpython-313.pyc +0 -0
  38. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__pycache__/sub_agent.cpython-313.pyc +0 -0
  39. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__pycache__/user_confirmation.cpython-313.pyc +0 -0
  40. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__pycache__/user_input.cpython-313.pyc +0 -0
  41. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__pycache__/user_interaction.cpython-313.pyc +0 -0
  42. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/__pycache__/webpage.cpython-313.pyc +0 -0
  43. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/base.py +0 -0
  44. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/file_ops.py +0 -0
  45. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/tools/shell.py +0 -0
  46. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis/utils.py +0 -0
  47. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +0 -0
  48. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
  49. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis_ai_assistant.egg-info/entry_points.txt +0 -0
  50. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
  51. {jarvis_ai_assistant-0.1.10 → jarvis_ai_assistant-0.1.12}/src/jarvis_ai_assistant.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.10
3
+ Version: 0.1.12
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
@@ -36,7 +36,7 @@ Dynamic: requires-python
36
36
  <img src="docs/images/jarvis-logo.png" alt="Jarvis Logo" width="200"/>
37
37
  </p>
38
38
 
39
- [![PyPI version](https://badge.fury.io/py/jarvis-ai.svg)](https://badge.fury.io/py/jarvis-ai)
39
+ [![PyPI version](https://badge.fury.io/py/jarvis-ai-assistant.svg)](https://badge.fury.io/py/jarvis-ai-assistant)
40
40
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
41
41
  [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
42
42
 
@@ -54,20 +54,23 @@ Dynamic: requires-python
54
54
 
55
55
  ## 🌟 Features
56
56
 
57
- 🤖 **Multiple AI Models**
58
- - Ollama integration (llama3.2, qwen2.5:14b)
59
- - DuckDuckGo AI search capabilities
57
+ 🤖 **AI Integration**
58
+ - Kimi AI integration with streaming responses
59
+ - Context-aware conversations
60
+ - File understanding capabilities
60
61
 
61
62
  🛠️ **Rich Tool Integration**
62
- - RAG (Retrieval-Augmented Generation)
63
- - File operations & Shell commands
64
- - Web search & content extraction
65
- - Python code execution with dependency management
63
+ - Shell command execution
64
+ - File operations (read/write/append)
65
+ - Task automation
66
+ - Predefined task support
66
67
 
67
68
  🔄 **Interactive Experience**
68
69
  - Natural language understanding
69
70
  - Context-aware responses
70
71
  - User-friendly interface
72
+ - Multi-line input support
73
+ - Colored output with progress indicators
71
74
 
72
75
  ## 🚀 Installation
73
76
 
@@ -81,25 +84,21 @@ pip install jarvis-ai-assistant
81
84
  # Quick Start
82
85
  jarvis
83
86
 
84
- # Using Specific Model
85
- jarvis --platform ollama --model qwen2.5:14b
87
+ # Process files
88
+ jarvis -f file1.txt file2.py
86
89
 
87
- # Custom Ollama API
88
- jarvis --platform ollama --model llama3.2 --api-base http://localhost:11434
90
+ # Using predefined tasks
91
+ # Create .jarvis file in your working directory:
92
+ analyze_code: Analyze the code in the current directory
93
+ fix_bugs: Help me find and fix bugs in the code
89
94
  ```
90
95
 
91
96
  ## 🧰 Tools
92
97
 
93
98
  | Tool | Description | Example |
94
99
  |------|-------------|---------|
95
- | 🔍 Search | Web search using DuckDuckGo | Search latest tech news |
96
- | 📚 RAG | Document querying with embeddings | Query your documentation |
97
- | 🐍 Python | Execute Python code | Run data analysis |
98
100
  | 🖥️ Shell | Execute system commands | Manage files and processes |
99
101
  | 📂 Files | Read/write operations | Handle configuration files |
100
- | 🌐 Web | Extract webpage content | Gather information |
101
- | 👤 User | Interactive input/confirmation | Get user preferences |
102
-
103
102
 
104
103
  ## 🤝 Contributing
105
104
 
@@ -115,6 +114,14 @@ Contributions are welcome! Please feel free to submit a Pull Request.
115
114
 
116
115
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
117
116
 
117
+ ## ⚙️ Environment Setup
118
+
119
+ Create a `.jarvis_env` file in your home directory with:
120
+
121
+ ```bash
122
+ KIMI_API_KEY=your_kimi_api_key_here
123
+ ```
124
+
118
125
  ---
119
126
 
120
127
  <div align="center">
@@ -6,7 +6,7 @@
6
6
  <img src="docs/images/jarvis-logo.png" alt="Jarvis Logo" width="200"/>
7
7
  </p>
8
8
 
9
- [![PyPI version](https://badge.fury.io/py/jarvis-ai.svg)](https://badge.fury.io/py/jarvis-ai)
9
+ [![PyPI version](https://badge.fury.io/py/jarvis-ai-assistant.svg)](https://badge.fury.io/py/jarvis-ai-assistant)
10
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
11
11
  [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
12
12
 
@@ -24,20 +24,23 @@
24
24
 
25
25
  ## 🌟 Features
26
26
 
27
- 🤖 **Multiple AI Models**
28
- - Ollama integration (llama3.2, qwen2.5:14b)
29
- - DuckDuckGo AI search capabilities
27
+ 🤖 **AI Integration**
28
+ - Kimi AI integration with streaming responses
29
+ - Context-aware conversations
30
+ - File understanding capabilities
30
31
 
31
32
  🛠️ **Rich Tool Integration**
32
- - RAG (Retrieval-Augmented Generation)
33
- - File operations & Shell commands
34
- - Web search & content extraction
35
- - Python code execution with dependency management
33
+ - Shell command execution
34
+ - File operations (read/write/append)
35
+ - Task automation
36
+ - Predefined task support
36
37
 
37
38
  🔄 **Interactive Experience**
38
39
  - Natural language understanding
39
40
  - Context-aware responses
40
41
  - User-friendly interface
42
+ - Multi-line input support
43
+ - Colored output with progress indicators
41
44
 
42
45
  ## 🚀 Installation
43
46
 
@@ -51,25 +54,21 @@ pip install jarvis-ai-assistant
51
54
  # Quick Start
52
55
  jarvis
53
56
 
54
- # Using Specific Model
55
- jarvis --platform ollama --model qwen2.5:14b
57
+ # Process files
58
+ jarvis -f file1.txt file2.py
56
59
 
57
- # Custom Ollama API
58
- jarvis --platform ollama --model llama3.2 --api-base http://localhost:11434
60
+ # Using predefined tasks
61
+ # Create .jarvis file in your working directory:
62
+ analyze_code: Analyze the code in the current directory
63
+ fix_bugs: Help me find and fix bugs in the code
59
64
  ```
60
65
 
61
66
  ## 🧰 Tools
62
67
 
63
68
  | Tool | Description | Example |
64
69
  |------|-------------|---------|
65
- | 🔍 Search | Web search using DuckDuckGo | Search latest tech news |
66
- | 📚 RAG | Document querying with embeddings | Query your documentation |
67
- | 🐍 Python | Execute Python code | Run data analysis |
68
70
  | 🖥️ Shell | Execute system commands | Manage files and processes |
69
71
  | 📂 Files | Read/write operations | Handle configuration files |
70
- | 🌐 Web | Extract webpage content | Gather information |
71
- | 👤 User | Interactive input/confirmation | Get user preferences |
72
-
73
72
 
74
73
  ## 🤝 Contributing
75
74
 
@@ -85,6 +84,14 @@ Contributions are welcome! Please feel free to submit a Pull Request.
85
84
 
86
85
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
87
86
 
87
+ ## ⚙️ Environment Setup
88
+
89
+ Create a `.jarvis_env` file in your home directory with:
90
+
91
+ ```bash
92
+ KIMI_API_KEY=your_kimi_api_key_here
93
+ ```
94
+
88
95
  ---
89
96
 
90
97
  <div align="center">
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jarvis-ai-assistant"
7
- version = "0.1.10"
7
+ version = "0.1.12"
8
8
  description = "Jarvis: An AI assistant that uses tools to interact with the system"
9
9
  readme = "README.md"
10
10
  authors = [{ name = "Your Name", email = "your.email@example.com" }]
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="jarvis-ai-assistant",
5
- version="0.1.10",
5
+ version="0.1.12",
6
6
  author="skyfire",
7
7
  author_email="skyfireitdiy@hotmail.com",
8
8
  description="An AI assistant that uses various tools to interact with the system",
@@ -1,3 +1,3 @@
1
1
  """Jarvis AI Assistant"""
2
2
 
3
- __version__ = "0.1.10"
3
+ __version__ = "0.1.12"
@@ -11,7 +11,7 @@ import os
11
11
  from datetime import datetime
12
12
 
13
13
  class Agent:
14
- def __init__(self, model: BaseModel, tool_registry: ToolRegistry, name: str = "Jarvis", is_sub_agent: bool = False):
14
+ def __init__(self, model: BaseModel, tool_registry: ToolRegistry, name: str = "Jarvis"):
15
15
  """Initialize Agent with a model, optional tool registry and name
16
16
 
17
17
  Args:
@@ -23,8 +23,7 @@ class Agent:
23
23
  self.model = model
24
24
  self.tool_registry = tool_registry or ToolRegistry(model)
25
25
  self.name = name
26
- self.is_sub_agent = is_sub_agent
27
- self.messages = []
26
+ self.prompt = ""
28
27
 
29
28
 
30
29
  @staticmethod
@@ -71,19 +70,28 @@ class Agent:
71
70
 
72
71
  return []
73
72
 
74
- def _call_model(self, messages: List[Dict]) -> Dict:
73
+ def _call_model(self, message: str) -> str:
75
74
  """调用模型获取响应"""
76
75
  try:
77
- return self.model.chat(
78
- messages=messages,
79
- )
76
+ return self.model.chat(message)
80
77
  except Exception as e:
81
78
  raise Exception(f"{self.name}: 模型调用失败: {str(e)}")
82
79
 
83
- def run(self, user_input: str) -> str:
84
- """处理用户输入并返回响应,返回任务总结报告"""
80
+ def run(self, user_input: str, file_list: Optional[List[str]] = None):
81
+ """处理用户输入并返回响应,返回任务总结报告
82
+
83
+ Args:
84
+ user_input: 用户输入的任务描述
85
+ file_list: 可选的文件列表,默认为None
86
+
87
+ Returns:
88
+ str: 任务总结报告
89
+ """
85
90
  self.clear_history()
86
91
 
92
+ if file_list:
93
+ self.model.upload_files(file_list)
94
+
87
95
  # 显示任务开始
88
96
  PrettyOutput.section(f"开始新任务: {self.name}", OutputType.PLANNING)
89
97
 
@@ -93,10 +101,7 @@ class Agent:
93
101
  tools_prompt += f" 描述: {tool['description']}\n"
94
102
  tools_prompt += f" 参数: {tool['parameters']}\n"
95
103
 
96
- self.messages = [
97
- {
98
- "role": "user",
99
- "content": f"""你是 {self.name},一个严格遵循 ReAct 框架进行逐步推理和行动的 AI 助手。
104
+ self.prompt =f"""你是 {self.name},一个严格遵循 ReAct 框架进行逐步推理和行动的 AI 助手。
100
105
 
101
106
  {tools_prompt}
102
107
 
@@ -123,7 +128,7 @@ ReAct 框架:
123
128
  - 只使用下面列出的工具
124
129
  - 每次只执行一个工具
125
130
  - 工具由用户手动执行
126
- - 必须使用有效的YAML格式:
131
+ - 必须使用有效合法的YAML格式:
127
132
  <START_TOOL_CALL>
128
133
  name: tool_name
129
134
  arguments:
@@ -164,7 +169,6 @@ arguments:
164
169
  ‼️ 工具调用必须是有效的YAML格式
165
170
  ‼️ 参数必须正确缩进
166
171
  ‼️ 使用YAML块样式(|)表示多行值
167
- ‼️ <END_TOOL_CALL>后的内容将被丢弃
168
172
  ‼️ 工具由用户手动执行
169
173
  ‼️ 等待用户提供工具执行结果
170
174
  ‼️ 不要假设或想象用户回应
@@ -190,32 +194,21 @@ arguments:
190
194
  任务:
191
195
  {user_input}
192
196
  """
193
- }
194
- ]
197
+
195
198
 
196
199
  while True:
197
200
  try:
198
201
  # 显示思考状态
199
202
  PrettyOutput.print("分析任务...", OutputType.PROGRESS)
200
203
 
201
- current_response = self._call_model(self.messages)
204
+ current_response = self._call_model(self.prompt)
202
205
 
203
206
  try:
204
207
  result = Agent.extract_tool_calls(current_response)
205
208
  except Exception as e:
206
209
  PrettyOutput.print(f"工具调用错误: {str(e)}", OutputType.ERROR)
207
- self.messages.append({
208
- "role": "user",
209
- "content": f"工具调用错误: {str(e)}"
210
- })
210
+ self.prompt = f"工具调用错误: {str(e)}"
211
211
  continue
212
-
213
-
214
- self.messages.append({
215
- "role": "assistant",
216
- "content": current_response
217
- })
218
-
219
212
 
220
213
  if len(result) > 0:
221
214
  try:
@@ -227,68 +220,29 @@ arguments:
227
220
  PrettyOutput.print(str(e), OutputType.ERROR)
228
221
  tool_result = f"Tool call failed: {str(e)}"
229
222
 
230
- self.messages.append({
231
- "role": "user",
232
- "content": tool_result
233
- })
223
+ self.prompt = tool_result
234
224
  continue
235
225
 
236
226
  # 获取用户输入
237
227
  user_input = get_multiline_input(f"{self.name}: 您可以继续输入,或输入空行结束当前任务")
238
- if not user_input:
239
- # 只有子Agent才需要生成任务总结
240
- if self.is_sub_agent:
241
- PrettyOutput.print("生成任务总结...", OutputType.PROGRESS)
242
-
243
- # 生成任务总结
244
- summary_prompt = {
245
- "role": "user",
246
- "content": """任务已完成。请根据之前的分析和执行结果,提供一个简明的任务总结,包括:
247
-
248
- 1. 关键发现:
249
- - 分析过程中的重要发现
250
- - 工具执行的关键结果
251
- - 发现的重要数据
252
-
253
- 2. 执行成果:
254
- - 任务完成情况
255
- - 具体实现结果
256
- - 达成的目标
257
-
258
- 请直接描述事实和实际结果,保持简洁明了。"""
259
- }
260
-
261
- while True:
262
- try:
263
- summary = self._call_model(self.messages + [summary_prompt])
264
-
265
- # 显示任务总结
266
- PrettyOutput.section("任务总结", OutputType.SUCCESS)
267
- PrettyOutput.print(summary, OutputType.SYSTEM)
268
- PrettyOutput.section("任务完成", OutputType.SUCCESS)
269
-
270
- return summary
271
-
272
- except Exception as e:
273
- PrettyOutput.print(str(e), OutputType.ERROR)
274
- else:
275
- # 顶层Agent直接返回空字符串
276
- PrettyOutput.section("任务完成", OutputType.SUCCESS)
277
- return ""
278
-
279
228
  if user_input == "__interrupt__":
280
229
  PrettyOutput.print("任务已取消", OutputType.WARNING)
281
230
  return "Task cancelled by user"
231
+ if user_input:
232
+ self.prompt = user_input
233
+ continue
234
+
235
+ if not user_input:
236
+ PrettyOutput.section("任务完成", OutputType.SUCCESS)
237
+ return
238
+
239
+
282
240
 
283
- self.messages.append({
284
- "role": "user",
285
- "content": user_input
286
- })
287
241
 
288
242
  except Exception as e:
289
243
  PrettyOutput.print(str(e), OutputType.ERROR)
290
244
 
291
245
  def clear_history(self):
292
246
  """清除对话历史,只保留系统提示"""
293
- self.messages = []
247
+ self.prompt = ""
294
248
  self.model.reset()
@@ -72,6 +72,10 @@ def select_task(tasks: dict) -> str:
72
72
 
73
73
  def main():
74
74
  """Main entry point for Jarvis."""
75
+ # Add argument parser
76
+ parser = argparse.ArgumentParser(description='Jarvis AI Assistant')
77
+ parser.add_argument('-f', '--files', nargs='*', help='List of files to process')
78
+ args = parser.parse_args()
75
79
 
76
80
  load_env_from_file()
77
81
 
@@ -95,7 +99,7 @@ def main():
95
99
  selected_task = select_task(tasks)
96
100
  if selected_task:
97
101
  PrettyOutput.print(f"\n执行任务: {selected_task}", OutputType.INFO)
98
- agent.run(selected_task)
102
+ agent.run(selected_task, args.files)
99
103
  return 0
100
104
 
101
105
  # 如果没有选择预定义任务,进入交互模式
@@ -104,7 +108,7 @@ def main():
104
108
  user_input = get_multiline_input("请输入您的任务(输入空行退出):")
105
109
  if not user_input or user_input == "__interrupt__":
106
110
  break
107
- agent.run(user_input)
111
+ agent.run(user_input, args.files)
108
112
  except Exception as e:
109
113
  PrettyOutput.print(f"错误: {str(e)}", OutputType.ERROR)
110
114
 
@@ -5,10 +5,14 @@ class BaseModel(ABC):
5
5
  """大语言模型基类"""
6
6
 
7
7
  @abstractmethod
8
- def chat(self, messages: List[Dict]) -> str:
8
+ def chat(self, message: str) -> str:
9
9
  """执行对话"""
10
10
  pass
11
11
 
12
+ def upload_files(self, file_list: List[str]) -> List[Dict]:
13
+ """上传文件"""
14
+ pass
15
+
12
16
  def reset(self):
13
17
  """重置模型"""
14
18
  pass
@@ -0,0 +1,258 @@
1
+ from typing import Dict, List, Optional
2
+ import requests
3
+ import json
4
+ import os
5
+ import mimetypes
6
+ from .base import BaseModel
7
+ from ..utils import PrettyOutput, OutputType
8
+ import time
9
+
10
+ class KimiModel(BaseModel):
11
+ """Kimi模型实现"""
12
+
13
+ def __init__(self, api_key: str = None):
14
+ """
15
+ 初始化Kimi模型
16
+ Args:
17
+ api_key: Kimi API密钥,如果不提供则从环境变量获取
18
+ """
19
+ self.api_key = api_key or os.getenv("KIMI_API_KEY")
20
+ if not self.api_key:
21
+ raise Exception("KIMI_API_KEY is not set")
22
+ self.auth_header = f"Bearer {self.api_key}"
23
+ self.chat_id = ""
24
+ self.uploaded_files = [] # 存储已上传文件的信息
25
+ self.first_chat = True # 添加标记,用于判断是否是第一次对话
26
+
27
+ def _create_chat(self) -> bool:
28
+ """创建新的对话会话"""
29
+ url = "https://kimi.moonshot.cn/api/chat"
30
+ payload = json.dumps({
31
+ "name": "未命名会话",
32
+ "is_example": False,
33
+ "kimiplus_id": "kimi"
34
+ })
35
+ headers = {
36
+ 'Authorization': self.auth_header,
37
+ 'Content-Type': 'application/json'
38
+ }
39
+ try:
40
+ response = requests.request("POST", url, headers=headers, data=payload)
41
+ self.chat_id = response.json()["id"]
42
+ return True
43
+ except Exception as e:
44
+ PrettyOutput.print(f"Failed to create chat: {e}", OutputType.ERROR)
45
+ return False
46
+
47
+ def _get_presigned_url(self, filename: str) -> Dict:
48
+ """获取预签名上传URL"""
49
+ url = "https://kimi.moonshot.cn/api/pre-sign-url"
50
+ mime_type, _ = mimetypes.guess_type(filename)
51
+ action = "image" if mime_type and mime_type.startswith('image/') else "file"
52
+
53
+ payload = json.dumps({
54
+ "action": action,
55
+ "name": os.path.basename(filename)
56
+ })
57
+
58
+ headers = {
59
+ 'Authorization': self.auth_header,
60
+ 'Content-Type': 'application/json'
61
+ }
62
+
63
+ response = requests.post(url, headers=headers, data=payload)
64
+ return response.json()
65
+
66
+ def _upload_file(self, file_path: str, presigned_url: str) -> bool:
67
+ """上传文件到预签名URL"""
68
+ try:
69
+ with open(file_path, 'rb') as f:
70
+ content = f.read()
71
+ response = requests.put(presigned_url, data=content)
72
+ return response.status_code == 200
73
+ except Exception as e:
74
+ PrettyOutput.print(f"Failed to upload file: {e}", OutputType.ERROR)
75
+ return False
76
+
77
+ def _get_file_info(self, file_data: Dict, name: str) -> Dict:
78
+ """获取文件信息"""
79
+ url = "https://kimi.moonshot.cn/api/file"
80
+ payload = json.dumps({
81
+ "type": "file",
82
+ "name": name,
83
+ "object_name": file_data["object_name"],
84
+ "chat_id": self.chat_id,
85
+ "file_id": file_data.get("file_id", "")
86
+ })
87
+
88
+ headers = {
89
+ 'Authorization': self.auth_header,
90
+ 'Content-Type': 'application/json'
91
+ }
92
+
93
+ response = requests.post(url, headers=headers, data=payload)
94
+ return response.json()
95
+
96
+ def _wait_for_parse(self, file_id: str) -> bool:
97
+ """等待文件解析完成"""
98
+ url = "https://kimi.moonshot.cn/api/file/parse_process"
99
+ headers = {
100
+ 'Authorization': self.auth_header,
101
+ 'Content-Type': 'application/json'
102
+ }
103
+
104
+ max_retries = 30
105
+ retry_count = 0
106
+
107
+ while retry_count < max_retries:
108
+ payload = json.dumps({"ids": [file_id]})
109
+ response = requests.post(url, headers=headers, data=payload, stream=True)
110
+
111
+ for line in response.iter_lines():
112
+ if not line:
113
+ continue
114
+
115
+ line = line.decode('utf-8')
116
+ if not line.startswith("data: "):
117
+ continue
118
+
119
+ try:
120
+ data = json.loads(line[6:])
121
+ if data.get("event") == "resp":
122
+ status = data.get("file_info", {}).get("status")
123
+ if status == "parsed":
124
+ return True
125
+ elif status == "failed":
126
+ return False
127
+ except json.JSONDecodeError:
128
+ continue
129
+
130
+ retry_count += 1
131
+ time.sleep(1)
132
+
133
+ return False
134
+
135
+ def upload_files(self, file_list: List[str]) -> List[Dict]:
136
+ """上传文件列表并返回文件信息"""
137
+ if not file_list:
138
+ return []
139
+
140
+ PrettyOutput.print("开始处理文件上传...", OutputType.PROGRESS)
141
+
142
+ if not self.chat_id:
143
+ PrettyOutput.print("创建新的对话会话...", OutputType.PROGRESS)
144
+ if not self._create_chat():
145
+ raise Exception("Failed to create chat session")
146
+
147
+ uploaded_files = []
148
+ for index, file_path in enumerate(file_list, 1):
149
+ try:
150
+ PrettyOutput.print(f"处理文件 [{index}/{len(file_list)}]: {file_path}", OutputType.PROGRESS)
151
+
152
+ # 获取预签名URL
153
+ PrettyOutput.print("获取上传URL...", OutputType.PROGRESS)
154
+ presigned_data = self._get_presigned_url(file_path)
155
+
156
+ # 上传文件
157
+ PrettyOutput.print("上传文件内容...", OutputType.PROGRESS)
158
+ if self._upload_file(file_path, presigned_data["url"]):
159
+ # 获取文件信息
160
+ PrettyOutput.print("获取文件信息...", OutputType.PROGRESS)
161
+ file_info = self._get_file_info(presigned_data, os.path.basename(file_path))
162
+
163
+ # 等待文件解析
164
+ PrettyOutput.print("等待文件解析完成...", OutputType.PROGRESS)
165
+ if self._wait_for_parse(file_info["id"]):
166
+ uploaded_files.append(file_info)
167
+ PrettyOutput.print(f"✓ 文件处理成功: {file_path}", OutputType.SUCCESS)
168
+ else:
169
+ PrettyOutput.print(f"✗ 文件解析失败: {file_path}", OutputType.ERROR)
170
+ else:
171
+ PrettyOutput.print(f"✗ 文件上传失败: {file_path}", OutputType.ERROR)
172
+
173
+ except Exception as e:
174
+ PrettyOutput.print(f"✗ 处理文件出错 {file_path}: {str(e)}", OutputType.ERROR)
175
+ continue
176
+
177
+ if uploaded_files:
178
+ PrettyOutput.print(f"成功处理 {len(uploaded_files)}/{len(file_list)} 个文件", OutputType.SUCCESS)
179
+ else:
180
+ PrettyOutput.print("没有文件成功处理", OutputType.WARNING)
181
+
182
+ self.uploaded_files = uploaded_files
183
+ return uploaded_files
184
+
185
+ def chat(self, message: str) -> str:
186
+ """发送消息并获取响应"""
187
+ if not self.chat_id:
188
+ PrettyOutput.print("创建新的对话会话...", OutputType.PROGRESS)
189
+ if not self._create_chat():
190
+ raise Exception("Failed to create chat session")
191
+
192
+ url = f"https://kimi.moonshot.cn/api/chat/{self.chat_id}/completion/stream"
193
+
194
+ # 只在第一次对话时带上文件引用
195
+ refs = []
196
+ refs_file = []
197
+ if self.first_chat and self.uploaded_files:
198
+ PrettyOutput.print(f"首次对话,引用 {len(self.uploaded_files)} 个文件...", OutputType.PROGRESS)
199
+ refs = [f["id"] for f in self.uploaded_files]
200
+ refs_file = self.uploaded_files
201
+ self.first_chat = False
202
+
203
+ PrettyOutput.print("发送请求...", OutputType.PROGRESS)
204
+ payload = {
205
+ "messages": [{"role": "user", "content": message}],
206
+ "use_search": True,
207
+ "extend": {"sidebar": True},
208
+ "kimiplus_id": "kimi",
209
+ "use_research": False,
210
+ "use_math": False,
211
+ "refs": refs,
212
+ "refs_file": refs_file
213
+ }
214
+
215
+ headers = {
216
+ 'Authorization': self.auth_header,
217
+ 'Content-Type': 'application/json'
218
+ }
219
+
220
+ try:
221
+ response = requests.post(url, headers=headers, json=payload, stream=True)
222
+ full_response = ""
223
+
224
+ PrettyOutput.print("接收响应...", OutputType.PROGRESS)
225
+ for line in response.iter_lines():
226
+ if not line:
227
+ continue
228
+
229
+ line = line.decode('utf-8')
230
+ if not line.startswith("data: "):
231
+ continue
232
+
233
+ try:
234
+ data = json.loads(line[6:])
235
+ if data.get("event") == "cmpl":
236
+ text = data.get("text", "")
237
+ if text:
238
+ PrettyOutput.print_stream(text, OutputType.SYSTEM)
239
+ full_response += text
240
+ except json.JSONDecodeError:
241
+ continue
242
+
243
+ PrettyOutput.print_stream_end()
244
+ return full_response
245
+
246
+ except Exception as e:
247
+ raise Exception(f"Chat failed: {str(e)}")
248
+
249
+ def reset(self):
250
+ """重置对话"""
251
+ self.chat_id = ""
252
+ self.uploaded_files = []
253
+ self.first_chat = True # 重置first_chat标记
254
+
255
+
256
+ if __name__ == "__main__":
257
+ kimi = KimiModel()
258
+ print(kimi.chat([{"role": "user", "content": "ollama如何部署"}]))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.10
3
+ Version: 0.1.12
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
@@ -36,7 +36,7 @@ Dynamic: requires-python
36
36
  <img src="docs/images/jarvis-logo.png" alt="Jarvis Logo" width="200"/>
37
37
  </p>
38
38
 
39
- [![PyPI version](https://badge.fury.io/py/jarvis-ai.svg)](https://badge.fury.io/py/jarvis-ai)
39
+ [![PyPI version](https://badge.fury.io/py/jarvis-ai-assistant.svg)](https://badge.fury.io/py/jarvis-ai-assistant)
40
40
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
41
41
  [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
42
42
 
@@ -54,20 +54,23 @@ Dynamic: requires-python
54
54
 
55
55
  ## 🌟 Features
56
56
 
57
- 🤖 **Multiple AI Models**
58
- - Ollama integration (llama3.2, qwen2.5:14b)
59
- - DuckDuckGo AI search capabilities
57
+ 🤖 **AI Integration**
58
+ - Kimi AI integration with streaming responses
59
+ - Context-aware conversations
60
+ - File understanding capabilities
60
61
 
61
62
  🛠️ **Rich Tool Integration**
62
- - RAG (Retrieval-Augmented Generation)
63
- - File operations & Shell commands
64
- - Web search & content extraction
65
- - Python code execution with dependency management
63
+ - Shell command execution
64
+ - File operations (read/write/append)
65
+ - Task automation
66
+ - Predefined task support
66
67
 
67
68
  🔄 **Interactive Experience**
68
69
  - Natural language understanding
69
70
  - Context-aware responses
70
71
  - User-friendly interface
72
+ - Multi-line input support
73
+ - Colored output with progress indicators
71
74
 
72
75
  ## 🚀 Installation
73
76
 
@@ -81,25 +84,21 @@ pip install jarvis-ai-assistant
81
84
  # Quick Start
82
85
  jarvis
83
86
 
84
- # Using Specific Model
85
- jarvis --platform ollama --model qwen2.5:14b
87
+ # Process files
88
+ jarvis -f file1.txt file2.py
86
89
 
87
- # Custom Ollama API
88
- jarvis --platform ollama --model llama3.2 --api-base http://localhost:11434
90
+ # Using predefined tasks
91
+ # Create .jarvis file in your working directory:
92
+ analyze_code: Analyze the code in the current directory
93
+ fix_bugs: Help me find and fix bugs in the code
89
94
  ```
90
95
 
91
96
  ## 🧰 Tools
92
97
 
93
98
  | Tool | Description | Example |
94
99
  |------|-------------|---------|
95
- | 🔍 Search | Web search using DuckDuckGo | Search latest tech news |
96
- | 📚 RAG | Document querying with embeddings | Query your documentation |
97
- | 🐍 Python | Execute Python code | Run data analysis |
98
100
  | 🖥️ Shell | Execute system commands | Manage files and processes |
99
101
  | 📂 Files | Read/write operations | Handle configuration files |
100
- | 🌐 Web | Extract webpage content | Gather information |
101
- | 👤 User | Interactive input/confirmation | Get user preferences |
102
-
103
102
 
104
103
  ## 🤝 Contributing
105
104
 
@@ -115,6 +114,14 @@ Contributions are welcome! Please feel free to submit a Pull Request.
115
114
 
116
115
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
117
116
 
117
+ ## ⚙️ Environment Setup
118
+
119
+ Create a `.jarvis_env` file in your home directory with:
120
+
121
+ ```bash
122
+ KIMI_API_KEY=your_kimi_api_key_here
123
+ ```
124
+
118
125
  ---
119
126
 
120
127
  <div align="center">
@@ -1,135 +0,0 @@
1
- from typing import Dict, List
2
- import requests
3
- import json
4
- import os
5
- from .base import BaseModel
6
- from ..utils import PrettyOutput, OutputType
7
- import time
8
-
9
- class KimiModel(BaseModel):
10
- """Kimi模型实现"""
11
-
12
- def __init__(self, api_key: str = None):
13
- """
14
- 初始化Kimi模型
15
- Args:
16
- api_key: Kimi API密钥,如果不提供则从环境变量获取
17
- """
18
- self.api_key = api_key or os.getenv("KIMI_API_KEY")
19
- if not self.api_key:
20
- raise Exception("KIMI_API_KEY is not set")
21
- self.auth_header = f"Bearer {self.api_key}"
22
- self.chat_id = ""
23
-
24
- def _create_chat(self) -> bool:
25
- """创建新的对话会话"""
26
- url = "https://kimi.moonshot.cn/api/chat"
27
- payload = json.dumps({
28
- "name": "未命名会话",
29
- "is_example": False,
30
- "kimiplus_id": "kimi"
31
- })
32
- headers = {
33
- 'Authorization': self.auth_header,
34
- 'Content-Type': 'application/json'
35
- }
36
- try:
37
- response = requests.request("POST", url, headers=headers, data=payload)
38
- self.chat_id = response.json()["id"]
39
- return True
40
- except Exception as e:
41
- PrettyOutput.print(f"Failed to create chat: {e}", OutputType.ERROR)
42
- return False
43
-
44
- def chat(self, messages: List[Dict]) -> str:
45
- """
46
- 实现BaseModel的chat方法
47
- Args:
48
- messages: 对话消息列表
49
- Returns:
50
- str: 模型的回复内容
51
- """
52
- if not self.chat_id:
53
- if not self._create_chat():
54
- raise Exception("Failed to create chat")
55
-
56
- url = f"https://kimi.moonshot.cn/api/chat/{self.chat_id}/completion/stream"
57
- payload = json.dumps({
58
- "messages": [messages[-1]],
59
- "use_search": True,
60
- "extend": {
61
- "sidebar": True
62
- },
63
- "kimiplus_id": "kimi",
64
- "use_research": False,
65
- "use_math": False,
66
- "refs": [],
67
- "refs_file": []
68
- })
69
- headers = {
70
- 'Authorization': self.auth_header,
71
- 'Content-Type': 'application/json'
72
- }
73
-
74
- try:
75
- response = requests.request("POST", url, headers=headers, data=payload, stream=True)
76
- full_response = ""
77
- references = []
78
-
79
- for line in response.iter_lines():
80
- if not line:
81
- continue
82
-
83
- line = line.decode('utf-8')
84
- if not line.startswith("data: "):
85
- continue
86
-
87
- try:
88
- data = json.loads(line[6:]) # 去掉 "data: " 前缀
89
-
90
- # 处理不同类型的事件
91
- if data.get("event") == "cmpl":
92
- if "text" in data:
93
- text = data["text"]
94
- PrettyOutput.print_stream(text, OutputType.SYSTEM) # 使用统一的流式输出
95
- full_response += text
96
- elif data.get("event") == "ref_docs":
97
- if "ref_cards" in data:
98
- for ref in data["ref_cards"]:
99
- reference = {
100
- "title": ref.get("title", ""),
101
- "url": ref.get("url", ""),
102
- "abstract": ref.get("abstract", "")
103
- }
104
- references.append(reference)
105
- PrettyOutput.print(f"\n参考来源: {reference['title']} - {reference['url']}",
106
- OutputType.INFO)
107
- elif data.get("event") == "error":
108
- error_msg = data.get("error", "Unknown error")
109
- raise Exception(f"Chat error: {error_msg}")
110
- elif data.get("event") == "all_done":
111
- break
112
-
113
- except json.JSONDecodeError:
114
- continue
115
-
116
- # 如果有参考文献,在回答后面添加引用信息
117
- if references:
118
- full_response += "\n\n参考来源:\n"
119
- for i, ref in enumerate(references, 1):
120
- full_response += f"{i}. {ref['title']} - {ref['url']}\n"
121
-
122
- PrettyOutput.print_stream_end() # 结束流式输出
123
- return full_response
124
-
125
- except Exception as e:
126
- raise Exception(f"Kimi API调用失败: {str(e)}")
127
-
128
- def reset(self):
129
- """重置模型"""
130
- self.chat_id = ""
131
-
132
-
133
- if __name__ == "__main__":
134
- kimi = KimiModel()
135
- print(kimi.chat([{"role": "user", "content": "ollama如何部署"}]))