Browse Source
Merge branch 'huangyongxing/feature-20260327161252-学习笔记' into milestone-20260325-学习笔记
milestone-20260325-学习笔记
Merge branch 'huangyongxing/feature-20260327161252-学习笔记' into milestone-20260325-学习笔记
milestone-20260325-学习笔记
12 changed files with 369 additions and 0 deletions
-
BIN黄永兴学习笔记/4.1黄永兴-项目案例笔记.docx
-
3黄永兴学习笔记/智能客服demo/SpringAIAlibaba/.mvn/wrapper/maven-wrapper.properties
-
10黄永兴学习笔记/智能客服demo/SpringAIAlibaba/SpringAIAlibaba.iml
-
127黄永兴学习笔记/智能客服demo/SpringAIAlibaba/pom.xml
-
13黄永兴学习笔记/智能客服demo/SpringAIAlibaba/src/main/java/com/example/springaialibaba/SpringAiAlibabaApplication.java
-
177黄永兴学习笔记/智能客服demo/SpringAIAlibaba/src/main/java/com/example/springaialibaba/controller/CustomerServiceController.java
-
13黄永兴学习笔记/智能客服demo/SpringAIAlibaba/src/main/resources/application.yml
-
13黄永兴学习笔记/智能客服demo/SpringAIAlibaba/src/test/java/com/example/springaialibaba/SpringAiAlibabaApplicationTests.java
-
13黄永兴学习笔记/智能客服demo/SpringAIAlibaba/target/classes/application.yml
-
BIN黄永兴学习笔记/智能客服demo/SpringAIAlibaba/target/classes/com/example/springaialibaba/SpringAiAlibabaApplication.class
-
BIN黄永兴学习笔记/智能客服demo/SpringAIAlibaba/target/classes/com/example/springaialibaba/controller/CustomerServiceController.class
-
BIN黄永兴学习笔记/智能客服demo/SpringAIAlibaba/target/test-classes/com/example/springaialibaba/SpringAiAlibabaApplicationTests.class
@ -0,0 +1,3 @@ |
|||||
|
wrapperVersion=3.3.4 |
||||
|
distributionType=only-script |
||||
|
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.14/apache-maven-3.9.14-bin.zip |
||||
@ -0,0 +1,10 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<module version="4"> |
||||
|
<component name="AdditionalModuleElements"> |
||||
|
<content url="file://$MODULE_DIR$" dumb="true"> |
||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> |
||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> |
||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> |
||||
|
</content> |
||||
|
</component> |
||||
|
</module> |
||||
@ -0,0 +1,127 @@ |
|||||
|
<?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.5.13</version> |
||||
|
<relativePath/> <!-- lookup parent from repository --> |
||||
|
</parent> |
||||
|
<groupId>com.example</groupId> |
||||
|
<artifactId>SpringAIAlibaba</artifactId> |
||||
|
<version>1.1.2.0</version> |
||||
|
<name>SpringAIAlibaba</name> |
||||
|
<description>SpringAIAlibaba</description> |
||||
|
|
||||
|
<properties> |
||||
|
<java.version>17</java.version> |
||||
|
<!-- 阿里云DashScope SDK版本(官方要求>=2.15.0) --> |
||||
|
<dashscope.version>2.22.13</dashscope.version> |
||||
|
<!-- RxJava版本(适配DashScope SDK) --> |
||||
|
<rxjava.version>2.2.21</rxjava.version> |
||||
|
</properties> |
||||
|
|
||||
|
<url/> |
||||
|
<licenses> |
||||
|
<license/> |
||||
|
</licenses> |
||||
|
<developers> |
||||
|
<developer/> |
||||
|
</developers> |
||||
|
<scm> |
||||
|
<connection/> |
||||
|
<developerConnection/> |
||||
|
<tag/> |
||||
|
<url/> |
||||
|
</scm> |
||||
|
|
||||
|
<dependencyManagement> |
||||
|
<dependencies> |
||||
|
<dependency> |
||||
|
<groupId>com.alibaba.cloud.ai</groupId> |
||||
|
<artifactId>spring-ai-alibaba-bom</artifactId> |
||||
|
<version>1.1.2.0</version> |
||||
|
<type>pom</type> |
||||
|
<scope>import</scope> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.ai</groupId> |
||||
|
<artifactId>spring-ai-bom</artifactId> |
||||
|
<version>1.1.2</version> |
||||
|
<type>pom</type> |
||||
|
<scope>import</scope> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.alibaba.cloud.ai</groupId> |
||||
|
<artifactId>spring-ai-alibaba-extensions-bom</artifactId> |
||||
|
<version>1.1.2.1</version> |
||||
|
<type>pom</type> |
||||
|
<scope>import</scope> |
||||
|
</dependency> |
||||
|
</dependencies> |
||||
|
</dependencyManagement> |
||||
|
|
||||
|
<dependencies> |
||||
|
|
||||
|
|
||||
|
<!-- Spring AI Alibaba Agent Framework --> |
||||
|
<dependency> |
||||
|
<groupId>com.alibaba.cloud.ai</groupId> |
||||
|
<artifactId>spring-ai-alibaba-agent-framework</artifactId> |
||||
|
<version>1.1.2.0</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- DashScope ChatModel 支持(如果使用其他模型,请跳转 Spring AI 文档选择对应的 starter) --> |
||||
|
<dependency> |
||||
|
<groupId>com.alibaba.cloud.ai</groupId> |
||||
|
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId> |
||||
|
<version>1.1.2.0</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-web</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>io.projectreactor.addons</groupId> |
||||
|
<artifactId>reactor-adapter</artifactId> |
||||
|
<version>3.5.0</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.projectlombok</groupId> |
||||
|
<artifactId>lombok</artifactId> |
||||
|
<optional>true</optional> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- 1. 阿里云DashScope官方SDK(解决所有dashscope包报红) --> |
||||
|
<dependency> |
||||
|
<groupId>com.alibaba</groupId> |
||||
|
<artifactId>dashscope-sdk-java</artifactId> |
||||
|
<version>${dashscope.version}</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- 2. RxJava 2.x(解决io.reactivex.Flowable报红) --> |
||||
|
<dependency> |
||||
|
<groupId>io.reactivex.rxjava2</groupId> |
||||
|
<artifactId>rxjava</artifactId> |
||||
|
<version>${rxjava.version}</version> |
||||
|
</dependency> |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
</dependencies> |
||||
|
|
||||
|
<build> |
||||
|
<plugins> |
||||
|
<plugin> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-maven-plugin</artifactId> |
||||
|
</plugin> |
||||
|
</plugins> |
||||
|
</build> |
||||
|
|
||||
|
</project> |
||||
@ -0,0 +1,13 @@ |
|||||
|
package com.example.springaialibaba; |
||||
|
|
||||
|
import org.springframework.boot.SpringApplication; |
||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
|
||||
|
@SpringBootApplication |
||||
|
public class SpringAiAlibabaApplication { |
||||
|
|
||||
|
public static void main(String[] args) { |
||||
|
SpringApplication.run(SpringAiAlibabaApplication.class, args); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,177 @@ |
|||||
|
package com.example.springaialibaba.controller; |
||||
|
|
||||
|
|
||||
|
import com.alibaba.cloud.ai.dashscope.agent.DashScopeAgent; |
||||
|
import com.alibaba.cloud.ai.dashscope.agent.DashScopeAgentOptions; |
||||
|
import com.alibaba.dashscope.app.Application; |
||||
|
import com.alibaba.dashscope.app.ApplicationParam; |
||||
|
import com.alibaba.dashscope.app.ApplicationResult; |
||||
|
import com.alibaba.dashscope.app.FlowStreamMode; |
||||
|
import com.alibaba.dashscope.exception.InputRequiredException; |
||||
|
import com.alibaba.dashscope.exception.NoApiKeyException; |
||||
|
import io.reactivex.Flowable; |
||||
|
import jakarta.servlet.http.HttpServletResponse; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.ai.chat.model.ChatResponse; |
||||
|
import org.springframework.ai.chat.prompt.Prompt; |
||||
|
import org.springframework.http.MediaType; |
||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||
|
import org.springframework.web.bind.annotation.RestController; |
||||
|
import reactor.adapter.rxjava.RxJava2Adapter; |
||||
|
import reactor.core.publisher.Flux; |
||||
|
|
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
|
||||
|
@Slf4j |
||||
|
@RestController |
||||
|
@RequiredArgsConstructor //使用RequiredArgsConstructor注解,自动注入final类型的字段 |
||||
|
@RequestMapping("/customer") |
||||
|
public class CustomerServiceController { |
||||
|
|
||||
|
//注入Spring AI Alibaba Agent |
||||
|
//@Autowired |
||||
|
private final DashScopeAgent dashScopeAgent; |
||||
|
|
||||
|
/** |
||||
|
* 智能客服接口(非流式,同步获取结果) |
||||
|
* @param question 用户问题 |
||||
|
* @return 知识库标准答案 |
||||
|
*/ |
||||
|
@GetMapping("/service") |
||||
|
public String customerService(@RequestParam("question") String question) { |
||||
|
|
||||
|
try { |
||||
|
/* |
||||
|
DashScopeAgentOptions 是工作流 / 智能体的调用参数,它只负责「触发工作流」,不负责「修改大模型的推理参数」。 |
||||
|
因为 Spring AI Alibaba 的自动配置在工作流(Agent)模式下不生效! |
||||
|
*/ |
||||
|
|
||||
|
// |
||||
|
/* ChatResponse response = dashScopeAgent.call( |
||||
|
new Prompt(question, DashScopeAgentOptions.builder() |
||||
|
.appId("df04e1abf24a416c8702260e88863ac4") |
||||
|
.build() |
||||
|
) |
||||
|
); |
||||
|
|
||||
|
return response.getResult().getOutput().getText();*/ |
||||
|
|
||||
|
ApplicationParam param = ApplicationParam.builder() |
||||
|
// 若没有配置环境变量,可用百炼API Key将下行替换为:.apiKey("sk-xxx")。但不建议在生产环境中直接将API Key硬编码到代码中,以减少API Key泄露风险。 |
||||
|
.apiKey(System.getenv("sk-f7d2253302b547c7a2fe257673cb854b")) |
||||
|
.appId("df04e1abf24a416c8702260e88863ac4") |
||||
|
.prompt(question) |
||||
|
.build(); |
||||
|
|
||||
|
Application application = new Application(); |
||||
|
ApplicationResult result = application.call(param); |
||||
|
return result.getOutput().getText(); |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
log.error("客服调用失败", e); |
||||
|
return "抱歉,智能客服暂时无法响应,请联系人工客服。"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 官方原生流式调用(1:1对照文档) |
||||
|
@GetMapping(value = "/service2", produces = MediaType.TEXT_HTML_VALUE + ";charset=UTF-8") |
||||
|
public Flux<String> customerService2( |
||||
|
@RequestParam("question") String question, |
||||
|
HttpServletResponse response |
||||
|
) { |
||||
|
//设置字符编码为UTF-8,解决中文乱码问题 |
||||
|
response.setCharacterEncoding("UTF-8"); |
||||
|
|
||||
|
try { |
||||
|
// ============================================== |
||||
|
// 【官方原版写法】 |
||||
|
// ============================================== |
||||
|
ApplicationParam param = ApplicationParam.builder() |
||||
|
.apiKey("sk-f7d2253302b547c7a2fe257673cb854b") // 你的API Key |
||||
|
.appId("df04e1abf24a416c8702260e88863ac4") |
||||
|
.prompt(question) |
||||
|
.incrementalOutput(true) // 官方:流式必须开 |
||||
|
.flowStreamMode(FlowStreamMode.MESSAGE_FORMAT) // 设置为流模式 |
||||
|
.build(); |
||||
|
|
||||
|
Application application = new Application(); |
||||
|
|
||||
|
// 官方流式调用 |
||||
|
Flowable<ApplicationResult> resultFlowable = application.streamCall(param); |
||||
|
|
||||
|
// 把 RxJava Flowable → Spring Flux(用于SSE输出) |
||||
|
// 正确的流式处理逻辑 |
||||
|
System.out.println(resultFlowable); |
||||
|
|
||||
|
/* return Flux.create(sink -> { |
||||
|
resultFlowable.subscribe( |
||||
|
res -> { |
||||
|
try { |
||||
|
if (res != null && res.getOutput() != null) { |
||||
|
String content = null; |
||||
|
|
||||
|
if ("stop".equals(res.getOutput().getFinishReason())) { |
||||
|
// 流结束 |
||||
|
content = res.getOutput().getText(); |
||||
|
if (content != null && !content.trim().isEmpty()) { |
||||
|
sink.next("data: " + content + "\n\n"); |
||||
|
} |
||||
|
} else { |
||||
|
// 流式输出 |
||||
|
if (res.getOutput().getWorkflowMessage() != null && |
||||
|
res.getOutput().getWorkflowMessage().getMessage() != null) { |
||||
|
|
||||
|
content = res.getOutput().getWorkflowMessage() |
||||
|
.getMessage().getContent(); |
||||
|
|
||||
|
if (content != null && !content.trim().isEmpty()) { |
||||
|
sink.next("data: " + content + "\n\n"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
log.error("处理响应异常", e); |
||||
|
} |
||||
|
}, |
||||
|
error -> { |
||||
|
log.error("流式调用异常", error); |
||||
|
sink.next("data: 服务调用异常\n\n"); |
||||
|
sink.complete(); |
||||
|
}, |
||||
|
() -> { |
||||
|
log.info("流式调用完成"); |
||||
|
sink.complete(); |
||||
|
} |
||||
|
); |
||||
|
});*/ |
||||
|
|
||||
|
// RxJava适配器 flowable 转换为 flux |
||||
|
return RxJava2Adapter.flowableToFlux(resultFlowable) |
||||
|
.map(this::extractContent) |
||||
|
.filter(content -> content != null && !content.trim().isEmpty()) |
||||
|
.map(content -> "data: " + content + "\n\n"); |
||||
|
|
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
log.error("客服调用失败", e); |
||||
|
return Flux.error(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 从 ApplicationResult 中提取内容 |
||||
|
private String extractContent(ApplicationResult res) { |
||||
|
if (res == null || res.getOutput() == null) return null; |
||||
|
|
||||
|
if ("stop".equals(res.getOutput().getFinishReason())) { |
||||
|
return res.getOutput().getText(); |
||||
|
} else if (res.getOutput().getWorkflowMessage() != null && |
||||
|
res.getOutput().getWorkflowMessage().getMessage() != null) { |
||||
|
return res.getOutput().getWorkflowMessage().getMessage().getContent(); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
server: |
||||
|
port: 8080 |
||||
|
|
||||
|
spring: |
||||
|
ai: |
||||
|
dashscope: |
||||
|
# 核心:工作流应用的AppId |
||||
|
agent: |
||||
|
app-id: df04e1abf24a416c8702260e88863ac4 |
||||
|
# 核心:你的API-Key |
||||
|
api-key: sk-f7d2253302b547c7a2fe257673cb854b |
||||
|
# 业务空间ID |
||||
|
workspace-id: llm-fuczq7vkh8vyz716 |
||||
@ -0,0 +1,13 @@ |
|||||
|
package com.example.springaialibaba; |
||||
|
|
||||
|
import org.junit.jupiter.api.Test; |
||||
|
import org.springframework.boot.test.context.SpringBootTest; |
||||
|
|
||||
|
@SpringBootTest |
||||
|
class SpringAiAlibabaApplicationTests { |
||||
|
|
||||
|
@Test |
||||
|
void contextLoads() { |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
server: |
||||
|
port: 8080 |
||||
|
|
||||
|
spring: |
||||
|
ai: |
||||
|
dashscope: |
||||
|
# 核心:工作流应用的AppId |
||||
|
agent: |
||||
|
app-id: df04e1abf24a416c8702260e88863ac4 |
||||
|
# 核心:你的API-Key |
||||
|
api-key: sk-f7d2253302b547c7a2fe257673cb854b |
||||
|
# 业务空间ID |
||||
|
workspace-id: llm-fuczq7vkh8vyz716 |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue