1、本文目的

  不借助任何框架,使用c#写一个agent,实现调用阿里千问大模型完成预定任务。同时完成一个可扩展的agent框架雏形。

2、预期读者

  本文假设读者已经了解了一些基本概念,例如AI,functioncall,c#编程等。

3、主要技术

  在编写agent的过程中主要用到以下几点:

  • 使用c#的WebClient来和千问接口进行通讯。
  • 使用functioncall功能实现外部功能调用

4、解决的难题

  在实现上述目的的过程中遇到了一些困难,这里记录一下,给自己备注,也为后人提醒。

  • tool数量太多。我们都知道,大模型能够调用外部函数,是基于大模型本身的一个功能functioncall,后来这个功能发展成目前非常火热的MCP。不管是那种形式,底层的本质都是一样的,在向大模型输入信息的时候,同时提供给大模型一些工具(tools),以供大模型在需要的时候选择调用(其实这里说大模型调用不适合,应该是大模型指出应该让agent调用哪个function)。对于专注于特定领域的agent来说,也许不需要太多的tools就能完成工作。但是对于一些通用型的agent来说,要辅助人类完成任何可能得任务,需要的function数量非常庞大。想象一下有这样一个agent,可以当做你的助理,不但能在工作中给你提供帮助,还能在生活中为你处理各种事情:查天气,订机票,提醒,订外卖,做旅游规划等等。这样一个功能周全的agent要实现起来需要的tools无法想象。我们每次请求大模型的时候,如果都把这些tools传递给大模型,不但数据量大,速度慢,你的大模型账单也会快速增加,因为大模型是按照tokens收费的。为此设计了一些小技巧,以减少每次提交请求时的tools数量。

    • 关键词法:这种方法就是监控用户的请求内容,如果包含指定的关键词,就把相对应的tools一起附带上。比如:当用户提到“天气”、“温度”时,就把查询天气的tools一起提交。
    • 分组控制器法:这种方法就是把所有的tool分成一些大类,每个大类包含一定数量的tools,同时为每个大类编写一个tools,这样大模型在选择工具时,先选择大类的tool,然后大类tool的实现中在动态加载这个类别下面的其他tools。比如:我们可以给“预定东西”作为一个大类,这个大类下面包含“订机票”,"订酒店","订外卖"等等。大模型分析到用户的意图是“预定”类的,就先调用这个大类的tool,再有大类tool的实现中,动态加载各个子类的tool,然后根据用户需求调用实际的tool,例如“订机票”。分组控制器法的好处是减少了非必要的tool的提交,弊端是需要二次提交才能定位到具体的小类tool上面。后面会进行优化,尽量减少二次提交的时机。
  • 大模型一次只能处理一个任务:在使用大模型function功能进行函数调用时候,发现大模型每次请求只能返回一个函数调用(观点如果有误,请指教)。比如用户请求:“帮我查一下北京明天的天气,然后订一张明天深圳到北京的机票”。在上面的例子中,用户实际给大模型2个任务,第一查天气,第二订机票。这两个任务都可以通过大模型的functioncall功能完成,但是一次请求中,大模型无法返回2个调用,只能返回一个,比如:getWeather(天气查询)。为此我们需要为这样的场景设计一个任务分解的tool,告诉大模型,如果存在多个任务,可以使用方法把任务分解为可以单独执行的最小单元。这样任务分解函数中的实现就可以对每个单独的任务进行重新提交,然后等待所有任务都返回后,整理这些内容在发给用户。
  • 逻辑处理:大模型本身具有推理能力,如何把这种推理能力转化为解决实际问题能力成为我们任务中的关键。在上面的任务分级方法来处理复杂任务时,每个任务之间可能存在依赖关系。例如用户请求:“如果明天北京天气好的话,就给我订一张从深圳到北京的机票”。很明显,“订机票”这个任务的执行取决于“查询北京天气”的结果,通过任务分解,并制定任务依赖,使用大模型的推理能力可以解决这类问题。

5、目前完成的功能

  • 实现自然语言对内部数据进行统计分析,并给出图形报表。例如:查一下加班最多的3个人是谁。大模型会根据用户的描述生成对应sql查询语句,执行这个查询语句得到结果,再把结果提交个大模型来回答用户的问题。当然这里有个前提,就是需要把内部系统数据表结果发给大模型(使用system的prompt)。
  • 个人工作助理:例如可以提醒、通知、会议纪要等。

6、代码说明:打算把相关代码打包下载,但是写完文章,发现无法插入附件。另外代码本身没有难度,代码里面包含了一些我们自己的类库调用,所以无法直接运行,但是这些类库调用不影响阅读、理解,要是把这些类库替换一下(没几个,很好改)也能运行。

既然无法下载,那么接下来我会抽空把一些主要的代码进行单独说明,最后会放到github上下载。

用c#从头写一个AI agent,实现企业内部自然语言数据统计分析的更多相关文章

  1. 从头写一个Cucumber测试(一) Selenium Test

    转载:https://yaowenjie.github.io/%E7%BC%96%E7%A8%8B%E7%9B%B8%E5%85%B3/cucumber-test, 背景(废话不读系列)   前段时间 ...

  2. 从头写一个Cucumber测试(二) Cucumber Test

    转载:https://yaowenjie.github.io/%E7%BC%96%E7%A8%8B%E7%9B%B8%E5%85%B3/cucumber-test-part-2 承接上文   前一篇博 ...

  3. Java Web 开发利用Struts2+Spring+mybatis写一个用户登录界面以及简单的数据交互

    框架的东西太复杂也难以讲通,直接上代码: 一.首先得配置环境 和导入必要的jar包 有一些重要的如下: Filter文件夹下的SafetyFilter.java   model文件夹下的 Global ...

  4. javascript 写一个ajax 自动拦截,并下载数据

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  5. 如何写一个像btgoogle一样的12306泄露数据查询

    demo地址:http://www.btgoogle.com/12306/ 圣诞节,12306送给了我们一个大礼物.大约 14w的数据泄露, 看网上都沸沸扬扬的.开始也准备找一个数据库来看看,随后,我 ...

  6. 从零写一个兼容MySQL/Oracle的Proxy中件间(一)《初识Oracle的通信协议》

    0.前言 MySQL由于开源的原因,有各式各样的中件间Proxy ,极大的丰富了做高可用或迁移的方案,习惯了MySQL生态圈的灵活和便利,Oracle官方不开源代码和协议,没有中间件proxy,显得很 ...

  7. 缓存原理,自己写一个缓存类(c#版)

    .net中的MemoryCache是通过内部封装一个静态Dictionary 自己写一个缓存,来看看内部怎么实现的 public class CustomerCache : ICache { priv ...

  8. Summer——从头开始写一个简易的Spring框架

    Summer--从头开始写一个简易的Spring框架                ​ 参考Spring框架实现一个简易类似的Java框架.计划陆续实现IOC.AOP.以及数据访问模块和事务控制模块. ...

  9. 念一句咒语 AI 就帮我写一个应用,我人麻了...

    原文链接:https://forum.laf.run/d/232 作为人类,我们时常会有自己独特的想法和脑洞大开的创意.然而,这些想法往往因为成本过高而无法实现,毕竟每个人的能力和精力都是有限的,尤其 ...

  10. Cordova webapp实战开发:(6)如何写一个iOS下获取APP版本号的插件?

    上一篇我们学习了如何写一个Andorid下自动更新的插件,我想还有一部分看本系列blog的开发人员希望学习在iOS下如何做插件的吧,那么今天你就可以来看看这篇文字了. 本次练习你能学到的 学习如何获取 ...

随机推荐

  1. Linux重要的日志文件

    1./var/log/boot.log 该文件记录了系统在引导过程中发生的事件,就是Linux系统开机自检过程显示的信息 2./var/log/syslog 只记录警告信息,常常是系统出问题的信息,所 ...

  2. Luogu P10842 Piggy and Trees 题解 [ 绿 ] [ 拆边 ] [ 贡献思维 ] [ 组合数学 ]

    Piggy and Trees:把路径拆成边的思维题. 思路 一看到这题的路径,就想到了 Luogu P3177 树上染色 这题化路径为边的贡献,分别计算的思维. 那么对于此题,先来观察题目里式子的意 ...

  3. 重生之数据结构与算法----数组&链表

    简介 数据结构的本质,只有两种结构,数组与链表.其它的都是它的衍生与组合 算法的本质就是穷举. 数组 数组可以分为两大类,静态数组与动态数组. 静态数组的本质是一段连续的内存,因为是连续的,所以我们可 ...

  4. Qt+OpenCV实现图片压缩(JPEG、PNG)

    一.概述 需求: 1.编写一个小工具实现图片压缩 2.图片仅支持JPEG和PNG格式 3.目的是压缩图片在磁盘中所占用的大小 4.使用的开发语言是Qt.C++.OpenCV 5.压缩的质量可以动态调节 ...

  5. Selenium KPI接口 iframe切换

    应用场景: 在编写脚本的时候,经常会发现最熟悉的错误"元素定位不到",此时如果你查看页面元素,有可能你会发现元素在>标签对之间. 此时,我们只有先将代码驱动切换到frame内 ...

  6. SuiGo智能博客系统

    一款由Golang+Vue开发的博客类网站,支持大模型对话编写智能博客,同时适配PC和移动端. 功能点说明 系统主要包括 1.博客功能:博客编写也可对话AI模型协助编写.查询.编辑页面.详情页面.分享 ...

  7. python 函数与方法的区别

    函数与方法的区别 并不是类中的调用都叫方法 1.函数要手动传self,方法不用传self. 2.如果是一个函数,用类名去调用,如果是一个方法,用对象去调用. class Foo(object): de ...

  8. vue watch监听路由变化

    vue watch监听路由变化 // 监听 this.$route.path // watch监听非DOM元素的改变 watch:{ '$route.path':function(to,from){ ...

  9. 在Ubuntu上安装php7.2、php7.3、php7.4

    目录 开始之前 在Ubuntu 18.04或16.04上安装PHP 7.4 更新Ubuntu 添加PHP存储库 安装PHP 7.4 在Ubuntu 16.04上安装PHP 7.2 更新Ubuntu 添 ...

  10. BUUCTF---RSA1

    RSA基础概念 rsa原理: RSA公开密钥密码体制的原理是:根据数论,寻求两个大素数比较简单,而将它们的乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥 RSA算法的具体描述如下: (1) ...