谈大语言模型动态思维流程编排
尽管大语言模型已经呈现出了强大的威力,但是如何让它完美地完成一个大的问题,仍然是一个巨大的挑战。
需要精心地给予大模型许多的提示(Prompt)。对于一个复杂的应用场景,编写一套完整的,准确无误的提示,并不容易。另一方面,尽管大模型已经具备了一些拆解问题,一步步解接的能力。但是就目前而言,这种分析,推理能力还是不能能准确地做出推理
另一方面,对于大多数特定的问题而言,人类本身具有了成熟,有效的分析问题,解决问题的能力。我们出生起,就不断地学习如何一步步地拆解问题,通过步步地解决小问题,最终解决一个复杂的问题。
许多的研究者提出了各种提示大模型拆解问题的方法。例如 计划和解题(Plan-and-Solve Prompting),反思 ReAct 等等。但是不同的问题,有不同的解决思路。我们从小在学校里解决应用题时,老师总是教我们解题思路。对于各种问题,大模型需要能够动态地做出解题方法。使用静态的提示来实现动态地计划是十分复杂,。在笔者看来,使用计算机语言来动态规划大模型解决问题的思路更加有效。
从实例谈起
我们计划编写一个增强个人记忆力的大模型应用,该项目叫做 回忆(Recall)。在这个应用中,使用者要不断地告诉大模型一些关于个人的信息。例如:
- 个人简历:包括姓名,性别,出身日期,出生地,家庭成员,教育和工作简历等等。
- 个人爱好:自己的爱好,包括饮食,业余爱好,购物的品牌等等
- 个人活动:比如一些主要的活动,比如逛街,朋友聚会,就医等等活动。
- 备忘录:一些需要备忘的事情,例如 我的衣服放在哪里了。每天吃什么药等等。
这个项目貌似比较简单,与windows AI PC 中的Recall ,开源项目Rewind 有相似之处。按照网络上的各种大模型架构的方法,主要使用如下方式
- 使用大模型的Memory 功能实现对话的记忆
- 将用户的个人信息,爱好,个人活动写入Vector 数据库中,使用RAG 技术在会话过程中读取相关信息
- 构建ReAct Agent 进行 Action -Throught-Observation 的过程
- 调用合适的工具(Agent Tools)
vector 数据库 可以使用内存Memory 也可以使用永久VectorDB ,例如Croma VectorDB。
大模型我们测试了下列几种:
- openai
- 本地 llama-3
- 文心一言
- kimi
- 零一万物
但是结果并不令人满意,主要表现在如下几个方面
- 并非所有的大模型都支持 Function Call,Agent,Memory ,RAG等功能的API。
- Vector 数据库要使用Embedding 功能实现text -splite .耗费的时间很长。
- Momory 功能是将输入和回答都一股脑地存储了起来。会造成某些噪声混乱。
- 简单的提问查询Vector数据库时,无法精切地匹配数据库的内容。
- ReAct 的效果并不理想,有时后会乱想,反复地循环。明明得到了结果,却无法停止对话。
- 延时长,耗费的token 多。
实验下来,openai 效果最好,其它国内的大模型或多多少地出现问题。
观点
美国著名的人工智能专家马文·明斯基在《心智社会》一书中提出,人类的思维是由无数的智能体组成的社会。面对复杂的问题,会由不同的智能体来完成思考,而且它指出,复杂的智能体是由更小的智能构成。智能体最终是非智能的元素组成的。 这种论述体现了《原子论》的哲学思想,它与工程设计的模块化思想同出一辙。
AI 应用中思维能够使用多个智能体实现。智能体是由更多小的智能体构成。我们能够利用智能体分层思想构建智能体。
从这一观点出发,我们对大模型应用进行了新的思考。
- 让大模型分层思考
将复杂的问题分解为若干的小问题,通过解决小问题,最后解决大问题。这种方式具有如下的优点:
-大模型回答简单的问题,有利于保证其确定性
-使提示工程变得简单
提示也被分解成小提示,小问题的提示更具有针对性
-不依赖具体的大模型API
简单地使用chat 就可以。
-有利于采纳本地小模型与远程大模型相结合 ,降低使用大模型的成本,提高响应时间
- 使用程序设计的方法动态地编排大模型的思维过程
对于特定的一类问题,可以实现根据人类的经验,制定一套完整的思维过程。这样做的优点:
-融入了人类的思维方式,更具有针对性。推理的速度更快
-有利于对大模型的回答做确定性判断
-有利于对大模型的回答做确定性验证
动态思维的流程
我们继续使用上面的实例来讨论动态思维流程。
- 判断语句是陈述句,还是询问句
- 如果是陈述句,内容要存储到数据库中,如果是提问句,那么要从数据库中获取相关的信息
- 为了对信息做分类,要判断陈述或者提问的内容的分类。
- 如果是其它类型的提问,就直接有大模型回答
思维流程的编排方法
可以用程序或者图形方式来编排大模型的思维流程,在我们的实验中,采取了工业控制领域中功能块的编排方法。
这里的功能块本质上实现了一个智能体。 如果功能块中使用了AI ,可以成为智能体功能块,而不包含AI模型的功能块可以称为普通功能块。
基于我们的经验,决定借用IEC61499 事件功能块的概念和方法,这样做的另一个意图是实现语言功能块和IEC61499 功能块的融合。
IEC61499 的基本概念包括:
- 基本功能块
- 复合功能块
- 功能块网络
IEC61499 功能块由事件输入,事件输出,数据输入和数据输出。事件用来控制程序执行 的流程,数据用来表示数据的流动。
大语言功能块内部由大语言模型来回答一个特定的问题。 其内部结构如下:
大模型思维流程
大语言思维流程由大语言功能块网络组成,通过功能块网络运行时解释执行。功能块共享环境信息,环境信息包含了基本信息(对话者的姓名, 今天几号,星期几等等)和功能块通过数据库中提取的信息。一个功能块系统的结构如下
实验平台
为了实验langFunctionblock 的想法,我们简单地搭建列一个实验平台:
- 基于Nodejs/Javascript
- 基于langchain库
- 一个Javascript 实现的功能块运行时
- 一组基于大模型的功能块
- 不依赖大模型的API
App架构
实例的功能块网络
功能块
InputMessage
输入用户提问的功能块,当用户输入消息时。该功能块产生:
- Output 事件
- OutMessage 数据
应用程序通过 WriteData 和Execution 调用该功能块。
设置InputMessage和OutMessage功能块的主要目的是使功能块具有一个统一的入口和出口。
Check
主要判断输入语句是询问句还是陈述句。
Memory
该功能块判断陈数句内容的类型:个人信息,事件,备忘录,然后将语句的类型,语句和时间标签存储到MongoDB 数据库中。
Recall
该功能块判断陈数句内容的类型:个人信息,事件,备忘录,然后从数据库中读出相应类型的数据,添加在环境信息中。
Basic
这是一个基本的智能体功能块,将InMessage 结合环境信息一起构成Prompt 询问大模型,回答输出到OutMessage
OutMessage
该模块将信息返回给对话者。
工具的使用
零一万物大模型目前还不支持Agent Tools,FunctionCall 的API ,但是通过我们功能块的方法也能够实现工具的调用。下面是调用打开空调和电灯的功能块网络。
再一次说明了基于功能块网络方式的动态思维编排方法的灵活性。
程序的实例
Check功能块
class Check {constructor(Parameters) {this.Name = Parameters.Name;this.Type = "CheckType";this.model = Parameters.Modelthis.ModelType = Parameters.ModelType}async Executive(runtime, EventType) {if (EventType == "Invoke") {console.log("Invoke:" + this.ModelType)console.log(this.InMessage)const Prefix = `请将下列语句分为下列几类:询问,陈述,请求。`const Suffix = `。请以JSON形式输出语句的类型 :JSON的格式为:{class:"语句的类型"}如果无法判断语句的类型,直接输出 {class:"其它"}`const Prompt = Prefix + this.InMessage + Suffixconst completion = await this.model.chat.completions.create({messages: [{"role": "user","content": Prompt,}],model: this.ModelType,});const Content = await completion.choices[0].message.contentconst JSonContent = JSON.parse(Content.replace("```json\n", "").replace("```", ""))console.log(JSonContent.class)if (JSonContent.class == "询问") {this.OutMessage = this.InMessageawait runtime.WriteOutputData({ FBName: this.Name, DataName: "OutMessage", Value: this.OutMessage })await runtime.EventNotify({ FBName: this.Name, EventName: "Ask" })}else if (JSonContent.class == "陈述") {this.OutMessage = this.InMessageawait runtime.WriteOutputData({ FBName: this.Name, DataName: "OutMessage", Value: this.OutMessage })await runtime.EventNotify({ FBName: this.Name, EventName: "Statment" })} else if (JSonContent.class == "请求") {this.OutMessage = this.InMessage;await runtime.WriteOutputData({ FBName: this.Name, DataName: "OutMessage", Value: this.OutMessage })await runtime.EventNotify({ FBName: this.Name, EventName: "Request" })}else {this.OutMessage = this.InMessageawait runtime.WriteOutputData({ FBName: this.Name, DataName: "OutMessage", Value: this.OutMessage })await runtime.EventNotify({ FBName: this.Name, EventName: "Ask" })}}}async WriteData(Name, Value) {if (Name == "InMessage") {this.InMessage = Value;}}async ReadData(Name) {if (Name == "OutMessage")return this.OutputMessage;}
}
主程序
import express from 'express';
import path from 'path'
import url from 'url'
//import fs from 'fs'
import OpenAI from 'openai';
import {RunTime} from "./RunTime/RunTime.mjs"
const API_BASE = "https://api.lingyiwanwu.com/v1"
const API_KEY = "xxxxxxxxxxxxxxxxxxx"
const openai = new OpenAI({apiKey: API_KEY,baseURL:API_BASE,model: "yi-large",temperature: 0});const router = express.Router();const app = express();const __filename = url.fileURLToPath(import.meta.url);const __dirname = path.dirname(__filename);
// var upload = multer({ dest: './documents' })app.use(express.static(path.join(__dirname, 'public')));app.use(express.json())router.get('/index', function (req, res) {res.sendFile(path.join(__dirname + '/views/indexB.html'));});router.post('/Request', async function (req, res) {Request = req.body;console.log(Request)const Method = Request.Method;const Message = Request.Message;console.log(Method);console.log(Message);const result = await RunFBNetwork(Message)res.send(JSON.stringify({Method: "SendMessage",Message: result}))
})
app.use('/', router);//RunTime Initialize
console.log("llm FunctionBlock Runtime Ver 1.0")
const runtime=new RunTime();
runtime.InitializeFunctionBlickList();
runtime.LoadFBNetwork(openai);
app.listen(process.env.port || 3000);
console.log('Running at Port 3000');async function RunFBNetwork(InputMessage){console.log("llm FunctionBlock Runtime Ver 1.0")//RunTime Initialize runtime.InitializeMongoDB()runtime.InitializeEnvironment()await runtime.WriteInputData({FBName:"InMessage",DataName:"InMessage",Value:InputMessage})await runtime.Executive({FBName:"InMessage",EventType:"Request"})//Running....await runtime.run()const Output=await runtime.ReadFBData({FBName:"OutMessage",DataName:"OutMessage"})console.log(Output)return (Output)
}
结果
经过我们的初步测试,结果要比采用大模型的memory,RAG,ReAct Agent等方式要好。主要表现为准确率高,速度快。
- 将复杂的问题拆解成为小问题更有效
- 对于特定的应用场景,能够利用人类分析问题的经验,动态地编写思维流程要比简单的将复杂任务交给大模型更好。效果远远超过ReAct Agent
- 功能块及其功能块网络适合大模型思维流程的编排。
感兴趣的读者可以进一步共同探讨。
相关文章:

谈大语言模型动态思维流程编排
尽管大语言模型已经呈现出了强大的威力,但是如何让它完美地完成一个大的问题,仍然是一个巨大的挑战。 需要精心地给予大模型许多的提示(Prompt)。对于一个复杂的应用场景,编写一套完整的,准确无误的提示&am…...

工厂自动化相关设备工业一体机起到什么作用?
在当今的制造业领域,工厂自动化已成为提高生产效率、保证产品质量和降低成本的关键。在这一进程中,工业一体机作为一种重要的设备,发挥着不可或缺的作用。 工业一体机是自动化生产线上的控制中心。它能够整合和处理来自各个传感器、执行器和其…...

哈佛大学 || 概念空间中学习动态的涌现:探索隐藏能力
获取本文论文原文PDF,请在公众号【AI论文解读】留言:论文解读 今天主要看一个问题:在模型中的学习动态是如何涌现的。 在现代生成模型的研究与应用中,不断发现这些模型在处理训练数据时展现出了惊人的能力,这些能力很…...

Dockerfile打包部署常用操作
文章目录 1、Dockerfile部署java程序(jar包)1.1、创建Dockerfile1.2、将Dockerfile和要上传的jar包放到一个目录下,构建镜像1.3、创建启动容器 2、Dockerfile部署vue2.1、创建dockerfile文件2.2、将打包的dist文件放到dockerfile同文件目录下…...

ArcGIS:探索地理信息系统的强大功能与实际应用
ArcGIS是一款功能强大的地理信息系统(GIS)软件,由Esri公司开发。它广泛应用于各个领域,包括城市规划、环境保护、资源管理、交通运输等。作为一名长期使用ArcGIS的用户,我深感这款软件在数据分析、地图制作和空间信息管…...

Python 全栈体系【三阶】(二)
第一章 Django 五、模板 1. 概述 Django中的模板是指可以动态生成任何基于文本格式文件的技术(如HTML、CSS等)。 Django中内置了自己的模板系统,称为DTL(Django Template Language), Django模板语言。 2. 配置 settings.py中关于模板的…...

【VUE】 深入理解 Vue 动态路由:简介、实际开发场景与代码示例
深入理解 Vue 动态路由:简介、实际开发场景与代码示例 Vue.js 是一个用于构建用户界面的渐进式框架,它拥有丰富的生态系统,其中 Vue Router 是其官方的路由管理库。动态路由是 Vue Router 的一个强大特性,允许我们在应用运行时根…...

Linux x86_64平台指令替换函数 text_poke_smp/bp
文章目录 前言一、text_poke_early1.1 text_poke_early简介1.2 用途 二、text_poke_smp2.1 简介2.1.1 text_poke_smp函数2.2.2 stop_machine_text_poke简介2.2.3 text_poke函数 2.2 用途 三、text_poke_smp 内核hook 前言 Linux x86_64平台指令替换函数有两种类型:…...

海南云亿商务咨询有限公司口碑怎么样?
在数字化浪潮席卷全球的今天,电商行业正以前所未有的速度发展。抖音作为短视频领域的佼佼者,其电商功能更是为众多品牌和企业打开了全新的销售渠道。海南云亿商务咨询有限公司,作为抖音电商服务领域的佼佼者,正以其专业的服务和创…...

航空数据管控系统-②项目分析与设计:任务2:使用Git或SVN管理项目(可选任务,只介绍Git安装)
任务描述 1、安装Git 2、注册GitHub 3、配置本地库 4、配置远程库 5、使用Git管理项目 任务指导 分为以下几个部分完成: 学会Git的安装,帐号注册本地存储库的管理自己创建一个项目,项目名称为自己的名字,上传到代码仓库ÿ…...

【面试题】串联探针和旁挂探针有什么区别?
在网络安全领域中,串联探针和旁挂探针(通常也被称为旁路探针)是两种不同部署方式的监控设备,它们各自具有独特的特性和应用场景。以下是它们之间的主要区别: 部署方式 串联探针:串联探针一般通过网关或者…...

LeetCode42(接雨水)[三种解法:理解动态规划,双指针,单调栈]
接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 这是一道困难题,难度确实有点层次.我们先来朴素思想走一波. 要求能接多少雨水,我们可以具化到每个硅谷,每个硅谷能存多少雨水,那么答案就是每个…...

STM32-ADC+DMA
本内容基于江协科技STM32视频学习之后整理而得。 文章目录 1. ADC模拟-数字转换器1.1 ADC模拟-数字转换器1.2 逐次逼近型ADC1.3 ADC框图1.4 ADC基本结构1.5 输入通道1.6 规则组的转换模式1.6.1 单次转换,非扫描模式1.6.2 连续转换,非扫描模式1.6.3 单次…...

代码随想录算法训练营第六十二天 | 108. 冗余连接、109. 冗余连接II、复习
108. 冗余连接 题目链接:https://kamacoder.com/problempage.php?pid1181 文档讲解:https://www.programmercarl.com/kamacoder/0108.%E5%86%97%E4%BD%99%E8%BF… 思路 从前向后遍历每一条边(因为优先让前面的边连上)࿰…...

昇思MindSpore学习笔记6-01LLM原理和实践--FCN图像语义分割
摘要: 记录MindSpore AI框架使用FCN全卷积网络理解图像进行图像语议分割的过程、步骤和方法。包括环境准备、下载数据集、数据集加载和预处理、构建网络、训练准备、模型训练、模型评估、模型推理等。 一、概念 1.语义分割 图像语义分割 semantic segmentation …...

【FFMPEG基础(一)】解码源码
学习分享 main函数decodetorgb32.h 文件decodetorgb32 .cpp文件 main函数 #include <QApplication> #include "decodetorgb32.h" int main(int argc, char *argv[]) {QApplication a(argc, argv);DecodeToRGB32 toRGB32;int restoRGB32.openVideo("../fi…...

第二证券股市资讯:深夜!突然暴涨75%!
一则重磅收买引发医药圈轰动。 北京时间7月8日晚间,美股开盘后,美国生物制药公司Morphic股价一度暴升超75%。音讯面上,生物医药巨子礼来公司官宣,将以57美元/股的价格现金收买Morphic,较上星期五的收盘价溢价79%&…...

flutter 使用wechat_assets_picker的权限检测
https://pub.dev/packages/wechat_assets_picker AssetPicker.pickAssets之前进行权限检查 pickImages() async {try {if (PermissionState.authorized ! await AssetPicker.permissionCheck()) {PermissionUtil.showAllPermissions(Permission.storage, 1);return;}final Lis…...

Mojo入门案例教程(上手篇)
以下是 Mojo 编程语言入门案例教程,内容包括 Mojo 的基本概念、变量、控制结构、函数等方面: Mojo 的基本概念 1.什么是 Mojo?:Mojo 是一种函数式编程语言,用于开发小型应用程序、脚本和工具。 2.Mojo 的特点&#x…...

如何在window执行mkfile
1、Windows cmd中出现错误:“‘make‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。”的解决方法_windows_是板栗啊-GitCode 开源社区 2、安装cmder,再通过包管理工具下载make...

Nginx 是一个非常流行的 Web 服务器和反向代理服务器
Nginx 是一个非常流行的 Web 服务器和反向代理服务器,以其高性能、稳定性、丰富的功能集和低资源消耗而闻名。下面是一个简化的 Nginx 使用教程,包括基本的安装、配置和一些常见用途。 安装 Nginx 在 Ubuntu/Debian 上安装: sudo apt upda…...

mysql怎么调整缓冲区大小
MySQL中调整缓冲区大小是数据库性能优化的重要一环。缓冲区大小直接影响了数据库的读写性能和响应速度。以下是一些常见的MySQL缓冲区及其调整方法: 一、InnoDB缓冲池(InnoDB Buffer Pool) InnoDB缓冲池是InnoDB存储引擎用来缓存表数据和索…...

计算机组成原理学习笔记(一)
计算机组成原理 [类型:: [[计算机基础课程]] ] [来源:: [[B站]] ] [主讲人:: [[咸鱼学长]] ] [评价:: ] [知识点:: [[系统软件]] & [[应用软件]] ] [简单解释:: 管理计算机系统的软件; 按照任务需要编写的程序 ] [问题:: ] [知识点:: [[机器字长]] ] [简单…...

Vue3 对跳转 同一路由传入不同参数的页面分别进行缓存
1:使用场景 从列表页跳转至不同的详情页面,对这些详情页面分别进行缓存 2:核心代码 2.1: 配置路由文件 在路由文件里对需要进行缓存的路由对象添加meta 属性 // 需要缓存的详情页面路由 { name: detail, path: /myRouter/detail…...

LinearLayout的测量流程
在日常开发中我们常常使用LinearLayout作为布局Group,本文从其源码实现出发分析测量流程。大家可以带着问题进入下面的分析流程,看看是否能找到答案。 垂直测量 View的测量入口方法是onmeasure方法。LinearLayout的onMeasure方法根据其方向而做不同的处…...

数据无忧:Ubuntu 系统迁移备份全指南
唠唠闲话 最近电脑出现了一些故障,送修期间,不得不在实验室的台式机上重装系统,配环境的过程花费了不少时间。为避免未来处理类似事情时耗费时间,特此整理一些备份策略。 先做以下准备: U盘启动盘,参考 …...

中国IDC圈探访北京•光子1号金融算力中心
今天,“AI”、“大模型”是最炙手可热的话题,全球有海量人群在工作生活中使用大模型,大模型产品涉及多模态,应用范围已涵盖电商、传媒、金融、短视频、制造等众多行业。 而回看2003年的互联网记忆, “上网”“在线”是…...

[Unity入门01] Unity基本操作
参考的傅老师的教程学了一下Unity的基础操作: [傅老師/Unity教學] Unity3D基礎入門 [華梵大學] 遊戲引擎應用基礎(Unity版本) Class#01 移动:鼠标中键旋转:鼠标右键放大:鼠标滚轮飞行模式:右键WASDQEFocus模式&…...

vivado DELAY_VALUE_XPHY、DIFF_TERM
延迟_值_XPHY PORT对象上的DELAY_VALUE_XPHY属性指定要添加的延迟量 Versal XPHY逻辑接口的输入或输出路径。在的早期阶段 opt_design在重新生成高级I/O向导IP时 DELAY_VALUE_XPHY值将从PORT复制到的XPHY实例上 输入或输出路径。Vivado设计套件中存在DRCs,以确保 DE…...

C++语言相关的常见面试题目(三)
1. List底层实现原理 省流: list底层实现了一个双向循环链表。 每个元素(或节点)包含三个部分:数据域(_M_Storage)、前驱指针(_M_prev)、后继指针(_M_next)。 数据域:存储实际数据。 前驱指针:指向链表中…...