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>
相关推荐
AI绘画哇哒哒4 小时前
【建议收藏!】35岁后端血泪忠告,这3类人别硬转Agent(过来人亲述)
java·人工智能·后端·ai·程序员·大模型·agent
QN1幻化引擎5 小时前
DalinX Phi 性能突破:跨层秩保持对齐与意识涌现度量的实证研究
人工智能·ai·架构·agi·asi
龙兵AI增长破局圈.赵老师讲成交5 小时前
只有把过程管好,结果才会出来。
大数据·人工智能·ai·创业创新
最强小杰5 小时前
gpt-5.6-sol 频繁报 503 怎么办?区分容量熔断和限速 429 的排查方法 + 可复用 retry wrapper
java·人工智能·gpt·ai
你是一个铁憨憨6 小时前
从 GIS 到 Spatial Agent:MCP 如何重新定义 GIS 的 AI 入口
arcgis·ai·agent·mcp·spatial
2601_953720827 小时前
【计算机毕业设计】基于Vue与Spring Boot的高校兼职信息服务平台设计与实现
spring boot·后端·课程设计
evans在进步10 小时前
Spring Boot 核心机制详解:可执行 JAR、CORS、静态资源与配置绑定
spring boot·后端·jar
Sayuanni%310 小时前
SpringBoot 从注解到源码:核心知识点总结
java·spring boot·后端
奇牙coding12311 小时前
gpt-5.6-luna 频繁 429 但 gpt-5.5 正常怎么办?不是配额问题,是 luna 独立的并发 session 限速桶
gpt·ai
安逸sgr11 小时前
AI 应用怎么评测?离线评测、人工评估和线上反馈如何结合?
人工智能·ai·大模型·agent·智能体