在使用ollama做大模型问答的过程中,发现存在着当输入问题过长之后,模型无法回答的问题。经过查询资料,这与一个叫做num_ctx的参数有关,它用来控制对话上下文的长度,在大模型动辄支持32k上下文的当下,ollama居然丧心病狂地把这个参数默认设成了2048也就是2.048k,真是叔可忍婶不可忍!
下面记录一下在尝试解决这个问题的过程中,最终成功的几种方法和失败的种种方案。
一劳永逸版:修改模型参数
ollama的每个模型都有个配置文件,这里需要在原基础上生成一个新的配置文件,再根据这个配置文件去生成新的模型,以qwen2
为例走一遍流程。
首先获取qwen2
的配置文件:
ollama show --modelfile qwen2 > Modelfile
此时本地多了一个Modelfile
文件,直接打开。其内容是这样的:
# Modelfile generated by "ollama show"
# To build a new Modelfile based on this, replace FROM with:
# FROM qwen2:latest
FROM /usr/share/ollama/.ollama/models/blobs/sha256-43f7a214e5329f672bb05404cfba1913cbb70fdaa1a17497224e1925046b0ed5
TEMPLATE "{{ if .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{ end }}{{ if .Prompt }}<|im_start|>user
{{ .Prompt }}<|im_end|>
{{ end }}<|im_start|>assistant
{{ .Response }}<|im_end|>
"
PARAMETER stop <|im_start|>
PARAMETER stop <|im_end|>
按照提示修改成这样:
# Modelfile generated by "ollama show"
# To build a new Modelfile based on this, replace FROM with:
# FROM qwen2:latest
FROM qwen2:latest
PARAMETER num_ctx 32000
TEMPLATE "{{ if .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{ end }}{{ if .Prompt }}<|im_start|>user
{{ .Prompt }}<|im_end|>
{{ end }}<|im_start|>assistant
{{ .Response }}<|im_end|>
"
PARAMETER stop <|im_start|>
PARAMETER stop <|im_end|>
...
然后根据这个配置文件生成新的qwen2:ctx32k
模型:
ollama create -f Modelfile qwen2:ctx32k
尝试查看模型参数:
ollama show qwen2:ctx32k
临时抱佛脚之命令行生效
这个很简单,直接在命令行中输入/set parameter num_ctx 32000
,但是缺点是只能在命令行中生效,通过API调用是无效的,下次从命令行再启动也是要重新输的。
临时抱佛脚之API生效
通过API访问ollama时,传入num_ctx=32000
这个参数来指定上下文长度,函数示例如下。
def chat(self, messages :str, history:list[dict]=[], **kwargs):
url = "http://{}:{}/api/chat".format(self.host, self.port)
data = {
"model": self.model_name,
"messages": history+[
{
"role": "user",
"content": messages
}
],
"stream": False,
"options": {
"num_ctx": 32000,
"temperature": 0.9
},
# "format": "json",
"keep_alive": self.keep_alive
}
data.update(kwargs)
response = requests.post(url, json=data, stream=False)
response.raise_for_status()
json_data = json.loads(response.text)
return json_data["message"]
没啥卵用之OpenAI API传参
由于项目是基于OpenaiAPI的,所以不能直接向上面发送请求,而是要先封装成下面这种形式:
model = ChatOpenAI(
streaming=streaming,
verbose=verbose,
callbacks=callbacks,
openai_api_key=config.get("api_key", "EMPTY"),
openai_api_base=config.get("api_base_url", fschat_openai_api_address()),
model_name=model_name,
temperature=temperature,
max_tokens=max_tokens,
openai_proxy=config.get("openai_proxy"),
**kwargs
)
我尝试在里面再加入num_ctx=32000
这个参数,直接报了无法解析的错误,失败。
没啥卵用之OpenAI 问答传参
因为不知道/set parameter num_ctx 32000
这句话只能在命令行中生效,因此我尝试通过model.predict()
和model.invoke()
去传入这句话去修改参数,也失败了。