探索 LLamaWorker 本地大模型API服务的新功能:函数调用

news2024/12/27 13:19:59

LLamaWorker 是一个基于 LLamaSharp 项目开发的可以在本地运行大模型服务,并提供与 OpenAI / Azure OpenAI 兼容的 API。同时,通过工具提示词的配置,提供函数调用 Function Call 能力,为开发者提供更多的可能。

1. 背景

在人工智能领域,大型语言模型(LLM)正在以其强大的自然语言处理能力改变游戏规则。为了满足开发者将这些模型集成到自己应用程序中的需求,我开发了 LLamaWorker。

LLamaWorker 是一个基于 LLamaSharp 项目开发的可以在本地运行大模型服务,并提供与 OpenAI / Azure OpenAI 兼容的 API。除了兼容性,LLamaWorker 还提供了一些其他功能,例如多模型支持、流式响应、嵌入支持、对话模版等。同时,对于支持函数调用的模型,通过工具提示词的配置,就可以使用函数调用 Function Call 能力。

LLamaWorker 项目地址:https://github.com/sangyuxiaowu/LLamaWorker?wt.mc_id=DT-MVP-5005195

2. 函数调用功能

经过这段时间的开发,LLamaWorker 迎来了重大更新。这次更新不仅优化了现有功能,还新增了许多实用特性,尤其是函数调用功能。它允许开发者在模型生成的对话中插入函数调用,从而实现更复杂的任务处理。以下是函数调用的配置示例:

"ToolPromptConfig": [
    {
      "PromptConfigDesc": "千问模板",
      "FN_NAME": "✿FUNCTION✿",
      "FN_ARGS": "✿ARGS✿",
      "FN_RESULT": "✿RESULT✿",
      "FN_EXIT": "✿RETURN✿",
      "FN_STOP_WORDS": [ "✿RESULT✿", "✿RETURN✿" ],
      "FN_CALL_TEMPLATE_INFO": {
        "zh": "# 工具\n\n## 你拥有如下工具:\n\n{tool_descs}",
        "en": "# Tools\n\n## You have access to the following tools:\n\n{tool_descs}"
      },
      "FN_CALL_TEMPLATE_FMT": {
        "zh": "## 你可以在回复中插入零次、一次或多次以下命令以调用工具:\n\n{0}: 工具名称,必须是[{4}]之一。\n{1}: 工具输入\n{2}: 工具结果\n{3}: 根据工具结果进行回复,需将图片用![](url)渲染出来",
        "en": "## When you need to call a tool, please insert the following command in your reply, which can be called zero or multiple times according to your needs:\n\n{0}: The tool to use, should be one of [{4}]\n{1}: The input of the tool\n{2}: Tool results\n{3}: Reply based on tool results. Images need to be rendered as ![](url)"
      },
      "FN_CALL_TEMPLATE_FMT_PARA": {
        "zh": "## 你可以在回复中插入以下命令以并行调用N个工具:\n\n{0}: 工具1的名称,必须是[{4}]之一\n{1}: 工具1的输入\n{0}: 工具2的名称\n{1}: 工具2的输入\n...\n{0}: 工具N的名称\n{1}: 工具N的输入\n{2}: 工具1的结果\n{2}: 工具2的结果\n...\n{2}: 工具N的结果\n{3}: 根据工具结果进行回复,需将图片用![](url)渲染出来",
        "en": "## Insert the following command in your reply when you need to call N tools in parallel:\n\n{0}: The name of tool 1, should be one of [{4}]\n{1}: The input of tool 1\n{0}: The name of tool 2\n{1}: The input of tool 2\n...\n{0}: The name of tool N\n{1}: The input of tool N\n{2}: The result of tool 1\n{2}: The result of tool 2\n...\n{2}: The result of tool N\n{3}: Reply based on tool results. Images need to be rendered as ![](url)"
      },
      "ToolDescTemplate": {
        "zh": "### {0}\n\n{1}: {2} 输入参数:{3}",
        "en": "### {0}\n\n{1}: {2} Parameters: {3}"
      }
    }
  ]

在这个配置中,我们使用了 Qwen2 模型提供的工具配置模板,通过配置 ToolPromptConfig,我们可以定义工具的调用方式、参数、结果等信息。这样一来,我们就可以在对话中插入函数调用,实现更多的功能。

该模板已经测试通过,当然你也可以进行调优使用。后续会提供并测试 Llama 3.1 的函数调用模板。

对于工具提示词的生成,我们新增了 ToolPromptGenerator 类,用于处理工具提示词,核心代码如下:

/// <summary>
/// 生成工具提示词
/// </summary>
/// <param name="req">原始对话生成请求</param>
/// <param name="tpl">模版序号</param>
/// <param name="lang">语言</param>
/// <returns></returns>
public string GenerateToolPrompt(ChatCompletionRequest req, int tpl = 0, string lang = "zh")
{
    // 如果没有工具或者工具选择为 none,则返回空字符串
    if (req.tools == null || req.tools.Length == 0 || (req.tool_choice != null && req.tool_choice.ToString() == "none"))
    {
        return string.Empty;
    }

    var config = _config[tpl];

    var toolDescriptions = req.tools.Select(tool => GetFunctionDescription(tool.function, config.ToolDescTemplate[lang])).ToArray();
    var toolNames = string.Join(",", req.tools.Select(tool => tool.function.name));

    var toolDescTemplate = config.FN_CALL_TEMPLATE_INFO[lang];
    var toolDesc = string.Join("\n\n", toolDescriptions);
    var toolSystem = toolDescTemplate.Replace("{tool_descs}", toolDesc);

    var parallelFunctionCalls = req.tool_choice?.ToString() == "parallel";
    var toolTemplate = parallelFunctionCalls ? config.FN_CALL_TEMPLATE_FMT_PARA[lang] : config.FN_CALL_TEMPLATE_FMT[lang];
    var toolPrompt = string.Format(toolTemplate, config.FN_NAME, config.FN_ARGS, config.FN_RESULT, config.FN_EXIT, toolNames);
    return $"\n\n{toolSystem}\n\n{toolPrompt}";
}

private string GetFunctionDescription(FunctionInfo function, string toolDescTemplate)
{
    var nameForHuman = function.name;
    var nameForModel = function.name;
    var descriptionForModel = function.description ?? string.Empty;
    var parameters = JsonSerializer.Serialize(function.parameters, new JsonSerializerOptions { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) });

    return string.Format(toolDescTemplate, nameForHuman, nameForModel, descriptionForModel, parameters).Trim();
}

其实函数调用并没有那么神秘,也是提示词的艺术。在这个函数中,我们首先判断是否有工具,如果没有工具或者工具选择为 none,则返回空字符串。然后,我们根据配置生成工具提示词,包括工具描述、工具名称等信息。最后,我们根据是否并行调用生成工具提示词。

这个函数的实现非常简单,但是却非常实用。通过这个函数,我们可以在对话中插入函数调用,实现更多的功能。下面,我们来看一下如何使用函数调用功能。

3. 使用函数调用

在项目中,新增了函数调用的请求示例,在运行项目后,可以通过打开 LLamaWorker.http 文件,查看函数调用的请求示例。

###
# 测试函数调用
POST {{LLamaWorker_HostAddress}}/v1/chat/completions
Content-Type: application/json

{
  "model": "gpt-3.5-turbo",
  "messages": [
    {
      "role": "system",
      "content": "你是用户 SangYuXiaoWu 的助理,你会遵守规则。您将完成所需的步骤并在采取任何后续行动之前请求批准。\r\n如果用户不提供足够的信息让你完成一项任务,你会一直问问题,直到你有足够的信息来完成任务。"
    },
    {
      "role": "user",
      "content": "帮我给我的老板,老周写一封邮件说我要涨薪"
    }
  ],
  "tools": [
    {
      "function": {
        "name": "AuthorEmailPlanner-GenerateRequiredSteps",
        "description": "返回编写电子邮件所需的必要步骤。",
        "parameters": {
          "type": "object",
          "required": [
            "topic",
            "recipients"
          ],
          "properties": {
            "topic": {
              "type": "string",
              "description": "电子邮件内容的2-3句简要描述"
            },
            "recipients": {
              "type": "string",
              "description": "收件人的描述"
            }
          }
        }
      },
      "type": "function"
    },
    {
      "function": {
        "name": "EmailPlugin-SendEmail",
        "description": "向收件人发送电子邮件。",
        "parameters": {
          "type": "object",
          "required": [
            "recipientEmails",
            "subject",
            "body"
          ],
          "properties": {
            "recipientEmails": {
              "type": "string",
              "description": "以分号分隔的收件人电子邮件列表"
            },
            "subject": {
              "type": "string"
            },
            "body": {
              "type": "string"
            }
          }
        }
      },
      "type": "function"
    }
  ],
  "tool_choice": "auto"
}

整个示例的完整流程提供了四个相关请求示例,可以通过这个示例来了解如何使用函数调用功能。

函数调用

4. 结语

对于函数调用,当前只是初步实现了非流式的函数调用功能,后续计划将继续优化函数调用功能,包括流式函数调用、函数调用的并行执行等。同时,我也会继续完善 LLamaWorker 的其他功能。欢迎大家关注 LLamaWorker 项目,一起探索更多的可能性!

LLamaWorker 项目的目标是为开发者社区提供一个高性能、易于使用的工具,以便更好地利用大型语言模型的能力。无论您是在构建聊天机器人、内容生成工具还是任何需要自然语言处理能力的应用,LLamaWorker 都能为您提供强大的支持。

我非常期待看到社区成员如何使用 LLamaWorker 来实现他们的创意和项目。如果您对 LLamaWorker 有任何反馈或建议,欢迎通过 GitHub Issues 或 Pull Requests 与我交流。让我们一起推动开源社区的发展,解锁更多的可能性!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1951395.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Robot Operating System——AsyncParametersClient监控Parameters的增删改行为

大纲 同步创建SyncParametersClient设置监控回调回调函数主体测试完整代码 异步创建AsyncParametersClient设置监控回调测试完整代码 在《Robot Operating System——Parameter设置的预处理、校验和成功回调》一文中&#xff0c;我们使用Node::add_post_set_parameters_callbac…

Django项目中报错:django.template.exceptions.TemplateDoesNotExist: index.html

访问127.0.0.1&#xff1a;8000访问出错 查看报错原因 到Django项目当中找到settings.py&#xff0c;找到TEMPLATES中的DIRS: 添加如下代码&#xff0c;并导入OS模块&#xff1a; "DIRS": [os.path.join(BASE_DIR,templates)] 再次访问IP地址&#xff1a;

【JVM基础07】——类加载器-什么是类加载器?类加载器有哪些?双亲委派了解吗?

目录 1- 引言&#xff1a;类加载器1-1 类加载器是什么&#xff1f;(What)1-2 为什么要用类加载器&#xff1f; 作用&#xff1a;类加载的过程&#xff1f;(Why) 2- ⭐核心&#xff1a;类加载器详解(How)2-1 类加载器分类2-2 什么是双亲委派模型&#xff1f;2-3 为什么采用双亲委…

开始尝试从0写一个项目--前端(三)

器材管理板块 添加器材管理导航 src\views\home\Home.vue src\router\index.js src\views\equipment\Equipment.vue <template><div>hello!</div></template> 测试 搜索导航分页查询 src\views\equipment\Equipment.vue <template><div&…

C#、Net6、WebApi报表方案

目录 1 Pdf表单方案 1.1出现如下错误提示: 1.2 字体路径使用 2 Docx报表模板方案 2.1 pdf方案缺陷 2.2 解决方案 3 Spire.Doc报表方案 3.1 Docx方案缺陷 3.2 解决方案 4 插入复选框 5 WebApi文件流下载接口 6 软件获取方式 1 Pdf表单方案 使用【Adobe Acrobat P…

0726,没什么用的SELECT和没用的我

目录 select 可恶&#xff01;&#xff01;&#xff01; 一对多聊天室 select&#xff1a;&#xff08;抄抄抄 最怕人类开始思考 补一对一的 select 喵&#xff1a;&#xff08;抄抄抄 &#xff1f;&#xff1f;今天就这么结束了&#xff1f;&#xff1f;&#xff1f; …

全能Ai助手:写作到设计,宝藏神器帮你事半功倍

今天&#xff0c;就让我们一起踏上这场寻找“隐藏”宝藏的旅程&#xff0c;探索这些AI工具如何改变我们的生活&#xff01; 一、高效生产力的提升之道 1. 文案创作助手 案例&#xff1a;某位自媒体博主使用了一款智能写作工具&#xff0c;不仅大大节省了写作时间&#xff0c;…

JMeter接口测试:测试中奖概率!

介绍 Apache JMeter 是 Apache 组织基于 Java 开发的压力测试工具&#xff0c;用于对软件做压力测试。JMeter 最初被设计用于 Web 应用测试&#xff0c;但后来扩展到了其他测试领域&#xff0c;可用于测试静态和动态资源&#xff0c;如静态文件、Java 小服务程序、CGI 脚本、J…

c语言第四天笔记

关于 混合操作&#xff0c;不同计算结果推理 第一种编译结果&#xff1a; int i 5; int sum (i) (i) 6 7 13 第二种编译结果&#xff1a; int i 5; int sum (i) (i) 6 7 7 7 前面的7是因为后面i的变化被影响后&#xff0c;重新赋值 14 第一种编译结果&#xff…

Llama + Dify,在你的电脑搭建一套AI工作流

theme: smartblue 点赞 关注 收藏 学会了 本文简介 最近字节在推Coze&#xff0c;你可以在这个平台制作知识库、制作工作流&#xff0c;生成一个具有特定领域知识的智能体。 那么&#xff0c;有没有可能在本地也部署一套这个东西呢&#xff1f;这样敏感数据就不会泄露了&…

Redis的两种持久化方式---RDB、AOF

rdb其实就是一种快照持久化的方式&#xff0c;它会将Redis在某个时间点的所有的数据状态以二进制的方式保存到硬盘上的文件当中&#xff0c;它相对于aof文件会小很多&#xff0c;因为知识某个时间点的数据&#xff0c;当然&#xff0c;这就会导致它的实时性不够高&#xff0c;如…

Scrapy 爬取旅游景点相关数据(三)

这一节我们将之前爬取到的景点数据进行解析&#xff0c;并且保存为excel&#xff0c;便于后续使用&#xff0c;本节包含 &#xff08;1&#xff09; 景点数据解析 &#xff08;2&#xff09;数据保存到excel 1 编写爬虫 这次继续改进第二节的爬虫&#xff0c;新建一个爬虫文…

C#如何引用dll动态链接库文件的注释

1、dll动态库文件项目生成属性中要勾选“XML文档文件” 注意&#xff1a;XML文件的名字切勿修改。 2、添加引用时XML文件要与DLL文件在同一个目录下。 3、如果要是添加引用的时候XML不在相同目录下&#xff0c;之后又将XML文件复制到相同的目录下&#xff0c;需要删除引用&am…

蓝桥强化宝典(3)BFS

一、定义 广度优先搜索&#xff08;Breadth-First Search, BFS&#xff09;是另一种用于遍历或搜索树或图的算法。与深度优先搜索&#xff08;DFS&#xff09;沿着树的深度遍历不同&#xff0c;广度优先搜索会逐层遍历图的顶点。它从一个指定的源顶点开始&#xff0c;首先访问这…

失业潮下,有人靠天工AI做副业年入10万?

前言 你好&#xff0c;我是咪咪酱 这篇文章总结2个AI副业项目&#xff0c;不用写代码&#xff0c;就能做的2个副业项目。 第一&#xff1a;AI生成微信表情包&#xff0c;上传到微信表情包平台等&#xff0c;坚持下去&#xff0c;会有可观的收入。 第二&#xff1a;AI生成连载…

Java 8 中 20 个高频面试题及答案

文章目录 前言20 道高频题问题 1&#xff1a;给定一个整数列表&#xff0c;使用 Stream 函数找出列表中所有的偶数&#xff1f;问题 2&#xff1a;给定一个整数列表&#xff0c;使用 Stream 函数找出所有以 1 开头的数字&#xff1f;问题 3&#xff1a;如何使用 Stream 函数在给…

1.ESP32-CAM 下使用 ESP-IDF 打开摄像头

主要资料&#xff1a; 乐鑫官方编程指南 ESP-IDF 编程指南安信可官方模块页 安信可-ESP32-CAM摄像头开发板官方使用教程 安信可ESP32-CAM摄像头开发demo–局域网拍照、实时视频、人脸识别 &#xff08;开发环境是Linux&#xff09; 本文目标是在 Windows 下跑通摄像头 hello …

国衍科技——RFID技术的应用

在文物馆藏信息的记录与管理过程中&#xff0c;准确性和详细性是至关重要的。无论是大型博物馆还是私人收藏馆&#xff0c;都需要有效的方法来确保馆藏文物信息的可追溯性和可访问性&#xff0c;才能提供更好的服务和保护馆藏资源。而结合射频识别&#xff08;RFID&#xff09;…

2-46 基于matlab的声音信号的短时能量、短时过零率、端点检测

基于matlab的声音信号的短时能量、短时过零率、端点检测。通过计算计算短时能量、调整能量门限&#xff0c;然后开始端点检测。输出可视化结果。程序已调通&#xff0c;可直接运行。 2-46 短时能量 短时过零率 端点检测 - 小红书 (xiaohongshu.com)