面向AI应用开发实战分享 - 基础篇

“前端转AI,第一讲来了”

引言

如果你是一名前端开发,同时又对AI开发很感兴趣,那么恭喜你,机会来了。

如果不是也没关系,同样能帮大家了解AI应用的开发思路。

本文将带大家从面向AI开发的基础知识开始,再到RAG,Agent,流程编排,深入了解如何在企业内部落地AI项目。

基础篇

一、如何面向AI交互

通常,我们使用一段文字输入,AI模型都会基于大模型自身来进行回答,这个相信大家已经都非常了解。但是,如果想让AI能够基于我们所期待的内容回答,或者说是基于我们的私域信息来进行回答,我们有哪些办法?

1. 模型训练
2. 微调Fine-tuning
3. Prompt提示词工程
4. RAG检索增强生成

模型训练:

通过从huggingface下载开源模型,在本地完成部署,比如最新推出的Llama 3 8B版,小模型对GPU的要求会相对低些,后通过大量的文档资料完成模型训练。

虽说小型模型降低了GPU的算力资源但成本也不是普通企业能承担的,除了自身的硬件成本、模型优化的人力成本,也存在模型的汰换风险,一旦外部大厂出个大招,那我们训练的模型就会面临淘汰,但企业也应采取防御型战略,先拥抱,毕竟AI已是大势所趋,模型在应用层接口方面在开源社区里已经标准化,开发设计时模型与功能解耦,随时替换。

微调Fine-tuning:

很多商业AI的服务模型都提供了这一能力,允许用户针对特定的应用场景调整预训练好的模型,以获得更符合预期的输出结果。

比如,你的公司有一个内部项目代号为"Project”,您希望使用LLM模型来自动生成关于"Project"的文档或回答员工关于"Project"的查询。但预训练模型没有接触过"Project"这个术语,因此无法生成相关的准确信息。这时候就可以通过一些术语或上下文来调整模型对于这一块的理解。

最后,微调是一种付费服务,如果未来换其他模型,你需要重新进行微调以适应新模型的特性和改进。这将再次产生计算和时间成本。

Prompt提示词工程:

这个应该是刚接触AI开发的同学,最先使用的,让AI能够按照我们的期望完成指令交付的方式。比如,让模型尽量用中文回答。你需要准备一份包含角色、背景、技巧、输出风格、输出范围等的Prompt提示词,然后在每次通讯时携带在上下文里。

如果你使用chat_model(Langchain术语)方式,则会在message数组的0键位一直保持system prompt,如果是LLM(Langchain术语)方式,则是在每次通讯时的message字符串里包装prompt+question,这里我们更应该基于chat_model方案来开发。

但是当你想要正式的投入到自己的项目中时,你可能会发觉Prompt非常难优化,AI并不能完全按照你的要求去执行。总结,Prompt会有以下几个痛点:

1. 设计难度大,如果模型的输出依赖于我们的提示词反馈,这可能会形成一个循环,我们需要不断地调整提示词以获得更好的输出。
2. 长度限制,每次通讯的message通常会包含:Prompt + n轮上下文history + 本次的question,这些内容的总文字数也是计算我们单次会话的token总成本,过长的prompt很容易使AI产生幻觉,影响回复结果。
3. Prompt依然无法解决让模型面向私域,我们公司内部的知识库进行回答

RAG检索增强生成:

RAG对刚接触的同学可能会比较抽象,借用Langchain的图来介绍一下

1. 首先是embedding向量存储

我们把内部文档在提取内容后进行切片,将内容转为段落数组(chunk),然后传入大模型的embed接口,模型会返回浮点数字,这个过程就是embedding,最后我们会把浮点数存入向量库,常见的向量库有es、faiss

图片

2. 接着是内容召回

输入一个问题,先通过模型embedding把问题转为向量数据,然后在我们的文档库里进行相似度搜索,召回相似度接近的数据后再交由大模型进行总结,最后返回给用户

图片

以上就是RAG的整个过程,RAG是个非常考验技术的工作,以上的流程是无法描述出RAG复杂性的,包括我们的产品在上线后,至今还在不断尝试如何更好的提升RAG的质量,做到能用很简单,但要做好非常难。

后面讲到内部知识库时再来讨论目前我们的方案,和线上实际效果。

引用在其他文章里看到的一句话,感同身受

RAG涉及的内容其实广泛,包括Embedding、分词分块、检索召回(相似度匹配)、chat系统、ReAct和Prompt优化等,最后还有与LLM的交互,整个过程技术复杂度很高。如果你用的LLM非常好,反而大模型这一块是你最不需要关心的。而这些环节里面我们每个都没达到1(比如0.9、0.7...),那么最终的结果可能是这些小数点的乘积。

https://mp.weixin.qq.com/s/WjiOrJHt8nSW5OGe2x4BAg

二、Agent

前面主要是AI在文字内容上的交付,那如何让AI完成工作的交付呢?

当在工作汇报时,如果能用下面这张图来演示你的AI Agent功能,会不会很有吸引力?

图片

(取自QCon上的一张分享图)

目前想实现Agent,主要有以下2种方式

ReAct自我推理

Few-shot Prompt + Thought + Action + Observation 

通过构造一个内含工具、推理和规划的prompt结构,模型在内部通过与提示的互动进行自我迭代和调整,以选择适当的工具或生成更好的输出。

例如:

{    "messages": [        {            "role": "system",            "content": "Assistant is a large language model trained by OpenAI.\n\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist. However, above all else, all responses must adhere to the format of RESPONSE FORMAT INSTRUCTIONS."        },        {            "role": "user",            "content": "TOOLS\n------\nAssistant can ask the user to use tools to look up information that may be helpful in answering the users original question. The tools the human can use are:\n\ninfo-tool: Useful for situations where you need to retrieve content through one or more URLs from https://info.bilibili.co/. Input should be a comma-separated list in the format of \"one or more valid URLs with the domain https://info.bilibili.co/pages/viewpage.action, where the URL should include the pageId parameter\", followed by \"the information you need to summarize, or to obtain a summary\".\n\nRESPONSE FORMAT INSTRUCTIONS\n----------------------------\n\nOutput a JSON markdown code snippet containing a valid JSON object in one of two formats:\n\n**Option 1:**\nUse this if you want the human to use a tool.\nMarkdown code snippet formatted in the following schema:\n\n```json\n{\n    \"action\": string, // The action to take. Must be one of [info-tool]\n    \"action_input\": string // The input to the action. May be a stringified object.\n}\n```\n\n**Option #2:**\nUse this if you want to respond directly and conversationally to the human. Markdown code snippet formatted in the following schema:\n\n```json\n{\n    \"action\": \"Final Answer\",\n    \"action_input\": string // You should put what you want to return to use here and make sure to use valid json newline characters.\n}\n```\n\nFor both options, remember to always include the surrounding markdown code snippet delimiters (begin with \"```json\" and end with \"```\")!\n\n\nUSER'S INPUT\n--------------------\nHere is the user's input (remember to respond with a markdown code snippet of a json blob with a single action, and NOTHING else):\n\nhttps://info.bilibili.co/pages/viewpage.action?pageId=849684529\n这篇文章讲了什么"        }    ]}

我们通过Prompt告诉模型,它善于使用工具来解决问题,告诉它每一个工具的介绍,和需要填入什么参数,最后要求模型每次回复时必须遵循使用markdown code格式返回,然后我们会在Agent进程里消费返回的json-schema,是调用工具还是Final Answer

Tool-call 代理交互

很明显ReAct会导致我们的上下文过长,很容易造成模型在经过几轮迭代之后不已markdown code的格式来返回内容,最终导致Agent走不下去。

tool-call的出现解决了这一问题,我们会把Prompt里这些非结构化的工具描述转化为结构化的api字段,这样既节省了Prompt的上下文长度,也变的容易控制

例如:

// POST /chat/completions{  ...  "tools": [      {        "type": "function",        "function": {          "name": "info-tool",          "description": "打开一个或多个带有pageId的xxxx网站,完成用户需求",          "parameters": {            "type": "object",            "properties": {              "pageId": {                "type": "number",                "description": "请填写网址里的pageId,多个用逗号隔开"              },              "task": {                "type": "string",                "description": "描述需求"              }            },            "required": [              "pageId",              "task"            ],            "additionalProperties": false,            "$schema": "http://json-schema.org/draft-07/schema#"          }        }      },      ...更多其他工具  ],  ...}

此时,模型也会以结构化的方式告诉你他使用的工具

// API Response{    ...    "tool_calls": [        {            "index": 0,            "id": "info-tool:0",            "type": "function",            "function": {            "name": "info-tool",            "arguments": "{\n    \"task\": \"获取页面内容\",\n    \"pageId\": 845030990\n}"            }        }    ]    ...}

三、开发框架

再来介绍下我们选择的技术框架,之后也会介绍其优点和不足之处

Langchain

在许多讨论AI的文章里都会提到Langchain,或者很多的开源框架都在和Langchain作比较。Langchain是一个集成了商业和开源模型,并提供了一整套工具和功能,简化了开发、集成和部署基于语言模型的应用。

- 组件化:为使用语言模型提供抽象层,以及每个抽象层的一组实现。组件是模块化且易于使用的,无论是否使用LangChain框架的其余部分。
- 现成的链:结构化的组件集合,用于完成特定的高级任务

通俗的讲,它为不同的模型,不同的组件提供了统一的输入和输出规范。

在Chain里可以传入[Prompt、Model、Tool、Memory(历史会话)、OutputParser],也能将多个model进行嵌套,让上一个model的输出作为下一个PromptTemplate的输入

目前官方提供了2种语言的版本,一个是Python,另一个是Nodejs

Flowise

基于Langchain的AI流程编排系统,主语言Nodejs,为Langchain的每个模型类和组件类提供了可视化的低代码组件,通过在画布上的拖拽组件,即可完成AI的整套交付流程,组件包括Chain(进程)、Prompt、Agent Tool、Chat Module等。

同类的还有Dify,它提供了多模型对接、RAG、任务编排、等整套的产品化方案。

Flowise更像是一个毛坯房,提供了解决方案,但所有的产品化还是需要自己开发,读懂它,能让你在开发Langchain时事半功倍。Dify更像豪华大别墅,大多数的功能都已经做好了产品化,内部独立维护了与模型的api封装,主语言Python。

Flowise中的packages介绍:

- Server:express,CRUD、完成组件库内的实例运行
- Component:JavaScript,实现Langchain类的可视化和低代码
- UI:React,AI流程编排的画布,和一些维护页面

以下是一个通过Agent由AI判断选择使用哪些工具的编排展示,我们重新开发了Agent组件,已更适应我们的tool-call功能,在Bili Agent主进程中,组件会负责消费这些关联了的工具

图片

部分代码示例​​​​​​​

import { AgentExecutor } from 'langchain/agents' // 将工具的配置信息转为model接口里tools的结构化字段// 由于对齐了接口规范,所以可以直接使用formatToOpenAITool函数const modelWithTools = model.bind({    tools: [...tools.map((tool: any) => formatToOpenAITool(tool))]}) // 按顺序组合const runnableAgent = RunnableSequence.from([    // 包含了用户的指令,和将模型消息里的tool_calls format后得到的ToolMessage,和上下文聊天记录    // 以上这些都会输入给prompt    {        [inputKey]: (i: { input: string; steps: AgentStep[] }) => i.input,        agent_scratchpad: (i: { input: string; steps: ToolsAgentStep[] }) => formatToolAgentSteps(i.steps),        [memoryKey]: async (_: { input: string; steps: AgentStep[] }) => {            const messages = (await memory.getChatMessages(flowObj?.sessionId, true, chatHistory)) as BaseMessage[]            return messages ?? []        }    },    prompt,    modelWithTools,    new OpenAIToolsAgentOutputParser()]) const executor = AgentExecutor.fromAgentAndTools({    agent: runnableAgent,    tools,    returnIntermediateSteps: true,    maxIterations: 5}) executor.invoke({input: '明天是几月几号?'}) // tool_calls示例{    "tool_calls": [      {        "index": 0,        "id": "GetDate:0",        "type": "function",        "function": {          "name": "GetDate",          "arguments": "{\n    \"task\": \"获取明天的日期\"\n}"        }      }    ]}

最后通过Agent的配置,就可以让模型在通用域和私域或是工具插件里自由的选择进行聊天

图片

以上就是基础篇的全部内容,至此可以发现,为什么本篇开头会提到恭喜前端。是的,以上技术栈全部来自前端领域。

在下篇文章中,会从我们项目应用的角度,分享一下产品化的AI平台应具备哪些解决方案,同时我们也引入了前端其他领域的技术,如:低代码、云函数。

-End-

作者丨Zerooo

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

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

相关文章

Vue3:ElementPlus分装动态列表查询表单和弹窗动态表单

文章目录 概要表单组件封装弹窗组件调用表单组件页面列表调用查询表单 表单组件封装 组件代码 <template><el-formref"ruleFormRef"class"elForm":inline"true":rules"rules":model"TableList"label-width"…

AlaSQL.js:用SQL解锁JavaScript数据操作的魔法

简介 先附上 github 地址 https://github.com/AlaSQL/alasql AlaSQL.js - JavaScript SQL database for browser and Node.js. Handles both traditional relational tables and nested JSON data (NoSQL). Export, store, and import data from localStorage, IndexedDB, or …

高德车道级安全预警再升级 10大场景全方位守护行车安全

今日起&#xff0c;2024年高考、端午节小长假相继到来&#xff0c;正值新一波出行高峰到来&#xff0c;高德地图车道级安全预警功能再次升级。升级后的车道级安全预警功能覆盖了10大安全风险较高的行车场景&#xff0c;全方位、超视距地为用户实时探测、预警行车风险&#xff0…

成都跃享未来教育咨询有限公司,值得信赖!

在浩渺的教育咨询市场中&#xff0c;成都跃享未来教育咨询有限公司以其独特的魅力和卓越的服务质量&#xff0c;成为了行业内的璀璨明星。作为一家致力于为学生提供全方位教育咨询服务的公司&#xff0c;成都跃享未来教育咨询有限公司始终坚持安全可靠的原则&#xff0c;为广大…

树莓派4B_OpenCv学习笔记4:测试摄像头_imread加载显示图像_imwrite保存图片

今日继续学习树莓派4B 4G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1&#xff1a; 今日对之前的测试CSI摄像头函数进行一些理解说明&#x…

pytorch中的zero_grad()函数的含义和使用

optimizer.zero_grad() &#xff0c;用于将模型的参数梯度初始化为0。 #反向计算 loss.backward()#反向传播计算梯度 optimizer.step()#更新参数&#xff0c;梯度被反向计算之后&#xff0c;调用函数进行所有参数更新 #在反向传播计算时&#xff0c;梯度的计算是累加&#xff…

降噪是什么意思?视频如何降噪?一文了解全部

在视频制作的过程中&#xff0c;我们经常会遇到噪音问题&#xff0c;这些噪音可能来自拍摄环境、录制设备或其他源头。然而&#xff0c;对于初学者来说&#xff0c;降噪是什么意思&#xff0c;以及如何有效地在视频中进行降噪可能是一些疑惑的问题。本文将深入解释降噪的概念&a…

【算法】深入浅出爬山算法:原理、实现与应用

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

echarts学习: 绘制双y轴折线图

前言 我们公司项目中的折线图大都是双y轴的&#xff0c;因为这些图表往往需要同时展示水位和流量这两种不同单位的数据&#xff0c;因此如何绘制双y轴折线图就是就是我所面临的首要问题。 1.如何绘制双y轴 将yAxis属性的值设置为一个数组&#xff0c;并在数组中添加两个axis对…

【LC刷题】DAY02:977 209 59

#【LC刷题】DAY02&#xff1a;977 209 59 文章目录 977. 有序数组的平方 [link](https://leetcode.cn/problems/squares-of-a-sorted-array/description/)第一思路&#xff1a;直接排序优化&#xff1a;双指针 209. 长度最小的子数组 [link](https://leetcode.cn/problems/min…

Apache Spark MLlib详解

Apache Spark MLlib 是 Spark 的一个核心组件&#xff0c;提供了大量的机器学习算法和工具&#xff0c;用于在大数据集上进行数据分析和预测建模。MLlib 提供了广泛的算法集&#xff0c;包括分类、回归、聚类、协同过滤、降维、特征提取、频繁模式挖掘和统计测试等。 主要特点…

记录一次Linux启动kafka后并配置了本地服务连接远程kafka的地址后依旧连接localhost的问题

问题的原因 我是使用docker来安装并启动kafka 的&#xff0c;所以在启动过程中并没有太多需要配置的地方&#xff0c;基本都是从网上照搬照抄&#xff0c;没动什么脑子&#xff0c;所以看着启动起来了觉得就没事了&#xff0c;但是运行项目的时候发现&#xff0c;我明明已经配…

第五届上海市青少年算法竞赛网络同步赛(小学组)

第五届上海市青少年算法竞赛网络同步赛(小学组)T1. 符号译码_网络同步赛 内存限制: 256 Mb 时间限制: 1000 ms 题目描述 小爱为标点符号设计了一套编码系统,编码规则如下: [ 的编码为 010 ] 的编码为 101 < 的编码为 00 > 编码为 11 + 的编码为 011 - 编码为 100 根…

AI辅助论文:探索AI查重与AI降重技术

在科研领域&#xff0c;AI写作工具如同新一代的科研利器&#xff0c;它们能够极大提高文献查阅、思路整理和表达优化的效率&#xff0c;本质上促进了科研工作的进步。AI写作工具不仅快速获取并整理海量信息&#xff0c;还帮助我们精确提炼中心思想&#xff0c;显著提升论文写作…

生成式人工智能的风险与治理——以ChatGPT为例

文 | 西南政法大学经济法学院 马羽男 以ChatGPT为代表的生成式人工智能在创造社会福利的同时&#xff0c;也带来了诸多风险。因此&#xff0c;当务之急是结合我国生成式人工智能发展状况&#xff0c;厘清其应用价值与潜在风险之间的关系&#xff0c;以便在不影响应用发展的前提…

0606 作业

#include <stdio.h> #include <string.h>typedef struct usr{char unm[21];char pwd[21]; }user;int main(int argc, const char *argv[]) {FILE* userfilefopen("./user_tible.txt","r");printf("输入username:");user u;scanf(&qu…

人工智能在肿瘤预后预测中的最新研究进展|顶刊精析·24-06-07

小罗碎碎念 今天要分享的文献主题&#xff0c;大家一定非常熟悉&#xff0c;因为绝大多数AI4cancer的文章都会提到它——预后预测&#xff0c;所以今天的文献主题是——人工智能肿瘤预后预测。 在正式开始分享之前&#xff0c;我想先带着大家梳理两个问题。解决了以下两个问…

Chrome 自动执行 JS 脚本 | Tampermonkey 插件

文章目录 第 1 步:安装插件 Tampermonkey第 2 步:固定到工具栏第 3 步:在网站上启用 Tampermonkey第 4 步:查看效果第 5 步:调试 JS 代码😂 背景:有个网站,每次进去都要点 3 次才能把相关页面展开。而且,页面经常会自己刷新,导致展开的页面又收回去了。【这一天天的…

【Python】实现极致:克服PyInstaller打包挑战,解决libpython3.10.so.1.0库丢失难题

【Python】实现极致&#xff1a;克服PyInstaller打包挑战&#xff0c;解决libpython3.10.so.1.0库丢失难题 大家好 我是寸铁&#x1f44a; 总结了一篇【Python】实现极致&#xff1a;克服PyInstaller打包挑战&#xff0c;解决libpython3.10.so.1.0库丢失难题✨ 喜欢的小伙伴可以…

MFC设置窗口在Z轴上的位置

函数原型&#xff1a; BOOL CWnd::SetWindowPos(const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags);返回值&#xff1a; 如果函数成功&#xff0c;则返回非零值&#xff1b;否则返回0。 参数&#xff1a; pWndInsertAfter&#xff1a;标识了在Z轴次…