SpringBoot和Vue3实战阿里百炼大模型极简版

实战效果

刚开始用ppt录制的视频,导进来有声音,又通过视频转gif网站转成了图片

支持markdown格式显示,流式调用

前期准备

阿里云百炼控制台申请apikey和创建智能体应用得到appid,并配置到系统环境变量。

同时要注意使用的模型用量,记得开启免费额度用完即停

一个模型免费额度用完了可以到应用配置里切换成其他模型,同时在智能体应用配置里可以做两个配置,最大回复token可以改小一点,这样测试的次数会多一点。同时关闭自主思考enbale thinking,这样流式调用返回的结果会快一点

后端代码

jdk使用17版本,电脑是win7系统,IDEA版本是2021.3

控制器

java 复制代码
package com.xmliu.alidemo;

import com.alibaba.cloud.ai.dashscope.agent.DashScopeAgent;
import com.alibaba.cloud.ai.dashscope.agent.DashScopeAgentOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/ai")
public class BailianStreamController {

    private static final Logger logger = LoggerFactory.getLogger(BailianStreamController.class);
    private DashScopeAgent agent;

    @Value("${spring.ai.dashscope.agent.app-id}")
    private String appId;

    @CrossOrigin(origins = "http://localhost:3000")
    @GetMapping(value = "/bailian/agent/stream", produces = "text/event-stream;charset=UTF-8")
    public Flux<String> stream(@RequestParam(value = "message",
            defaultValue = "知识库文档主要内容是什么?") String message) {
        logger.info("----开始流式聊天----");
        return agent.stream(new Prompt(message, DashScopeAgentOptions.builder().withAppId(appId).build()))
                .map(response -> {
                    if (response == null || response.getResult() == null) {
                        logger.error("chat response is null");
                        // 空响应返回空串,最后统一处理
                        return "";
                    }
                    AssistantMessage app_output = response.getResult().getOutput();
                    String content = app_output.getText();
                    logger.info("content:\n{}\n\n", content);
                    return content != null ? content : "";
                })
                // 过滤空字符串
                .filter(content -> !content.isBlank())
                // 流结束追加标识
                .concatWith(Mono.just("data:__STREAM_END__"));
    }
}

配置文件

application.properties,其中appid和key配置在系统环境变量中,故代码里看不到具体的值

xml 复制代码
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: 9000

POM文件

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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

javascript 复制代码
<template>
	<h1 class="box">阿里百炼大模型智能体应用测试</h1>
	<div class="chat-container">
		<div class="reply-content">
			<span v-html="parsedReply"></span>
			<span v-if="errorMsg" class="error-tip">{{errorMsg}}</span>
		</div>
		<div class="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'
	const question = ref('')
	const reply = ref('')
	const isLoading = ref(false)
	const errorMsg = ref('')

	const parsedReply = computed(() => {
		return marked.parse(reply.value)
	})
	// 调用后端接口
	const send = async () => {
		console.log("点击了按钮")
		if (!question.value.trim()) return;
		isLoading.value = true
		reply.value = ''
		errorMsg.value = ''

		try {
			const url =
				`http://127.0.0.1:8080/ai/bailian/agent/stream?message=${encodeURIComponent(question.value)}`
			const eventSoure = new EventSource(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 = false
			errorMsg.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: 0 20px;
	}

	.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-color 0.2s;
	}

	.chat-input :focus {
		border-color: #1677ff;
	}

	.send-button {
		padding: 0 24px;
		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: blink 1.2s infinite;
	}

	@keyframes blink {

		0%,
		100% {
			opacity: 0;
		}

		50% {
			opacity: 1;
		}
	}

	.reply-content {
		text-align: left;
		min-height: 40px;
		margin: 20px 0;
	}

	.reply-content h1 {
		font-size: 20px;
		font-weight: bold;

	}

	.reply-content code {
		background: #f5f5f5;
		padding: 2px 4px;
	}

	.box {
		text-align: center;
	}
</style>
相关推荐
程序员晓琪3 小时前
约定大于配置:基于 Java 包名自动生成 API 版本路由的最佳实践
java·spring boot·后端
Flittly3 小时前
【AgentScope Java新手村系列】(11)中断与恢复
java·spring boot·spring
doiito7 小时前
【Agent Harness】为什么我把 JSON‑LD “编译成 DAG” 后,整个 Agent 平台立刻聪明了
ai·rust·架构设计·系统设计·ai agent
xiezhr12 小时前
折腾半小时,终于让AI 能直接帮我写飞书文档了
ai·飞书·ai agent·飞书cli·飞书文档
岳小哥AI12 小时前
Claude Fable和Claude Mythos 5同时发布:注意力机制下愈加强大的AI大模型
ai·ai基础
Artech12 小时前
[MAF预定义的AIContextProvider-04]Mem0Provider——长期记忆基于的云端解决方案
ai·agent·maf·aicontextprovider·chathistorymemoryprovider·mem0provider
哥不是小萝莉1 天前
一文读懂 OpenAI Codex 源码的原理、架构与未来
ai
用户3521802454751 天前
🎆从 Prompt 到 Skill:让 Spring AI Agent 学会"装新技能"
人工智能·spring boot·ai编程
AlfredZhao1 天前
AI 编程工作总结:从体验问题到模块能力建设
ai·codex
cup112 天前
[技术复盘] Windows Python 打包实战:Nuitka 环境踩坑总结与 CI 自动化构建全指南
python·ai·环境变量·ci·nuitka·skill