SpringBoot和Vue3实战阿里百炼大模型极简版
实战效果
刚开始用ppt录制的视频,导进来有声音,又通过视频转gif网站转成了图片
支持markdown格式显示,流式调用
前期准备
阿里云百炼控制台申请apikey和创建智能体应用得到appid,并配置到系统环境变量。
同时要注意使用的模型用量,记得开启免费额度用完即停
一个模型免费额度用完了可以到应用配置里切换成其他模型,同时在智能体应用配置里可以做两个配置,最大回复token可以改小一点,这样测试的次数会多一点。同时关闭自主思考enbale thinking,这样流式调用返回的结果会快一点
后端代码
jdk使用17版本,电脑是win7系统,IDEA版本是2021.3
控制器
packagecom.xmliu.alidemo;importcom.alibaba.cloud.ai.dashscope.agent.DashScopeAgent;importcom.alibaba.cloud.ai.dashscope.agent.DashScopeAgentOptions;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.ai.chat.messages.AssistantMessage;importorg.springframework.ai.chat.prompt.Prompt;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.web.bind.annotation.*;importreactor.core.publisher.Flux;importreactor.core.publisher.Mono;@RestController@RequestMapping("/ai")publicclassBailianStreamController{privatestaticfinalLoggerlogger=LoggerFactory.getLogger(BailianStreamController.class);privateDashScopeAgentagent;@Value("${spring.ai.dashscope.agent.app-id}")privateStringappId;@CrossOrigin(origins="http://localhost:3000")@GetMapping(value="/bailian/agent/stream",produces="text/event-stream;charset=UTF-8")publicFlux<String>stream(@RequestParam(value="message",defaultValue="知识库文档主要内容是什么?")Stringmessage){logger.info("----开始流式聊天----");returnagent.stream(newPrompt(message,DashScopeAgentOptions.builder().withAppId(appId).build())).map(response->{if(response==null||response.getResult()==null){logger.error("chat response is null");// 空响应返回空串,最后统一处理return"";}AssistantMessageapp_output=response.getResult().getOutput();Stringcontent=app_output.getText();logger.info("content:\n{}\n\n",content);returncontent!=null?content:"";})// 过滤空字符串.filter(content->!content.isBlank())// 流结束追加标识.concatWith(Mono.just("data:__STREAM_END__"));}}配置文件
application.properties,其中appid和key配置在系统环境变量中,故代码里看不到具体的值
spring.application.name=alidemo # appID spring.ai.dashscope.agent.app-id=${APP_ID} spring.ai.dashscope.agent.connect-timeout=30000 spring.ai.dashscope.agent.read-timeout=30000 # API Key spring.ai.dashscope.api-key=${DASHSCOPE_API_KEY} spring.ai.dashscope.logging.request-response=true server.tomcat.connection-timeout=30000 server.servlet.session.timeout=30m server.servlet.encoding.charset=UTF-8 server.servlet.encoding.enable=true server.servlet.encoding.force=true ##server: ## port: 9000POM文件
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.10</version><relativePath/><!-- lookup parent from repository --></parent><groupId>com.xmliu</groupId><artifactId>alidemo</artifactId><version>0.0.1-SNAPSHOT</version><name>alidemo</name><description/><url/><licenses><license/></licenses><developers><developer/></developers><scm><connection/><developerConnection/><tag/><url/></scm><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-dashscope</artifactId><version>1.0.0.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions><version>3.4.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId><version>3.4.0</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.14.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><executions><execution><id>default-compile</id><phase>compile</phase><goals><goal>compile</goal></goals><configuration><annotationProcessorPaths><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></path></annotationProcessorPaths></configuration></execution><execution><id>default-testCompile</id><phase>test-compile</phase><goals><goal>testCompile</goal></goals><configuration><annotationProcessorPaths><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></path></annotationProcessorPaths></configuration></execution></executions></plugin></plugins></build></project>前端代码
前端使用HbuilderX 5.07开发,nodejs版本是13.14.0,vue3开发
核心代码App.vue
<template><h1class="box">阿里百炼大模型智能体应用测试</h1><divclass="chat-container"><divclass="reply-content"><span v-html="parsedReply"></span><span v-if="errorMsg"class="error-tip">{{errorMsg}}</span></div><divclass="input-area"><input @keyup.enter="send"v-model="question"class="chat-input"placeholder="输入问题"/><button @click="send"class="send-button":class="{disabled:isLoading}":disabled="isLoading">发送</button></div></div></template><script setup>import{ref,computed,nextTick}from'vue'import{marked}from'marked'constquestion=ref('')constreply=ref('')constisLoading=ref(false)consterrorMsg=ref('')constparsedReply=computed(()=>{returnmarked.parse(reply.value)})// 调用后端接口constsend=async()=>{console.log("点击了按钮")if(!question.value.trim())return;isLoading.value=truereply.value=''errorMsg.value=''try{consturl=`http://127.0.0.1:8080/ai/bailian/agent/stream?message=${encodeURIComponent(question.value)}`consteventSoure=newEventSource(url)eventSoure.onmessage=(e)=>{console.log('e.data==',e.data)if('data:__STREAM_END__'===e.data){console.log('--------------结束-----------------------------',e.data)eventSoure.close()isLoading.value=false;return;}errorMsg.value='';reply.value+=e.data;}eventSoure.onerror=(err)=>{if(eventSoure.readyState===2){console.log("正常结束")}else{eventSoure.close()errorMsg.value='接口请求失败,请稍后再试'console.error('接口错误1',err)}isLoading.value=false}}catch(error){isLoading.value=falseerrorMsg.value='接口异常,请稍后再试'console.error('接口异常',error)}}</script><style>.error-tip{color:#ff4d4f;font-size:14px;}.loading-tip{color:#666;font-size:14px;}.chat-container{max-width:800px;margin:20px auto;padding:020px;}.input-area{display:flex;gap:10px;margin-top:20px;}.chat-input{flex:1;padding:12px 16px;border:1px solid #e0e0e0;border-radius:8px;font-size:14px;outline:none;transition:border-color0.2s;}.chat-input:focus{border-color:#1677ff;}.send-button{padding:024px;background-color:#1677ff;color:white;border:none;border-radius:8px;font-size:14px;cursor:pointer;}.send-button.disabled{background-color:#cccccc;cursor:not-allowed;}.send-button:hover{background-color:#0f5fd7;}.blink{animation:blink1.2s infinite;}@keyframes blink{0%,100%{opacity:0;}50%{opacity:1;}}.reply-content{text-align:left;min-height:40px;margin:20px0;}.reply-content h1{font-size:20px;font-weight:bold;}.reply-content code{background:#f5f5f5;padding:2px 4px;}.box{text-align:center;}</style>