关于llamasharp 大模型多轮对话,模型对话无法终止,或者输出角色标识User:,或者System等角色标识问题。

最近在使用llamasharp 本地加载大模型输出,模型启动,模型会话,模型使用cuda都没有任何问题,但是到最后一步,让大模型输出内容的时候发现,要么输出内容重复,要么输出角色标识,自问自答,而且一直自问自答,用户体验相当糟糕。

查看llamasharp 文档和源码,发现已经在 ChatSession 中实现了将gguf的自带模板通过metedata中导出,然后格式化后作为模型template 注入了,那么就以为着我们不需要在构建提示词对话模板和设置停止词了,但是我发现,模型通过InferenceParams 设置的参数确实注入到llama.cpp 中起作用,但是就是system 和 user 消息的模板没有注入到llama.cpp 中,所以,我们直接通过AddSystemMessage 添加第一条系统提示消息,后继续使用user 角色对模型问答的时候,它就不遵循对话模板来一文一答了,而是自问自答,而且还不会停止,直到输出maxtokens.

cs 复制代码
 try
 {
     ModelDataInfo? modelInfo = GetModelByName(ModelName);
     if (modelInfo == null) return;
     if (modelInfo?.ModelWeight == null) await StartModel((int)modelInfo?.ModelId!);
     SessionDataInfo? sessionInfo = await CreateSession(SessionId,modelInfo,SystemText);
     if (sessionInfo == null) return;
     if (InferenceParam != null) await SetInferenceParam(sessionInfo.SessionId!,InferenceParam);
     if (sessionInfo.SessionChat == null) return;
     sessionInfo.SessionHistory?.AddMessage(AuthorRole.User,UserText);
     StringBuilder Assistant = new StringBuilder();
     await foreach (var text in sessionInfo.SessionChat.ChatAsync(new ChatHistory.Message(AuthorRole.User,UserText),true,sessionInfo.SessionInference))
     {
         if (InferenceParam != null && InferenceParam.AntiPrompts.Contains(text))
         {
             //break;
         }
         RetMessage(text);
         Assistant.Append(text);
     }
     sessionInfo.SessionHistory?.AddMessage(AuthorRole.Assistant,Assistant.ToString());

最后解决方案是,System 消息提示词如下:

你是一个人工智能政务办公助手,必须严格遵守以下要求:

  1. 使用中文回答。

  2. 不要在你的回复中包含任何特殊标记或角色标签。

3.不要输出重复的内容。

4.只回答用户的问题,不要提出新问题。

  1. 不要模拟对话,只给出答案。

  2. 回答完成后就停止,不要继续生成。

User 对话的提示词如下:

<|im_start|>user{0}<|im_end|><|im_start|>assistant //注意这里的{0},对应string.fomat 对话具体内容。

然后终于解决了他不会自问自答输出角色标识的问题了,但是又发现一直输出直到达到最大token限制,这明显不符合预期,查询了大量资料和看了llamasharp 源码没发现问题,最后看了看llama.cpp 的源码了,llama系列的模型,默认保留了一个\n\n 的截断词,注意是不能转义的\n\n,模型即便输出需要两次换行它也不会输出这个标记,只要输出这个标记就以为回答完了,那么就知道了.

cs 复制代码
            InferenceParams InferenceParam = new InferenceParams();
            InferenceParam.MaxTokens = Inference.InferTokens;
            InferenceParam.TokensKeep = Inference.InferKeep;
            InferenceParam.DecodeSpecialTokens = Inference.InferSpecial;
            InferenceParam.AntiPrompts = new List<string>() {@"\n\n"};  //Inference.InferPromptAnti!.Split(",").ToList();

其他的截断提示词先不管,设置@"\n\n", 基本能满足要求。调试时候正常了,但是我通过前端设置了 多个提示词,通过,分隔,然后读取到list<string> 对象里面的时候发现又不起作用了,这里有个小坑,这个分隔字符串不能加双引号,而且不能设置成 "\\n\\n"通过转移来识别,因为c#默认下的\\转义为\ ,是输出了文本,不是换行符,所以处理的时候 @"截至词",才能匹配llama.cpp, 其实这是c# 到c++语法的一个差异性导致的,如果不同时精通这两种语言,估计始终找不到问题所在。

经过这些处理,一切正常,可以平替了ollama和dify 以及Inferences ,实现本地化自开发人工智能应用了。

相关推荐
web打印社区3 分钟前
web-print-pdf:突破浏览器限制,实现专业级Web静默打印
前端·javascript·vue.js·electron·html
橘子师兄21 分钟前
C++AI大模型接入SDK—ChatSDK封装
开发语言·c++·人工智能·后端
RFCEO22 分钟前
前端编程 课程十三、:CSS核心基础1:CSS选择器
前端·css·css基础选择器详细教程·css类选择器使用方法·css类选择器命名规范·css后代选择器·精准选中嵌套元素
桂花很香,旭很美23 分钟前
基于 MCP 的 LLM Agent 实战:架构设计与工具编排
人工智能·nlp
Christo324 分钟前
TFS-2026《Fuzzy Multi-Subspace Clustering 》
人工智能·算法·机器学习·数据挖掘
五点钟科技32 分钟前
Deepseek-OCR:《DeepSeek-OCR: Contexts Optical Compression》 论文要点解读
人工智能·llm·ocr·论文·大语言模型·deepseek·deepseek-ocr
人工智能AI技术35 分钟前
【C#程序员入门AI】本地大模型落地:用Ollama+C#在本地运行Llama 3/Phi-3,无需云端
人工智能·c#
Agentcometoo44 分钟前
智能体来了从 0 到 1:规则、流程与模型的工程化协作顺序
人工智能·从0到1·智能体来了·时代趋势
Amumu121381 小时前
Vuex介绍
前端·javascript·vue.js
工程师老罗1 小时前
什么是目标检测?
人工智能·目标检测·计算机视觉