ai应用一篇通【react环境】

发布时间:2026/7/24 18:02:07

ai应用一篇通【react环境】
首先进行技术选型。1 Deepseek文本大模型其官方具备面向nodejs环境的openai调用模型的sdk。2 环境直接起一个react项目直接在前端项目中调用Deepseek仅学习用生产还是要起nodejs轻服务。一 流式多轮对话1.1 基础请求先发出一个简单的文本请求。下面的apiKey需要替换为自己的key在deepseek开发平台中获取。下面的代码包含了OpenAI的简单用法importOpenAIfromopenai;import{useState,useEffect}fromreact;constopenainewOpenAI({baseURL:https://api.deepseek.com,apiKey:xxxxxxxxxxxxxxxxxxxxx,dangerouslyAllowBrowser:true,});exportdefaultfunctionDeepseekPage(){const[chatList,setChatList]useState([])useEffect((){openai.chat.completions.create({messages:[{role:system,content:You are a helpful assistant.},{role:user,content:hello.},],model:deepseek-v4-flash,thinking:{type:disabled},stream:false,}).then(res{console.log(res.choices[0].message.content);});},[])return(div{chatList.map((msg,index)(div key{index}strong{msg.role}:/strong{msg.content}/div))}/div)}注意下面代码中打印了一个res.choices[0].message.content内容如下{role:assistant,content:Hi! How can I help you today?}其中content是内容role是角色。现在页面上已经展示了一行返回内容了。1.2 多轮对话多轮对话的核心是将第一轮中模型的输出添加到 messages 末尾。上面代码中第一次请求的参数是这样的[{role:system,content:You are a helpful assistant.},{role:user,content:hello.},]我们将返回体和用户的写入内容追加到后面使参数变为[{role:system,content:You are a helpful assistant.},{role:user,content:hello.},{role:assistant,content:Hi! How can I help you today?}{role:user,content:xxxxxx},]同时在用户点击发送后触发接口请求。现在我们要做两件事1 上面代码中的useEffect要重复触发触发条件是有新的用户信息产生时所以书写一个变量记录该信息列表chatList并将其加入到useEffect依赖项中。2 状态的触发需要入口所以添加input和submit入口。exportdefaultfunctionDeepseekPage(){const[chatList,setChatList]useState([{role:system,content:You are a helpful assistant.},{role:user,content:hello.},])const[input,setInput]useState()useEffect((){if(chatList[chatList.length-1].role!user)returnopenai.chat.completions.create({messages:chatList,model:deepseek-v4-flash,thinking:{type:disabled},stream:false,}).then(res{console.log(res.choices[0].message.content);setChatList([...chatList,res.choices[0].message])});},[chatList])return(div{chatList.map((msg,index)(div key{index}strong{msg.role}:/strong{msg.content}/div))}Space vertical sizemediumSpace.Compact style{{width:100%}}Input defaultValueCombine input and buttonvalue{input}onChange{(e)setInput(e.target.value)}/Button typeprimaryonClick{(){setChatList([...chatList,{role:user,content:input}])}}Submit/Button/Space.Compact/Space/div)}现在输入文字点击按钮就可以实现多轮对话了。1.3 流式传输现在ai返回的语句是一次性全部返回的等待时候较长。我们使用ai对话的时候可以让它陆续返回实现打字机效果就是流式传输了。首先将stream设置为true让其开启流式传输。其次要在js中补充承接逻辑。1.3.1 fetch如果使用fetch来处理返回值会返回两个重要的数据value和doneReading。doneReading是流式数据是否已全部返回。value是返回的内容使用new TextDecoder().decode(value)进行解析读取。返回的内容解析后可能出现的情况示例如下第一轮返回data:{choices:[{delta:{content:你第二轮返回}}]}\n\n可以看到解析的时候一个有效json会分成多次返回一个有效json由data开启由\n结束。整个代码逻辑如下1 判断是否已经全部返回否则循环获取数据。2 将本次数据与上次数据相结合形成本次校验是否形成有效json?数据chunkValue。3 将有效数据以’data: ‘为开头’\n’为结尾取出4 解析json串后赋值1.3.2 openai我们这里使用openai来处理。首先将openai.chat.completions.create中的stream设置为true让其开启流式传输。先把useEffect中的代码提取出来成为方法使用。因为这个方法是独立性比较强的所以不需要封装为hook。const getCharDateasync(dataList, callback, streamfalse){letresawait openai.chat.completions.create({messages: dataList, model:deepseek-v4-flash, thinking:{type:disabled}, stream: stream,})callback([...dataList, res.choices[0].message])}现在添加流式处理逻辑。openai已对其做了封装实现流式就比较容易。其会返回异步迭代器Async Iterator直接使用 for await…of 循环来逐块获取数据即可。forawait(const chunk of res){console.log(chunk)}上面打印出的chunk示例如下{id:5a3ce01f-1353-47ed-b355-0337dc890ff6, // 对话id 多组流式对话时靠它拼接object:chat.completion.chunk,created:1784792183,model:deepseek-v4-flash,system_fingerprint:fp_8b330d02d0_prod0820_fp8_kvcache_20260402,choices:[{index:0,delta:{role:assistant,content:// 数据放在这里},logprobs:null,finish_reason:null}]}现在根据chunk内容list有值则拼接无值则添加对话项将id记录在项中用来寻找对应项。forawait(constchunkofres){callback(prevList{constchartIndexItemprevList.findIndex(item{returnitem.charIdchunk.id})if(chartIndexItem-1){return[...prevList,{...chunk.choices[0].delta,charId:chunk.id}]}else{returnprevList.map(item{if(item.charIdchunk.id){return{...item,content:item.contentchunk.choices[0].delta.content}}else{returnitem}})}})}如此就实现了流式效果。1.3.3 设置node中间层上面是在前端项目中直接请求的openai接口实际项目中需要使用node中间层做中转以保护key。中转层在操作时需要注意一下几点:1 发出请求时注意请求头的正确性{Content-Type:text/event-stream,Cache-Control:no-cache,Connection:keep-alive,}返回数据时使用res.write陆续返回。数据返回结束后使用res.end();结束接口。其他逻辑和前端项目中的内容等同都是通过openai获取chund后对数据进行处理。前端可以使用fetch读取流式数据axios不支持。fetch读取流式数据的方式上面有介绍。使用response.body.getReader().read()读取内容new TextDecoder().decode(value)进行解码。response.body.getReader().read()反复读取直到返回的done为true时break。这里也可以使用EventSource但是EventSource仅支持get接口不支持太长的上下文传递。const eventSourcenew EventSource(url);eventSource.addEventListener(message, function(e: any){content.valuee.data;});eventSource.addEventListener(end,(){eventSource.close();});个人更推荐仍然使用openai来在前端读取只是不写秘钥把url改成node中间层的地址。二 图像生成我们仍然选用国内场景大模型可灵ai来做示范。可灵ai需要比文本请求多做一件事通过jsonwebtoken包换取token。当然这一步在生产上肯定是后端做的这里我们就放在前端了。npm i jsonwebtoken安装依赖。2.1 发布任务可灵ai首页左侧有开发者平台按钮开发者平台右上角能进入控制台买个试用资源包然后创建key。和文本一样在header中写Authorization “Bearer XXX”其中 XXX 填写第一步获取的 API Key。现在页面中准备好相关的内容。divstyle{{margin:10px}}Imagewidth{200}srchttps://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png//divSpace verticalsizemediumSpace.Compactstyle{{width:100%}}InputdefaultValueCombine input and buttonvalue{pInput}onChange{(e)setPInput(e.target.value)}/ButtontypeprimaryonClick{()getImage(pInput)}图片生成/Button/Space.Compact/Space然后在getImage事件中根据pInput的值获取图片把图片url给image组件即可。api调用文档https://klingai.com/document-api/api/image/2-1/image-generationconst getImageasync(imageInput){const endPointhttps://api-beijing.klingai.com/v1/images/generationsletresfetch(endPoint,{headers:{Content-Type:application/json,Authorization:Bearer xxxx,}, method:POST, body: JSON.stringify({prompt: imageInput, aspect_ratio:1:1,})})if(res.status400){throw new Error(Non-200 response: ${await res.text()});}const resJsonawait res.json();constidresJson.data.task_id;const resultUrl${endpoint}/${id};console.log(id, resultUrl)// while(true){// 循环获取图片内容直到生成成功 // 返回task_status标志位为succeed即成功 // 成功后task_result中有生成图片的url //}}可灵ai是不支持跨域的所以咋package.json中配置proxy来进行跨域。在文本框中输入文字后点击图片生成id。909536646579253261/v1/images/generations/909536646579253261根据这个id就可以来获取图片内容了。2.2 获取图片现在将while中的内容补全。while(true){// console.log(resJson,id)// 循环获取图片内容直到生成成功// 返回task_status标志位为succeed即成功// 成功后task_result中有生成图片的urlawaitnewPromise((resolve)setTimeout(resolve,100));// 预防堵塞 让出主线程constresultawaitfetch(resultUrl,{headers:{Content-Type:application/json,Authorization:Bearer xxxx,}});constresultJsonawaitresult.json();console.log(resultJson)consttaskStatusresultJson.data.task_status;if(taskStatussucceed){console.log(resultJson.data?.task_result.images[0].url)setImageUrl(resultJson.data?.task_result.images[0].url)returnresultJson.data?.task_result.images[0].url}else{continue}}setImageUrl是这个方法的第二个参数用来赋值图片地址。现在点击生成图片页面上就出现了图片。三 AI应用智能体-------------------------------------------------------------------------------------------------------------未完待续 持续更新

相关新闻

TFLite Micro农业场景声音分类部署实战:鸟鸣、虫鸣与机械噪音的多类别端侧识别系统

TFLite Micro农业场景声音分类部署实战:鸟鸣、虫鸣与机械噪音的多类别端侧识别系统

2026/7/24 17:52:07

TFLite Micro农业场景声音分类部署实战:鸟鸣、虫鸣与机械噪音的多类别端侧识别系统 一、引言:音频分类在智慧农业中的独特价值 农田环境中的声音信息承载着丰富的生态和机械状态信号。鸟类的鸣叫频度可以作为生物多样性的指示指标,而特定害…

装闭 RenoPit 源码解析(05):FastAPI与Celery如何执行AI装修分析

装闭 RenoPit 源码解析(05):FastAPI与Celery如何执行AI装修分析

2026/7/24 17:52:07

AI 装修闭坑分析可能包含多张图片、多份合同以及多次大模型调用,不适合让 FastAPI 请求一直阻塞。装闭 RenoPit 在 fthux/RenoPit 中使用 Celery 和 Redis 编排这条长任务链,本篇分析任务从入队到结束的全过程。 一、FastAPI 只负责启动任务 用户点击“…

百度网盘下载速度突然很慢怎么回事?2026还有解除限制的方法吗

百度网盘下载速度突然很慢怎么回事?2026还有解除限制的方法吗

2026/7/24 17:52:07

不少人可能会遇到这样的困扰:在日常日常使用网络存储服务时,原本几兆甚至几十兆每秒的传输速度,忽然降到了几十KB,或者出现速度忽高忽低、频繁波动的状况。这种现象通常由多重因素共同作用产生,下面梳理了常见的原因及…

Claude模型的道德AI框架与实践解析

Claude模型的道德AI框架与实践解析

2026/7/24 19:02:10

1. Anthropic与Claude模型的核心道德框架解析当Anthropic在2021年由前OpenAI团队创立时,其创始人Dario Amodei就明确表示:"我们要建造的AI系统,必须从底层架构就嵌入安全性和可解释性"。这种理念直接催生了《Claude公约》——这份被…

DeepSeek全栈AI平台技术解析与应用实践

DeepSeek全栈AI平台技术解析与应用实践

2026/7/24 19:02:10

1. 项目概述:DeepSeek的技术定位与行业价值 DeepSeek作为新一代全栈AI技术平台,正在通过其独特的技术架构和开放生态重塑行业智能化标准。这个项目名称中的"技术筑魂"直指其核心优势——将前沿AI能力深度融入技术栈底层,而"向…

WarcraftHelper深度解析:4步打造魔兽争霸III稳定体验的专业方案

WarcraftHelper深度解析:4步打造魔兽争霸III稳定体验的专业方案

2026/7/24 19:02:10

WarcraftHelper深度解析:4步打造魔兽争霸III稳定体验的专业方案 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper WarcraftHelper作为魔兽争…

BQ25713 PROCHOT功能详解:动态电源管理与CPU热保护实战

BQ25713 PROCHOT功能详解:动态电源管理与CPU热保护实战

2026/7/24 19:02:10

1. 项目概述与核心价值在笔记本电脑、平板电脑这类移动设备的电源系统设计里,有一个看似不起眼但至关重要的功能,它像一位沉默的哨兵,时刻守护着系统的稳定与安全。这个功能就是PROCHOT,全称Processor Hot,直译过来就是…

ComfyUI模型配置文件model-list.json详解与实战指南

ComfyUI模型配置文件model-list.json详解与实战指南

2026/7/24 19:02:10

1. 项目概述秋叶ComfyUI启动器的model-list.json配置文件是ComfyUI生态中管理AI模型的核心枢纽文件。作为一款面向Stable Diffusion工作流的可视化节点编辑器,ComfyUI通过这个配置文件实现了对各类AI模型(如基础模型、LoRA、ControlNet等)的集…

配置系统策略禁用u盘等外设

配置系统策略禁用u盘等外设

2026/7/24 18:52:09

在日常办公或公共电脑维护中,我们经常面临这样的困扰:公司内部资料需要严防外泄,可总有员工随手插U盘拷贝文件;学校机房的电脑病毒泛滥,源头往往就是学生带来的个人U盘;甚至有些场景下,我们希望…

微服务进阶:服务网格与Istio

微服务进阶:服务网格与Istio

2026/7/24 4:17:29

541|微服务进阶:服务网格与Istio 上篇文章我们聊了微服务的基本概念和拆分方法。 但微服务多了,问题也多了: 服务之间怎么通信? 怎么监控每个服务的调用链路? 熔断、限流、重试怎么做? 安全认证怎么统一? 以前这些都靠SDK库(比如Hystrix、Feign),每个服务都要集成…

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

2026/7/23 4:40:05

一、零售门店全域协同业务背景与行业痛点 1.1 门店超级终端设备矩阵(连锁便利店/商超标准配置) 自助收银Kiosk一体机:顾客结算、自助核销优惠券、商品素材预览;运营折叠平板:店长后台商品上新、图片录入、活动配置、…

噗叽短视频界面分析

噗叽短视频界面分析

2026/7/23 1:54:13

1 和小红书类似,可以采用类似判断方法------------其实他比小红书好判断,因为他没有图片,控件位置几乎是固定的,都不用判断------------2 因为他没有点赞按钮------------而且几乎所有控件位置都是完全一样的,所以我就…

Django毕设项目:基于 Django 的 智能化学生综合素质测评审核系统 校园学生评优评奖综合管理系统(源码+文档,讲解、调试运行,定制等)

Django毕设项目:基于 Django 的 智能化学生综合素质测评审核系统 校园学生评优评奖综合管理系统(源码+文档,讲解、调试运行,定制等)

2026/7/24 0:01:07

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

[具身智能-634]:Python 封装的地平线 VIO 多媒体库:libsrcampy库详解

[具身智能-634]:Python 封装的地平线 VIO 多媒体库:libsrcampy库详解

2026/7/24 0:01:07

srcampy /libsrcampy 名称释义先明确结论: 官方文档没有公布标准化英文全称,是地平线内部项目缩写;行业公认拆解如下:srcampy Source Amplifier Python bindingsrc Source(图像源:MIPI Sensor、视频源&am…

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

2026/7/24 0:01:07

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化,核心特色:三维 X/Y/Z 三轴空间,所有散点分布在 0~10 立方体空间内;散点使用径向渐变实现立体 3D 圆球质感;支持鼠标 / 触屏拖拽画布,…