llm-with-vim 2.0.20261111__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.
- llm_with_vim-2.0.20261111/LICENSE +21 -0
- llm_with_vim-2.0.20261111/PKG-INFO +445 -0
- llm_with_vim-2.0.20261111/README.md +420 -0
- llm_with_vim-2.0.20261111/llm_engine/__init__.py +29 -0
- llm_with_vim-2.0.20261111/llm_engine/__main__.py +5 -0
- llm_with_vim-2.0.20261111/llm_engine/default_config.json +65 -0
- llm_with_vim-2.0.20261111/llm_engine/editors/micro/README.md +114 -0
- llm_with_vim-2.0.20261111/llm_engine/editors/micro/llm_micro/help/llm-micro.md +39 -0
- llm_with_vim-2.0.20261111/llm_engine/editors/micro/llm_micro/llm_micro.lua +673 -0
- llm_with_vim-2.0.20261111/llm_engine/editors/micro/llm_micro/repo.json +7 -0
- llm_with_vim-2.0.20261111/llm_engine/editors/micro/llm_micro/syntax/llm-chat.yaml +14 -0
- llm_with_vim-2.0.20261111/llm_engine/editors/vim/doc/llm.txt +175 -0
- llm_with_vim-2.0.20261111/llm_engine/editors/vim/ftdetect/llm.vim +2 -0
- llm_with_vim-2.0.20261111/llm_engine/editors/vim/plugin/llm.vim +592 -0
- llm_with_vim-2.0.20261111/llm_engine/editors/vscode/LICENSE +21 -0
- llm_with_vim-2.0.20261111/llm_engine/editors/vscode/README.md +66 -0
- llm_with_vim-2.0.20261111/llm_engine/editors/vscode/extension.js +511 -0
- llm_with_vim-2.0.20261111/llm_engine/editors/vscode/package.json +100 -0
- llm_with_vim-2.0.20261111/llm_engine/editors/vscode/syntaxes/llm-chat.tmLanguage.json +53 -0
- llm_with_vim-2.0.20261111/llm_engine/engine.py +1774 -0
- llm_with_vim-2.0.20261111/llm_engine/install_editors.py +577 -0
- llm_with_vim-2.0.20261111/llm_engine/plugin_loader.py +184 -0
- llm_with_vim-2.0.20261111/llm_engine/plugins/tools/__init__.py +1 -0
- llm_with_vim-2.0.20261111/llm_engine/plugins/tools/bash.py +53 -0
- llm_with_vim-2.0.20261111/llm_engine/plugins/tools/edit.py +63 -0
- llm_with_vim-2.0.20261111/llm_engine/plugins/tools/list_dir.py +44 -0
- llm_with_vim-2.0.20261111/llm_engine/plugins/tools/python.py +55 -0
- llm_with_vim-2.0.20261111/llm_engine/plugins/tools/read.py +38 -0
- llm_with_vim-2.0.20261111/llm_engine/plugins/tools/search.py +66 -0
- llm_with_vim-2.0.20261111/llm_engine/plugins/tools/view_image.py +69 -0
- llm_with_vim-2.0.20261111/llm_engine/plugins/tools/web_fetch.py +53 -0
- llm_with_vim-2.0.20261111/llm_engine/plugins/tools/write.py +49 -0
- llm_with_vim-2.0.20261111/llm_engine/provider_spec.py +350 -0
- llm_with_vim-2.0.20261111/llm_engine/providers/ali.json +64 -0
- llm_with_vim-2.0.20261111/llm_engine/providers/deepseek.json +64 -0
- llm_with_vim-2.0.20261111/llm_engine/providers/haijing.json +64 -0
- llm_with_vim-2.0.20261111/llm_engine/providers/llama.json +68 -0
- llm_with_vim-2.0.20261111/llm_engine/providers/ollama.json +76 -0
- llm_with_vim-2.0.20261111/llm_engine/providers/openai_compat.json +67 -0
- llm_with_vim-2.0.20261111/llm_engine/providers/zhipu.json +64 -0
- llm_with_vim-2.0.20261111/llm_engine/schemas/provider.schema.json +34 -0
- llm_with_vim-2.0.20261111/llm_engine/tools.py +115 -0
- llm_with_vim-2.0.20261111/llm_with_vim.egg-info/PKG-INFO +445 -0
- llm_with_vim-2.0.20261111/llm_with_vim.egg-info/SOURCES.txt +51 -0
- llm_with_vim-2.0.20261111/llm_with_vim.egg-info/dependency_links.txt +1 -0
- llm_with_vim-2.0.20261111/llm_with_vim.egg-info/entry_points.txt +5 -0
- llm_with_vim-2.0.20261111/llm_with_vim.egg-info/requires.txt +1 -0
- llm_with_vim-2.0.20261111/llm_with_vim.egg-info/top_level.txt +1 -0
- llm_with_vim-2.0.20261111/pyproject.toml +76 -0
- llm_with_vim-2.0.20261111/setup.cfg +4 -0
- llm_with_vim-2.0.20261111/test/test_context_consistency.py +142 -0
- llm_with_vim-2.0.20261111/test/test_ollama_format.py +63 -0
- llm_with_vim-2.0.20261111/test/test_provider_spec.py +112 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Kenneth-Lee-2012
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: llm-with-vim
|
|
3
|
+
Version: 2.0.20261111
|
|
4
|
+
Summary: LLM chat engine for Vim/VSCode/Micro: the conversation is an editable text file
|
|
5
|
+
Author-email: Kenneth Lee <kenneth-lee-2012@qq.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Kenneth-Lee/llm_with_vim
|
|
8
|
+
Project-URL: Issues, https://github.com/Kenneth-Lee/llm_with_vim/issues
|
|
9
|
+
Keywords: llm,chat,vim,vscode,micro,ollama,deepseek,ai
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Topic :: Text Editors
|
|
19
|
+
Classifier: Topic :: Utilities
|
|
20
|
+
Requires-Python: >=3.6
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: requests
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# LLM with Vim
|
|
27
|
+
|
|
28
|
+
这是一个简单有用的LLM Restful API访问引擎。
|
|
29
|
+
|
|
30
|
+
最初的时候,我主要用它实现从vim对ollama进行访问的,所以叫做llm_with_vim。后来
|
|
31
|
+
慢慢增加其他LLM API的支持,又增加vscode和micro的插件。2.0版本重构引入了新的
|
|
32
|
+
插件化引擎架构(我们称之为ContextForge架构,见
|
|
33
|
+
[架构设计](docs/contextforge_architecture_design.md)),但项目名保持为
|
|
34
|
+
llm-with-vim。本质上,它是一个可以让你在编辑器中不断编辑和LLM的交互历史的另类
|
|
35
|
+
“智能体”(Agent)。
|
|
36
|
+
|
|
37
|
+
也许很多人都知道,但也许也有很多人不知道:现在的大语言模型都是没有记忆的。它完
|
|
38
|
+
成训练以后,内容就固定了,你给它说什么,它就基于你说的话决定返回什么。
|
|
39
|
+
|
|
40
|
+
所以我们一般理解的和LLM的“对话”,其实是每次都把所有的对话都过程都告诉LLM,LLM都
|
|
41
|
+
当作是“一次对话”。这样给了我们一个玩技巧的空间:你不需要为你原来说过的话负责,
|
|
42
|
+
你随时可以修改,你也不需要接受LLM说过的话,你也随时可以修改。
|
|
43
|
+
|
|
44
|
+
各种所谓“提示词工程”,本质都是控制这个输入给LLM的“对话”是什么,控制了这个对话的
|
|
45
|
+
上下文,就控制了LLM的输出。
|
|
46
|
+
|
|
47
|
+
比如说你让AI给你写一份简历,AI写完以后你基本上都满意,但你希望你换一个名字,并
|
|
48
|
+
且调整一下你的工作经历。你反复给它说明白这个问题其实不容易,还不如你直接编辑它
|
|
49
|
+
的回答,让它把这个当作它自己说的,之后你直接提其他更复杂的修改要求。你如果对它
|
|
50
|
+
整个回答都不满意,你也可以删掉他这个回答,然后在问题上增加你的额外要求。这样整
|
|
51
|
+
个沟通效率就会高得多。
|
|
52
|
+
|
|
53
|
+
这种方法最大程度扩展了你对AI的控制能力。现在各种智能体,本质都是软件在你输入以
|
|
54
|
+
后,帮你按某种方式编排这个“上下文”,而我们这个工具反过来,我们把这个上下文整个
|
|
55
|
+
呈现在编辑器里,让你自己看到整个上下文,决定怎么安排你和LLM的“共同历史”,完全按
|
|
56
|
+
你的要求提交给LLM。
|
|
57
|
+
|
|
58
|
+

|
|
59
|
+
|
|
60
|
+
当然,因为这个工具的目的是人为接入交互过程,所以它也没有一般AI编程智能体那种自
|
|
61
|
+
动循环的能力,它最多支持LLM那边要求工具调用的时候自动回复,其他时候,LLM回复以
|
|
62
|
+
后,我们就需要用户的介入,你要自己决定下一步把什么上下文提交给它。
|
|
63
|
+
|
|
64
|
+
## 安装
|
|
65
|
+
|
|
66
|
+
最简单的方式是从 PyPI 安装(支持 pip / uv):
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install llm-with-vim # 或 uv tool install llm-with-vim
|
|
70
|
+
llm-with-vim-setup # 检测并安装 Vim/VSCode/micro 插件
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
也可以只装部分编辑器插件:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
llm-with-vim-setup --vim # 仅 Vim 插件(--vscode / --micro 同理)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
从源码安装或了解可编辑安装、uv 等方式,参考[安装指南](INSTALL.md)。
|
|
80
|
+
|
|
81
|
+
### 安装后 vim 插件未激活的排查
|
|
82
|
+
|
|
83
|
+
安装成功(`vimfiles/plugin/llm.vim` 确实存在)但打开 `.llm` 文件没有高亮和热键时,
|
|
84
|
+
在 vim 里按以下顺序检查,可以快速定位断在哪一环(Windows 用户尤其容易遇到)。
|
|
85
|
+
|
|
86
|
+
第一步,二分定位——插件到底加载没有:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
:LLMHelp
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
这是插件加载时注册的全局命令,不依赖文件类型检测。能弹出帮助说明插件已加载,
|
|
93
|
+
问题在文件类型识别(跳到第三步);提示“不是编辑器命令”说明脚本根本没被
|
|
94
|
+
加载(继续第二步)。
|
|
95
|
+
|
|
96
|
+
第二步,确认脚本在 runtimepath 上(Windows 上最常见的两类原因):
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
:scriptnames
|
|
100
|
+
:echo expand('~')
|
|
101
|
+
:set runtimepath?
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`scriptnames` 输出里应能看到 `<你的家目录>\vimfiles\plugin\llm.vim`。
|
|
105
|
+
|
|
106
|
+
特别地:如果 llm.vim **在** scriptnames 列表里,但 `:LLMHelp` 却不存在——说明脚本
|
|
107
|
+
加载到一半出错中断了(命令定义在文件末尾),执行 `:messages` 查看报错,常见于
|
|
108
|
+
编码问题(见本节末尾)或 vim 版本过老缺少某功能。
|
|
109
|
+
|
|
110
|
+
llm.vim 不在 scriptnames 里时:
|
|
111
|
+
|
|
112
|
+
* HOME 不一致:安装脚本写入的是 `%USERPROFILE%\vimfiles`,而 vim 的 `~` 解析到了别处
|
|
113
|
+
(比如环境变量 `HOME` 指向网络盘)。对比 `expand('~')` 与安装输出路径,把
|
|
114
|
+
vimfiles 拷到 vim 实际的家目录即可。(新版 install.py 已按 vim 的规则解析家目录,
|
|
115
|
+
并会主动询问 vim 确认,两处不一致时两处都装——重跑安装脚本通常可直接修复。)
|
|
116
|
+
* 运行的 vim 和安装目标不是同一个:Neovim 不读 `~/vimfiles`(Windows 上配置在
|
|
117
|
+
`~/AppData/Local/nvim`);WSL 里的 vim 读的是 Linux 家目录;微软商店版 vim 的
|
|
118
|
+
路径也有差异。
|
|
119
|
+
|
|
120
|
+
第三步,确认 vimrc 和文件类型检测:
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
:echo $MYVIMRC
|
|
124
|
+
:set filetype?
|
|
125
|
+
:filetype
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
* `$MYVIMRC` 为空说明你以为在改的 vimrc 根本没被读取。Windows 上 vimrc 放在家
|
|
129
|
+
目录,名字 `_vimrc` 或 `.vimrc` 都行;注意记事本的“隐藏已知文件扩展名”可能
|
|
130
|
+
让它实际变成 `_vimrc.txt`。
|
|
131
|
+
* vimrc 里需要 `filetype plugin on`(它同时开启检测和插件加载,本插件的
|
|
132
|
+
`ftdetect` 钩子就是在这一步生效的)。编辑 `.llm` 文件时 `set filetype?` 应显示
|
|
133
|
+
`llm`。
|
|
134
|
+
* 如果你的 vimfiles 里有自定义的 `filetype.vim`,它会整体替换内置版本,需要自行
|
|
135
|
+
保证 `ftdetect` 目录仍被加载。
|
|
136
|
+
|
|
137
|
+
最后看一眼加载期报错:`:messages`。中文 Windows 上若 vim 默认 cp936 编码,脚本里
|
|
138
|
+
的 UTF-8 中文注释偶发解析问题,可在 vimrc 开头加 `set encoding=utf-8`。
|
|
139
|
+
|
|
140
|
+
## 用法
|
|
141
|
+
|
|
142
|
+
这里主要介绍原理。
|
|
143
|
+
|
|
144
|
+
我们的应用的主体是一个python程序,命令名为 `llm-with-vim`(旧名 `llm_engine` /
|
|
145
|
+
`llm-engine` 仍可用,是同一个程序的过渡别名)。如果你本地已经安装了ollama,简
|
|
146
|
+
单的用法是这样:
|
|
147
|
+
```bash
|
|
148
|
+
echo "User: hello" | llm-with-vim
|
|
149
|
+
```
|
|
150
|
+
或者
|
|
151
|
+
```bash
|
|
152
|
+
llm-with-vim < chat.llm
|
|
153
|
+
```
|
|
154
|
+
这个程序的使用方式就是把你输入的对话提交给LLM,然后把对话本身,以及
|
|
155
|
+
LLM的回答,一起返回给你。
|
|
156
|
+
|
|
157
|
+
当然,这种用法并不方便,我们设计的使用方式是通过插件来调用这个命令,这样,你一
|
|
158
|
+
边编辑一个文本文件,一边就可以提交请求给LLM,然后基于回答继续编辑这个上下文,再
|
|
159
|
+
做下一次提交。这样你就会成为你和LLM这段因果的时空控制者,你不是和它不断创建“未
|
|
160
|
+
来”,而是反复改变“过去”和“当下”。
|
|
161
|
+
|
|
162
|
+
下面我们主要用vim为例来介绍这个程序的用法,`vscode`和`micro`的对应用法可以参考
|
|
163
|
+
[vscode/README.md](vscode/README.md),和
|
|
164
|
+
[micro/llm_micro/help/llm-micro.md](micro/llm_micro/help/llm-micro.md)。
|
|
165
|
+
|
|
166
|
+
安装`vim插件`后,`vim`会把`.llm`后缀名的文件特殊对待(特有的语法高亮,特有的热
|
|
167
|
+
键,特有的缩写等等)。
|
|
168
|
+
|
|
169
|
+
`.llm`就是个普通文本文件,里面的内容要求是这样的:
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
Configure: {'engine_type': 'ollama', 'server_addr': 'default',
|
|
173
|
+
'model': 'qwen2.5:0.5b', 'keep_alive': 36,
|
|
174
|
+
'max_tokens': 512, 'temperature': 1}
|
|
175
|
+
System: 你是一个中学数学老师,协助我解决一些中学数学问题。
|
|
176
|
+
@// 这是临时注释,提交时会被忽略;在替换模式下会被清理
|
|
177
|
+
@## 这是长久注释,不提交给AI,但会保留在文件中
|
|
178
|
+
User: 解如下方程:2x^2 + 3x -10=0。
|
|
179
|
+
不需要过程解释。
|
|
180
|
+
Assistant: ...
|
|
181
|
+
User: 有没有其他解法?
|
|
182
|
+
....
|
|
183
|
+
```
|
|
184
|
+
`llm文件`中以“xxx: ”开头的行称为一个“角色发言”。当前实现也兼容 `System:`、
|
|
185
|
+
`User:`、`Assistant:`、`Tool:`、`Configure:` 后面不带空格,以及使用全角冒号 `:`
|
|
186
|
+
的写法。角色发言后的每一行,在遇到新的角色发言前,都是这个角色发言的一部分。
|
|
187
|
+
|
|
188
|
+
除了User的发言,其他部分都是可选的。当前实现要求提交内容中至少有一条 `User:` 消
|
|
189
|
+
息;没有角色前缀的普通文本会被视为无效上下文并给出模板提示。
|
|
190
|
+
|
|
191
|
+
下面是支持的角色:
|
|
192
|
+
|
|
193
|
+
* User: 这表示你的发言
|
|
194
|
+
|
|
195
|
+
* System:这通常用于给整个对话定调,它的地位比其他角色的地位稍高,通常LLM会对这
|
|
196
|
+
个发言偏袒一些,在上下文过长的时候也会优先保护它。但它也不是绝对控制所有发言
|
|
197
|
+
的。
|
|
198
|
+
|
|
199
|
+
* Assistant:这是LLM的发言
|
|
200
|
+
|
|
201
|
+
* Configure:这是给Agent(也就是llm_engine)说的话,就是用来配置用的,通常你需
|
|
202
|
+
要这个选择引擎,配置服务器地址,选择工具等等。
|
|
203
|
+
|
|
204
|
+
给LLM发送的上下文从文件开头算起,一直到你发送的位置为止,后面的内容自动忽略。发
|
|
205
|
+
送方法通常是在最后一个User发言后输入jj,或者按\<F1\>,这整个上下文都会发给LLM,
|
|
206
|
+
并且把它的回答补充到User后面,而原来在User发言后面的内容都不会改变。
|
|
207
|
+
|
|
208
|
+
所以,如果你临时不想发什么东西出去,你可以暂时放在别的文件中,或者直接留在本文
|
|
209
|
+
件的最后。
|
|
210
|
+
|
|
211
|
+
这不改变这仍是一个文本文件,你可以用所有你喜欢的vim编辑功能来编辑这个文件。你可
|
|
212
|
+
以继续决定向下开辟你和LLM的未来,也可以编辑你和它交往的过往。每段这样的历史都可
|
|
213
|
+
以独立存盘,独立重新使用,可以用git进行版本管理。
|
|
214
|
+
|
|
215
|
+
如果在输出的过程中需要中止请求,可以按K键(原K键功能被禁止了)。注意这里不要用
|
|
216
|
+
Ctrl-C,Ctrl-C仍是打断当前vim操作的功能,这不会中止请求任务。
|
|
217
|
+
|
|
218
|
+
\<F2\>映射到outline功能,可以显示一个新窗口给出所有User的位置,你可以通过这个来
|
|
219
|
+
定位到特定的问题,只要移动到特定的行然后回车就可以跳转到那个问答上。
|
|
220
|
+
|
|
221
|
+
完整的命令列表可以通过:help llm查看。
|
|
222
|
+
|
|
223
|
+
如果一时忘了快捷键,可以在 Vim 里执行 `:LLMHelp` 或按 `<F4>` 查看快速帮助。
|
|
224
|
+
|
|
225
|
+
如果你在`micro`中使用,对应快捷键是:`F1` 提交、`Shift+K` 中断、`F2` 大纲、`F3`
|
|
226
|
+
图片预览。
|
|
227
|
+
|
|
228
|
+
### 扩展模式和替换模式
|
|
229
|
+
|
|
230
|
+
llm_engine默认工作在替换模式,就是你输入的上下文,它会做一些过滤会产生一些调试
|
|
231
|
+
日志,替换你原来的上下文。这是llm_engine的完整功能。但这种功能在部分编辑器上面
|
|
232
|
+
上下文变得很长的时候会影响速度,因为可能要一下提供数千甚至上万行的文本。所以我
|
|
233
|
+
们现在也提供--append模式,加上这个参数,llm_engine不过滤输入,而是直接输出LLM的
|
|
234
|
+
响应。
|
|
235
|
+
|
|
236
|
+
我们现在在vim和vscode上默认使用扩展模式,以提高显示效率,你仍可以使用全功能的替
|
|
237
|
+
换模式,在vim上使用JJ输入或者F5提交请求,就是对应的模式。其他插件可以参考其他参
|
|
238
|
+
加的帮助。
|
|
239
|
+
|
|
240
|
+
### 引用图片和调用工具
|
|
241
|
+
|
|
242
|
+
如果LLM支持(即模型具备视觉能力),对话中可以引用本地图片和调用工具。其中引用
|
|
243
|
+
本地图片的方法是在上下文中增加“$$图片本地路径$$”这样的描述,代理会把图片附加
|
|
244
|
+
到这个角色的发言中。细节:
|
|
245
|
+
|
|
246
|
+
* 语法仅在 User 角色的发言中生效,其他角色中出现同样的记号不会被解释
|
|
247
|
+
* 相对路径基于 llm 文件所在目录(由编辑器插件自动传入)解析
|
|
248
|
+
* 提交时引用处会替换为“[IMAGE:路径]”占位符一并发给 LLM;如果文件不存在,
|
|
249
|
+
占位符变为“[IMAGE_NOT_FOUND:路径]”,从提交结果中可以直接看出来
|
|
250
|
+
|
|
251
|
+
工具是个全局的概念,这可以在Configure角色中告知LLM有那些工具可用。像这样:
|
|
252
|
+
```
|
|
253
|
+
Configure: {'model': 'qwen3:1.7b', 'tools': ['read', 'bash', 'search']}
|
|
254
|
+
User: 请读取 /etc/hostname 并告诉我这台机器的名称
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
当前可用工具:
|
|
258
|
+
|
|
259
|
+
| 工具名 | 功能 |
|
|
260
|
+
|--------|------|
|
|
261
|
+
| read | 读取文件内容 |
|
|
262
|
+
| write | 写入/创建文件 |
|
|
263
|
+
| edit | 精确字符串替换编辑文件 |
|
|
264
|
+
| bash | 执行 bash 命令 |
|
|
265
|
+
| search | grep 正则搜索文件内容 |
|
|
266
|
+
| list\_dir | 列出目录内容 |
|
|
267
|
+
| python | 执行 Python 代码片段 |
|
|
268
|
+
| web\_fetch | 获取网页文本内容 |
|
|
269
|
+
| view\_image | 查看图片 |
|
|
270
|
+
|
|
271
|
+
每个工具是 `llm_engine/plugins/tools/` 下的一个插件文件,由
|
|
272
|
+
`llm_engine/plugins/plugins.json` 清单选择加载;用户也可在
|
|
273
|
+
`~/.config/llm-with-vim/plugins.json` 清单中登记自己的工具插件或排除内置工具
|
|
274
|
+
(详见 `docs/plugin_architecture_design.md`)。通过`max_tool_rounds`(默认10)可以
|
|
275
|
+
控制单次对话中工具调用的最大轮数。
|
|
276
|
+
|
|
277
|
+
在`vim插件`中,`allTools`缩写会展开成所有工具的配置,可以用这种方法建立工具的基
|
|
278
|
+
础配置模板。
|
|
279
|
+
|
|
280
|
+
### 使用思维链
|
|
281
|
+
|
|
282
|
+
思维链可以优化模型的输出,这需要模型支持。如果你使用的是ollama,通过ollama show
|
|
283
|
+
<model>命令可以查看模型是否有thinking这个Capability。如果有,在`llm_with_vim`的
|
|
284
|
+
配置中可以用'thinking': True激活。
|
|
285
|
+
|
|
286
|
+
思维过程会以一次性注释的形式输出,下次提交的时候会被全部忽略并且丢弃,所以如果
|
|
287
|
+
你需要保留,就把它拷贝出提交范围。
|
|
288
|
+
|
|
289
|
+
### Configure
|
|
290
|
+
|
|
291
|
+
User/System/Assistant都是LLM或者人说的话,所以是自然语言的。而Configure是给Agent
|
|
292
|
+
说的话,Agent就是我们的传统电脑,所以必须是“结构化”的。这里支持 JSON 或 Python
|
|
293
|
+
字典格式(内部会按结构解析)
|
|
294
|
+
的定义。
|
|
295
|
+
|
|
296
|
+
通常你不用学,一开始可以完全不写,让llm_engine自动给你生成一个,然后修改就行。
|
|
297
|
+
我们的插件也通过vim的缩写(:ab[breviate])提供了一组模板,比如:
|
|
298
|
+
|
|
299
|
+
* configO 本地ollama配置模板
|
|
300
|
+
* configAli Ali云配置模板
|
|
301
|
+
* configHj 海鲸配置模板
|
|
302
|
+
* configZp 智谱配置模板
|
|
303
|
+
|
|
304
|
+
本地之外的模型通常需要配置apikey,模板中通常只有一个占位符,需要自己修改成你自
|
|
305
|
+
己的API key。如果你不想每个llm文件都出现这个信息,也可以写到用户目录配置中:
|
|
306
|
+
`~/.config/llm-with-vim/config.json`(新路径,推荐)。
|
|
307
|
+
当前仍兼容旧路径 `~/.config/llm_engine/llm_engine.json`:首次运行时会自动把
|
|
308
|
+
旧配置迁移到新路径并在输出中提示(原文件保留,确认无误后可删除)。
|
|
309
|
+
|
|
310
|
+
引擎名、服务器地址和模型名都支持别名,比如 server_addr 写 'default' 会解析为
|
|
311
|
+
localhost,model 写 'qwen' 会解析为 'qwen2.5:0.5b'。可用别名定义在各引擎的
|
|
312
|
+
provider 描述文件中(见下文“自定义引擎”),你也可以在描述文件里增加自己的
|
|
313
|
+
别名。
|
|
314
|
+
|
|
315
|
+
### 其他辅助语法
|
|
316
|
+
|
|
317
|
+
llm文件还提供一些辅助语法,以便更容易维护代码逻辑。这包括:
|
|
318
|
+
|
|
319
|
+
* 头文件:llm支持类似C语言的头文件机制,可以通过@@inc前缀说明其他包含文件。具体
|
|
320
|
+
语法也很简单,在某行顶格写"@@inc xxx.h"就可以了,xxx.h中的内容会无条件包含到所
|
|
321
|
+
处的位置。具体细节参考[@@inc原语设计思路](docs/inc_directive.md)。
|
|
322
|
+
|
|
323
|
+
* 临时注释:@// 开头的语句被看作临时注释,提交请求给llm\_engine时会被忽略,不会进
|
|
324
|
+
入LLM上下文。是否会在文件中“自动消失”取决于提交模式:替换模式会清理,追加模式会
|
|
325
|
+
保留原文本(但仍不会提交给LLM)。
|
|
326
|
+
|
|
327
|
+
* 长久注释:@## 开头的语句被看作长久注释,这种语句也会被llm\_engine忽略。这个地方
|
|
328
|
+
有个风险是:如果AI返回的语句中也有这样的行,也会被忽略。
|
|
329
|
+
|
|
330
|
+
* 引用图片:语法为 `$$图片路径$$`,仅在 User 角色发言中生效,详见前文
|
|
331
|
+
“引用图片和调用工具”一节。
|
|
332
|
+
|
|
333
|
+
这些辅助语法最大的风险是如果角色也有一样的输出,可能导致llm\_engine误解释,我们
|
|
334
|
+
已经尽量使用比较特殊的符号组合了,但不能保证LLM会怎么返回,所以,只能请你自行注
|
|
335
|
+
意。
|
|
336
|
+
|
|
337
|
+
### 全局配置
|
|
338
|
+
|
|
339
|
+
除了通过单个llm文件配置单个会话的参数,llm-with-vim也可以通过独立配置文件进行全
|
|
340
|
+
局配置(推荐 `~/.config/llm-with-vim/config.json`,旧文件
|
|
341
|
+
`~/.config/llm_engine/llm_engine.json` 会被自动迁移),这些配置分三层:
|
|
342
|
+
|
|
343
|
+
* 默认配置:这个内嵌在llm\_engine的模块目录中
|
|
344
|
+
* 用户配置:推荐放在$HOME/.config/llm-with-vim/config.json,兼容旧目录
|
|
345
|
+
$HOME/.config/llm\_engine/
|
|
346
|
+
* 文件配置:这个就是前面Configure角色的定义
|
|
347
|
+
|
|
348
|
+
后面的配置会覆盖前面的配置,通常来说,全局的配置,比如API Key,可以放到用户配置
|
|
349
|
+
上,单个会话专门的配置,则可以配置在单个文件中,至于默认配置,这是工具自身的一
|
|
350
|
+
部分,可以拷贝出来当作用户配置的模板。
|
|
351
|
+
|
|
352
|
+
你也可以用这个部分设置一个默认的引擎和模型,避免每次创建llm都要写配置。
|
|
353
|
+
```json
|
|
354
|
+
{
|
|
355
|
+
"config": {
|
|
356
|
+
"engine_type": "ollama",
|
|
357
|
+
"server_addr": "localhost",
|
|
358
|
+
"model": "qwen2.5:0.5b",
|
|
359
|
+
"keep_alive": 3600
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### 环境变量
|
|
365
|
+
|
|
366
|
+
* `LLM_ENGINE_CONFIG`:指定用户配置文件的完整路径(默认
|
|
367
|
+
`~/.config/llm-with-vim/config.json`)
|
|
368
|
+
* `LLM_ENGINE_DEBUG`:等价于 Configure 里写 `'debug': True`
|
|
369
|
+
* `LLM_FILE_DIR`:工具和图片的相对路径基准目录,编辑器插件会自动设置为当前
|
|
370
|
+
llm 文件所在目录
|
|
371
|
+
* `LLM_FILE_ENCODING`:重设标准流编码(主要供 Windows 使用,默认 utf-8)
|
|
372
|
+
|
|
373
|
+
## 一些技巧
|
|
374
|
+
|
|
375
|
+
* 如果你不知道当前环境有什么可用,把Configure的engine_type设置为TELLME再提交
|
|
376
|
+
一次,引擎会输出一份环境清单:可用引擎(含用户自建的)、可用工具、当前生效的
|
|
377
|
+
三层合并配置。首次输错提交时的模板提示也会指引到这里。想知道某台服务器上具体
|
|
378
|
+
有什么模型,再把model设置为TELLME提交,支持查询的引擎(比如ollama)会返回
|
|
379
|
+
模型列表。
|
|
380
|
+
|
|
381
|
+
* ollama第一次使用某个模型会比较慢,可能因此会超时,可以通过如下Configure参数调
|
|
382
|
+
整超时时间(以秒为单位):
|
|
383
|
+
|
|
384
|
+
* keep_alive=60。定义模型使用后,在内存中保留多久
|
|
385
|
+
* connect_timeout=30。定义连接超时时间
|
|
386
|
+
* read_timeout=1800。定义请求超时时间
|
|
387
|
+
|
|
388
|
+
* 如果你不知道引擎是什么协议,可以尝试用通用的OpenAI协议去尝试一下,只要引擎的
|
|
389
|
+
名字和标准模型不一样,就会尝试用OpenAI的协议去访问。如果你不确定你的请求是否
|
|
390
|
+
和请求的一致,可以在Configure中加一个"'verbose': True"的参数,这样输出中会包
|
|
391
|
+
含每次llm请求的信息,让你看看是否符合期望。
|
|
392
|
+
|
|
393
|
+
* 需要看发送给LLM的原始报文时,可以在Configure中加一个"'debug': True"参数(或
|
|
394
|
+
设置环境变量LLM_ENGINE_DEBUG),引擎会把每次请求的完整JSON(URL、headers、
|
|
395
|
+
消息内容)打印出来;响应制式同样收齐后聚合成一个等价的完整响应对象一次性输出
|
|
396
|
+
(分片content拼接、tool_calls重组、保留finish_reason/usage等元数据),不再是
|
|
397
|
+
每个流式分片一行。图片base64会截断、auth密钥会脱敏。若只需要看请求不看响应,
|
|
398
|
+
可用"'debug': 'request'"减少输出。该输出在vim的追加模式下同样可见,调试完删
|
|
399
|
+
掉这些@//注释行即可(它们不会回传给LLM)。
|
|
400
|
+
|
|
401
|
+
## 当前支持的引擎
|
|
402
|
+
|
|
403
|
+
* [Ollama](https://ollama.com/),参考配置:Configure: {'engine_type': 'ollama',
|
|
404
|
+
'model': 'qwen2.5:0.5b', 'keep_alive': 3600}
|
|
405
|
+
|
|
406
|
+
* [DeepSeek](https://www.deepseek.com/) ,参考配置:Configure: {'engine_type':
|
|
407
|
+
'deepseek', 'model': 'deepseek-chat', 'auth': 'Bearer sk-xxx'}
|
|
408
|
+
|
|
409
|
+
* [智谱 AI](https://open.bigmodel.cn/),参考配置:Configure: {'engine_type':
|
|
410
|
+
'zhipu', 'model': 'glm-4.7', 'auth': 'Bearer your-api-key'}
|
|
411
|
+
|
|
412
|
+
* [阿里云百炼](https://dashscope.aliyuncs.com/) ,参考配置:Configure:
|
|
413
|
+
{'engine_type': 'ali', 'model': 'deepseek-r1', 'auth': 'Bearer sk-xxx'}
|
|
414
|
+
|
|
415
|
+
* [海鲸 AI](https://www.atalk-ai.com/) ,参考配置:Configure: {'engine_type':
|
|
416
|
+
'haijing', 'model': 'DeepSeek-R1', 'auth': 'Basic xxx'}
|
|
417
|
+
|
|
418
|
+
* [llama.cpp](https://github.com/ggerganov/llama.cpp) ,参考配置:Configure:
|
|
419
|
+
{'engine_type': 'llama', 'server_addr': 'localhost:8080'}
|
|
420
|
+
|
|
421
|
+
* 对于任何兼容 OpenAI API 格式的服务(如
|
|
422
|
+
[vLLM](https://github.com/vllm-project/vllm))或者llama-server(这个连模型的
|
|
423
|
+
名字都可以随便写),可以使用任意引擎名称,参考配置:Configure: {'engine_type':
|
|
424
|
+
'vllm', 'server_addr': 'localhost:8000', 'model': 'Qwen/Qwen2.5-7B-Instruct'}
|
|
425
|
+
|
|
426
|
+
### 自定义引擎
|
|
427
|
+
|
|
428
|
+
每个引擎的行为由一个 JSON 描述文件(provider 描述)驱动,内置描述在
|
|
429
|
+
`llm_engine/providers/` 目录(ollama、deepseek、zhipu、ali、haijing、llama、
|
|
430
|
+
openai\_compat)。上条“任意引擎名称”的原理就是:引擎不认识这个名字时,自动回
|
|
431
|
+
退到 openai\_compat 描述用 OpenAI 协议访问。
|
|
432
|
+
|
|
433
|
+
你也可以增加自己的引擎:拷贝一份内置描述到 `~/.config/llm-with-vim/providers/`
|
|
434
|
+
下修改(服务地址、默认模型、鉴权方式、模型查询地址、别名等都是字段化的),文件
|
|
435
|
+
名即引擎名,用户描述会覆盖同名的内置描述。字段含义和设计思路参考
|
|
436
|
+
[ContextForge架构设计](docs/contextforge_architecture_design.md)。
|
|
437
|
+
|
|
438
|
+
## 已知问题
|
|
439
|
+
|
|
440
|
+
* micro在Windows下不支持异步模式,需要提交请求后只能等待全部回答返回后才能看到
|
|
441
|
+
显示。这会造成一种“服务器迟迟没有响应”的错觉。如果你是因为不熟悉vim的键位操作
|
|
442
|
+
所以用micro,我建议使用evim(vim包里自带),这用起来也是和记事本差不多的。
|
|
443
|
+
|
|
444
|
+
* 部分LLM服务平台可能会拒绝非通用AI引擎发的请求,所以通过本应用发送请求,有可能
|
|
445
|
+
被这些平台拒绝。
|