Skip to content

Commit 36985aa

Browse files
authored
feat(FEL): 提供 Spring 框架启动支持 (#409)
* fel-flow说明文档 * 响应式流实现java的publisher接口 * FelSpringBootAutoConfiguration集成 * 依赖更新 * choir替换java的publisher实现 * 添加jdk的publisher测试 * 添加示例与文档 * 模块名称修正 * 修改匿名类 * 重构fel-starter * fel-spring-example注释完善 * fel-spring-example修改注释
1 parent d7bc7f2 commit 36985aa

File tree

42 files changed

+2875
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2875
-3
lines changed

.github/workflows/pr-title-check.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: PR Title Check
22

33
on:
4-
pull_request:
4+
pull_request_target:
55
types: [opened, edited, synchronize]
66

77
permissions:
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<parent>
7+
<groupId>org.fitframework.example</groupId>
8+
<artifactId>fel-spring-example-parent</artifactId>
9+
<version>1.0.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>chat-model-spring-example</artifactId>
13+
14+
<dependencies>
15+
<!-- FEL Spring Boot Starter -->
16+
<dependency>
17+
<groupId>org.fitframework.fel</groupId>
18+
<artifactId>fel-spring-boot-starter</artifactId>
19+
<version>${fel.version}</version>
20+
</dependency>
21+
22+
<!-- Spring Boot Web -->
23+
<dependency>
24+
<groupId>org.springframework.boot</groupId>
25+
<artifactId>spring-boot-starter-web</artifactId>
26+
</dependency>
27+
28+
<!-- WebFlux:流式响应需要 -->
29+
<dependency>
30+
<groupId>org.springframework.boot</groupId>
31+
<artifactId>spring-boot-starter-webflux</artifactId>
32+
</dependency>
33+
</dependencies>
34+
35+
<build>
36+
<plugins>
37+
<plugin>
38+
<groupId>org.springframework.boot</groupId>
39+
<artifactId>spring-boot-maven-plugin</artifactId>
40+
</plugin>
41+
</plugins>
42+
</build>
43+
</project>
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2026 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.example.ai.chat.model;
8+
9+
import modelengine.fel.core.chat.ChatMessage;
10+
import modelengine.fel.core.chat.ChatModel;
11+
import modelengine.fel.core.chat.ChatOption;
12+
import modelengine.fel.core.chat.support.ChatMessages;
13+
import modelengine.fel.core.chat.support.HumanMessage;
14+
import modelengine.fitframework.flowable.Choir;
15+
import reactor.adapter.JdkFlowAdapter;
16+
import reactor.core.publisher.Flux;
17+
18+
import org.springframework.beans.factory.annotation.Value;
19+
import org.springframework.web.bind.annotation.GetMapping;
20+
import org.springframework.web.bind.annotation.RequestMapping;
21+
import org.springframework.web.bind.annotation.RequestParam;
22+
import org.springframework.web.bind.annotation.RestController;
23+
24+
import java.util.Map;
25+
26+
/**
27+
* 聊天模型样例控制器(Spring Boot 版本)。
28+
*
29+
* @author 黄可欣
30+
* @since 2026-01-20
31+
*/
32+
@RestController
33+
@RequestMapping("/ai/example")
34+
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
35+
public class ChatModelExampleController {
36+
private final ChatModel chatModel;
37+
@Value("${example.model}")
38+
private String modelName;
39+
40+
public ChatModelExampleController(ChatModel chatModel) {
41+
this.chatModel = chatModel;
42+
}
43+
44+
/**
45+
* 聊天接口。
46+
*
47+
* @param query 表示用户输入查询的 {@link String}。
48+
* @return 表示聊天模型生成的回复的 {@link Map}{@code <}{@link String}{@code , }{@link Object}{@code >}。
49+
*/
50+
@GetMapping("/chat")
51+
public Map<String, Object> chat(@RequestParam("query") String query) {
52+
ChatOption option = ChatOption.custom().model(this.modelName).stream(false).build();
53+
ChatMessage aiMessage =
54+
this.chatModel.generate(ChatMessages.from(new HumanMessage(query)), option).first().block().get();
55+
return Map.of("content", aiMessage.text(), "toolCalls", aiMessage.toolCalls());
56+
}
57+
58+
/**
59+
* 流式聊天接口。
60+
*
61+
* @param query 表示用户输入查询的 {@link String}。
62+
* @return 表示聊天模型生成的流式回复的 {@link Flux}{@code <}{@link Map}{@code <}{@link String}{@code , }{@link Object}{@code >>}。
63+
*/
64+
@GetMapping(value = "/chat-stream", produces = "text/event-stream;charset=UTF-8")
65+
public Flux<Map<String, Object>> chatStream(@RequestParam("query") String query) {
66+
ChatOption option = ChatOption.custom().model(this.modelName).stream(true).build();
67+
Choir<ChatMessage> choir = this.chatModel.generate(ChatMessages.from(new HumanMessage(query)), option);
68+
return JdkFlowAdapter.flowPublisherToFlux(choir.map(chatMessage -> Map.of("content", chatMessage.text())));
69+
}
70+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2026 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.example.ai.chat.model;
8+
9+
import org.springframework.boot.SpringApplication;
10+
import org.springframework.boot.autoconfigure.SpringBootApplication;
11+
12+
/**
13+
* 启动程序(Spring Boot 版本)。
14+
*
15+
* @author 黄可欣
16+
* @since 2026-01-20
17+
*/
18+
@SpringBootApplication
19+
public class DemoApplication {
20+
public static void main(String[] args) {
21+
SpringApplication.run(DemoApplication.class, args);
22+
}
23+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
spring:
2+
application:
3+
name: chat-model-example
4+
5+
fel:
6+
openai:
7+
api-base:'${api-base}'
8+
api-key:'${your-api-key}'
9+
example:
10+
model:'${model-name}'
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<parent>
7+
<groupId>org.fitframework.example</groupId>
8+
<artifactId>fel-spring-example-parent</artifactId>
9+
<version>1.0.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>chat-template-spring-example</artifactId>
13+
14+
<dependencies>
15+
<!-- FEL Spring Boot Starter -->
16+
<dependency>
17+
<groupId>org.fitframework.fel</groupId>
18+
<artifactId>fel-spring-boot-starter</artifactId>
19+
<version>${fel.version}</version>
20+
</dependency>
21+
22+
<!-- Spring Boot Web -->
23+
<dependency>
24+
<groupId>org.springframework.boot</groupId>
25+
<artifactId>spring-boot-starter-web</artifactId>
26+
</dependency>
27+
</dependencies>
28+
29+
<build>
30+
<plugins>
31+
<plugin>
32+
<groupId>org.springframework.boot</groupId>
33+
<artifactId>spring-boot-maven-plugin</artifactId>
34+
</plugin>
35+
</plugins>
36+
</build>
37+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2026 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.example.ai.chat.template;
8+
9+
import modelengine.fel.core.chat.ChatMessage;
10+
import modelengine.fel.core.chat.ChatModel;
11+
import modelengine.fel.core.chat.ChatOption;
12+
import modelengine.fel.core.chat.support.ChatMessages;
13+
import modelengine.fel.core.template.MessageTemplate;
14+
import modelengine.fel.core.template.support.HumanMessageTemplate;
15+
import modelengine.fel.core.util.Tip;
16+
17+
import org.springframework.beans.factory.annotation.Value;
18+
import org.springframework.web.bind.annotation.GetMapping;
19+
import org.springframework.web.bind.annotation.RequestMapping;
20+
import org.springframework.web.bind.annotation.RequestParam;
21+
import org.springframework.web.bind.annotation.RestController;
22+
23+
import java.util.Map;
24+
25+
/**
26+
* 聊天模板样例控制器(Spring Boot 版本)。
27+
*
28+
* @author 黄可欣
29+
* @since 2026-01-20
30+
*/
31+
@RestController
32+
@RequestMapping("/ai/example")
33+
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
34+
public class ChatTemplateExampleController {
35+
private final ChatModel chatModel;
36+
private final MessageTemplate template;
37+
@Value("${example.model}")
38+
private String modelName;
39+
40+
public ChatTemplateExampleController(ChatModel chatModel) {
41+
this.chatModel = chatModel;
42+
this.template = new HumanMessageTemplate("给我讲个关于{{adjective}}的{{content}}。");
43+
}
44+
45+
/**
46+
* 聊天接口。
47+
*
48+
* @param adjective 表示主题的 {@link String}。
49+
* @param content 表示内容的 {@link String}。
50+
* @return 表示聊天模型生成的回复的 {@link Map}{@code <}{@link String}{@code , }{@link Object}{@code >}。
51+
*/
52+
@GetMapping("/chat")
53+
public Map<String, Object> chat(@RequestParam("adjective") String adjective,
54+
@RequestParam("content") String content) {
55+
ChatOption option = ChatOption.custom().model(this.modelName).stream(false).build();
56+
ChatMessage aiMessage =
57+
this.chatModel.generate(ChatMessages.from(this.template.render(Tip.from("adjective", adjective)
58+
.add("content", content)
59+
.freeze())), option).first().block().get();
60+
return Map.of("content", aiMessage.text(), "toolCalls", aiMessage.toolCalls());
61+
}
62+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2026 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.example.ai.chat.template;
8+
9+
import modelengine.fitframework.starter.spring.annotation.EnableFitProxy;
10+
import org.springframework.boot.SpringApplication;
11+
import org.springframework.boot.autoconfigure.SpringBootApplication;
12+
13+
/**
14+
* 启动程序(Spring Boot 版本)。
15+
*
16+
* @author 黄可欣
17+
* @since 2026-01-20
18+
*/
19+
@SpringBootApplication
20+
public class DemoApplication {
21+
public static void main(String[] args) {
22+
SpringApplication.run(DemoApplication.class, args);
23+
}
24+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
spring:
2+
application:
3+
name: chat-template-example
4+
fel:
5+
openai:
6+
api-base:'${api-base}'
7+
api-key:'${your-api-key}'
8+
example:
9+
model:'${model-name}'
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<parent>
7+
<groupId>org.fitframework.example</groupId>
8+
<artifactId>fel-spring-example-parent</artifactId>
9+
<version>1.0.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>chat-memory-spring-example</artifactId>
13+
14+
<dependencies>
15+
<!-- FEL Spring Boot Starter -->
16+
<dependency>
17+
<groupId>org.fitframework.fel</groupId>
18+
<artifactId>fel-spring-boot-starter</artifactId>
19+
<version>${fel.version}</version>
20+
</dependency>
21+
22+
<!-- Spring Boot Web -->
23+
<dependency>
24+
<groupId>org.springframework.boot</groupId>
25+
<artifactId>spring-boot-starter-web</artifactId>
26+
</dependency>
27+
</dependencies>
28+
29+
<build>
30+
<plugins>
31+
<plugin>
32+
<groupId>org.springframework.boot</groupId>
33+
<artifactId>spring-boot-maven-plugin</artifactId>
34+
</plugin>
35+
</plugins>
36+
</build>
37+
</project>

0 commit comments

Comments
 (0)