657 lines
12 KiB
Markdown
657 lines
12 KiB
Markdown
# API 参考文档
|
|
|
|
## 📚 模块索引
|
|
|
|
- [AgentTemplate API](#agenttemplate-api)
|
|
- [RagTemplate API](#ragtemplate-api)
|
|
- [GraphTemplate API](#graphtemplate-api)
|
|
- [配置项说明](#配置项说明)
|
|
|
|
---
|
|
|
|
## AgentTemplate API
|
|
|
|
### 类说明
|
|
|
|
`com.ccb.fintec.agent.template.AgentTemplate`
|
|
|
|
封装 Spring AI ChatClient 的常用调用模式,提供简洁的对话能力。
|
|
|
|
### 构造方法
|
|
|
|
```java
|
|
public AgentTemplate(ChatClient chatClient)
|
|
```
|
|
|
|
**参数**:
|
|
- `chatClient`: Spring AI 聊天客户端(由自动配置提供)
|
|
|
|
---
|
|
|
|
### 方法列表
|
|
|
|
#### 1. ask(String question)
|
|
|
|
简单问答
|
|
|
|
**签名**:
|
|
```java
|
|
public String ask(String question)
|
|
```
|
|
|
|
**参数**:
|
|
- `question`: 用户问题
|
|
|
|
**返回**: AI 的回答
|
|
|
|
**示例**:
|
|
```java
|
|
String answer = agentTemplate.ask("什么是Spring AI?");
|
|
```
|
|
|
|
---
|
|
|
|
#### 2. ask(String systemPrompt, String question)
|
|
|
|
带系统提示的问答
|
|
|
|
**签名**:
|
|
```java
|
|
public String ask(String systemPrompt, String question)
|
|
```
|
|
|
|
**参数**:
|
|
- `systemPrompt`: 系统提示词,定义 AI 角色和行为
|
|
- `question`: 用户问题
|
|
|
|
**返回**: AI 的回答
|
|
|
|
**示例**:
|
|
```java
|
|
String answer = agentTemplate.ask(
|
|
"你是一位专业的Java工程师",
|
|
"如何优化Stream性能?"
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
#### 3. askWithTools(String question, Object... toolObjects)
|
|
|
|
带工具调用的问答
|
|
|
|
**签名**:
|
|
```java
|
|
public String askWithTools(String question, Object... toolObjects)
|
|
```
|
|
|
|
**参数**:
|
|
- `question`: 用户问题
|
|
- `toolObjects`: 包含 `@Tool` 注解的对象
|
|
|
|
**返回**: AI 的回答(可能包含工具调用结果)
|
|
|
|
**示例**:
|
|
```java
|
|
@Service
|
|
public class WeatherService {
|
|
@Tool(description = "查询天气")
|
|
public String getWeather(String city) {
|
|
return weatherApi.query(city);
|
|
}
|
|
}
|
|
|
|
// 使用
|
|
String answer = agentTemplate.askWithTools(
|
|
"北京今天天气怎么样?",
|
|
new WeatherService()
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
#### 4. askForObject(String question, Class<T> responseType)
|
|
|
|
结构化输出
|
|
|
|
**签名**:
|
|
```java
|
|
public <T> T askForObject(String question, Class<T> responseType)
|
|
```
|
|
|
|
**参数**:
|
|
- `question`: 用户问题
|
|
- `responseType`: 期望的返回类型
|
|
|
|
**返回**: 解析后的 Java 对象
|
|
|
|
**示例**:
|
|
```java
|
|
@Data
|
|
public class PersonInfo {
|
|
private String name;
|
|
private Integer age;
|
|
private String email;
|
|
}
|
|
|
|
PersonInfo info = agentTemplate.askForObject(
|
|
"从以下文本提取个人信息: 我叫张三,今年25岁,邮箱zhangsan@example.com",
|
|
PersonInfo.class
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
#### 5. stream(String question)
|
|
|
|
流式输出
|
|
|
|
**签名**:
|
|
```java
|
|
public Flux<String> stream(String question)
|
|
```
|
|
|
|
**参数**:
|
|
- `question`: 用户问题
|
|
|
|
**返回**: 响应式流,逐块返回 AI 回答
|
|
|
|
**示例**:
|
|
```java
|
|
@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
|
public Flux<ServerSentEvent<String>> streamChat(String message) {
|
|
return agentTemplate.stream(message)
|
|
.map(chunk -> ServerSentEvent.builder(chunk).build());
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### 6. streamWithMemory(String conversationId, String question)
|
|
|
|
带记忆的流式输出
|
|
|
|
**签名**:
|
|
```java
|
|
public Flux<String> streamWithMemory(String conversationId, String question)
|
|
```
|
|
|
|
**参数**:
|
|
- `conversationId`: 会话ID
|
|
- `question`: 用户问题
|
|
|
|
**返回**: 响应式流
|
|
|
|
**示例**:
|
|
```java
|
|
Flux<String> response = agentTemplate.streamWithMemory(
|
|
"user_123_session_456",
|
|
"我刚才问了什么?"
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
#### 7. askWithMemory(String conversationId, String question)
|
|
|
|
带记忆的多轮对话
|
|
|
|
**签名**:
|
|
```java
|
|
public String askWithMemory(String conversationId, String question)
|
|
```
|
|
|
|
**参数**:
|
|
- `conversationId`: 会话ID
|
|
- `question`: 用户问题
|
|
|
|
**返回**: AI 的回答
|
|
|
|
**示例**:
|
|
```java
|
|
// 第一轮
|
|
String answer1 = agentTemplate.askWithMemory("session_001", "我叫张三");
|
|
|
|
// 第二轮(AI 记得用户的名字)
|
|
String answer2 = agentTemplate.askWithMemory("session_001", "我叫什么名字?");
|
|
// 回答: "你叫张三"
|
|
```
|
|
|
|
---
|
|
|
|
## RagTemplate API
|
|
|
|
### 类说明
|
|
|
|
`com.ccb.fintec.rag.template.RagTemplate`
|
|
|
|
封装检索增强生成(RAG)能力,基于向量数据库实现知识库问答。
|
|
|
|
### 构造方法
|
|
|
|
```java
|
|
public RagTemplate(ChatClient chatClient, VectorStore vectorStore)
|
|
```
|
|
|
|
**参数**:
|
|
- `chatClient`: Spring AI 聊天客户端
|
|
- `vectorStore`: 向量数据库
|
|
|
|
---
|
|
|
|
### 方法列表
|
|
|
|
#### 1. ask(String question)
|
|
|
|
基于知识库问答
|
|
|
|
**签名**:
|
|
```java
|
|
public String ask(String question)
|
|
```
|
|
|
|
**参数**:
|
|
- `question`: 用户问题
|
|
|
|
**返回**: 基于知识库的回答
|
|
|
|
**示例**:
|
|
```java
|
|
String answer = ragTemplate.ask("公司的报销流程是什么?");
|
|
```
|
|
|
|
---
|
|
|
|
#### 2. stream(String question)
|
|
|
|
基于知识库的流式问答
|
|
|
|
**签名**:
|
|
```java
|
|
public Flux<String> stream(String question)
|
|
```
|
|
|
|
**参数**:
|
|
- `question`: 用户问题
|
|
|
|
**返回**: 响应式流
|
|
|
|
**示例**:
|
|
```java
|
|
@GetMapping(value = "/rag/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
|
public Flux<ServerSentEvent<String>> streamRag(String question) {
|
|
return ragTemplate.stream(question)
|
|
.map(chunk -> ServerSentEvent.builder(chunk).build());
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### 3. askWithMemory(String conversationId, String question)
|
|
|
|
带记忆的 RAG 问答
|
|
|
|
**签名**:
|
|
```java
|
|
public String askWithMemory(String conversationId, String question)
|
|
```
|
|
|
|
**参数**:
|
|
- `conversationId`: 会话ID
|
|
- `question`: 用户问题
|
|
|
|
**返回**: 基于知识库的回答
|
|
|
|
**示例**:
|
|
```java
|
|
String answer = ragTemplate.askWithMemory("session_001",
|
|
"结合我之前的问题,再详细解释一下");
|
|
```
|
|
|
|
---
|
|
|
|
#### 4. askWithConfig(String question, double similarityThreshold, int topK)
|
|
|
|
自定义检索参数的 RAG 问答
|
|
|
|
**签名**:
|
|
```java
|
|
public String askWithConfig(String question, double similarityThreshold, int topK)
|
|
```
|
|
|
|
**参数**:
|
|
- `question`: 用户问题
|
|
- `similarityThreshold`: 相似度阈值(0.0-1.0),越高越严格
|
|
- `topK`: 返回最相关的 K 个文档片段
|
|
|
|
**返回**: 基于知识库的回答
|
|
|
|
**示例**:
|
|
```java
|
|
// 高精度模式: 只返回非常相关的内容
|
|
String answer = ragTemplate.askWithConfig(question, 0.9, 3);
|
|
|
|
// 召回模式: 返回更多相关内容
|
|
String answer = ragTemplate.askWithConfig(question, 0.6, 10);
|
|
```
|
|
|
|
---
|
|
|
|
## GraphTemplate API
|
|
|
|
### 类说明
|
|
|
|
`com.ccb.fintec.graph.template.GraphTemplate`
|
|
|
|
提供工作流编排能力,支持顺序、并行、路由、循环等模式。
|
|
|
|
### 静态方法
|
|
|
|
#### 1. sequential(Node<?, ?>... nodes)
|
|
|
|
创建顺序工作流
|
|
|
|
**签名**:
|
|
```java
|
|
public static SequentialWorkflow sequential(Node<?, ?>... nodes)
|
|
```
|
|
|
|
**参数**:
|
|
- `nodes`: 按顺序执行的节点数组
|
|
|
|
**返回**: 顺序工作流实例
|
|
|
|
**示例**:
|
|
```java
|
|
SequentialWorkflow workflow = GraphTemplate.sequential(
|
|
GraphTemplate.node("清洗", text -> text.trim()),
|
|
GraphTemplate.node("翻译", text -> translate(text)),
|
|
GraphTemplate.node("总结", text -> summarize(text))
|
|
);
|
|
|
|
String result = workflow.execute(input);
|
|
```
|
|
|
|
---
|
|
|
|
#### 2. parallel(Node<?, ?>... nodes)
|
|
|
|
创建并行工作流
|
|
|
|
**签名**:
|
|
```java
|
|
public static ParallelWorkflow parallel(Node<?, ?>... nodes)
|
|
```
|
|
|
|
**参数**:
|
|
- `nodes`: 并行执行的节点数组
|
|
|
|
**返回**: 并行工作流实例
|
|
|
|
**示例**:
|
|
```java
|
|
ParallelWorkflow workflow = GraphTemplate.parallel(
|
|
GraphTemplate.node("情感分析", text -> sentiment(text)),
|
|
GraphTemplate.node("关键词提取", text -> keywords(text)),
|
|
GraphTemplate.node("分类", text -> classify(text))
|
|
);
|
|
|
|
List<String> results = workflow.execute(input);
|
|
```
|
|
|
|
---
|
|
|
|
#### 3. routing()
|
|
|
|
创建路由工作流构建器
|
|
|
|
**签名**:
|
|
```java
|
|
public static RoutingWorkflow routing()
|
|
```
|
|
|
|
**返回**: 路由工作流构建器
|
|
|
|
**示例**:
|
|
```java
|
|
RoutingWorkflow workflow = GraphTemplate.routing()
|
|
.addBranch("技术",
|
|
Condition.of(ctx -> ((String)ctx).contains("技术")),
|
|
GraphTemplate.node("技术回答", q -> techAnswer(q)))
|
|
.addBranch("业务",
|
|
Condition.of(ctx -> ((String)ctx).contains("业务")),
|
|
GraphTemplate.node("业务回答", q -> businessAnswer(q)))
|
|
.setDefault(GraphTemplate.node("通用回答", q -> generalAnswer(q)));
|
|
|
|
String result = workflow.execute(question);
|
|
```
|
|
|
|
---
|
|
|
|
#### 4. loop(Node<?, ?> node, Condition condition, int maxIterations)
|
|
|
|
创建循环工作流
|
|
|
|
**签名**:
|
|
```java
|
|
public static LoopWorkflow loop(Node<?, ?> node, Condition condition, int maxIterations)
|
|
```
|
|
|
|
**参数**:
|
|
- `node`: 要循环执行的节点
|
|
- `condition`: 继续循环的条件(返回 true 则继续)
|
|
- `maxIterations`: 最大迭代次数(防止死循环)
|
|
|
|
**返回**: 循环工作流实例
|
|
|
|
**示例**:
|
|
```java
|
|
LoopWorkflow workflow = GraphTemplate.loop(
|
|
GraphTemplate.node("优化", text -> optimize(text)),
|
|
Condition.of(result -> !isSatisfactory((String)result)),
|
|
5 // 最多迭代5次
|
|
);
|
|
|
|
String result = workflow.execute(initialText);
|
|
```
|
|
|
|
---
|
|
|
|
#### 5. node(String name, Function<I, O> function)
|
|
|
|
创建工作流节点
|
|
|
|
**签名**:
|
|
```java
|
|
public static <I, O> Node<I, O> node(String name, Function<I, O> function)
|
|
```
|
|
|
|
**参数**:
|
|
- `name`: 节点名称(用于调试和日志)
|
|
- `function`: 节点执行逻辑
|
|
|
|
**返回**: 节点实例
|
|
|
|
**示例**:
|
|
```java
|
|
Node<String, String> node = GraphTemplate.node(
|
|
"数据转换",
|
|
data -> data.toUpperCase()
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## 配置项说明
|
|
|
|
### 核心配置 (app.ai.*)
|
|
|
|
#### 安全防护 (app.ai.safety.*)
|
|
|
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
|--------|------|--------|------|
|
|
| `enabled` | Boolean | true | 是否启用安全防护 |
|
|
| `block-keywords` | List<String> | [] | 敏感词列表 |
|
|
|
|
**示例**:
|
|
```yaml
|
|
app:
|
|
ai:
|
|
safety:
|
|
enabled: true
|
|
block-keywords:
|
|
- 暴力
|
|
- 色情
|
|
- 赌博
|
|
```
|
|
|
|
**功能说明**:
|
|
- 双向检查:拦截请求和响应中的敏感内容
|
|
- 大小写不敏感:自动转小写匹配
|
|
- 发现敏感词时抛出 `AiException` 异常
|
|
|
|
---
|
|
|
|
#### 限流配置 (app.ai.rate-limit.*)
|
|
|
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
|--------|------|--------|------|
|
|
| `max-requests-per-minute` | Integer | 60 | 每分钟最大请求数 |
|
|
|
|
**示例**:
|
|
```yaml
|
|
app:
|
|
ai:
|
|
rate-limit:
|
|
max-requests-per-minute: 100
|
|
```
|
|
|
|
---
|
|
|
|
#### 重试策略 (app.ai.retry.*)
|
|
|
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
|--------|------|--------|------|
|
|
| `enabled` | Boolean | true | 是否启用重试 |
|
|
| `max-attempts` | Integer | 3 | 最大重试次数 |
|
|
| `backoff-ms` | Long | 1000 | 重试间隔(毫秒) |
|
|
|
|
**示例**:
|
|
```yaml
|
|
app:
|
|
ai:
|
|
retry:
|
|
enabled: true
|
|
max-attempts: 5
|
|
backoff-ms: 2000
|
|
```
|
|
|
|
**功能说明**:
|
|
- 自动处理网络波动、临时故障
|
|
- 记录重试日志,方便问题排查
|
|
- 支持固定退避时间
|
|
|
|
---
|
|
|
|
### Spring AI 配置 (spring.ai.*)
|
|
|
|
#### OpenAI 配置
|
|
|
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
|--------|------|--------|------|
|
|
| `spring.ai.openai.api-key` | String | - | API Key |
|
|
| `spring.ai.openai.base-url` | String | https://api.openai.com/v1 | API 地址 |
|
|
| `spring.ai.openai.chat.options.model` | String | gpt-3.5-turbo | 模型名称 |
|
|
| `spring.ai.openai.chat.options.temperature` | Double | 0.7 | 温度参数(0-1) |
|
|
| `spring.ai.openai.chat.options.max-tokens` | Integer | - | 最大输出 Token 数 |
|
|
|
|
**示例**:
|
|
```yaml
|
|
spring:
|
|
ai:
|
|
openai:
|
|
api-key: ${OPENAI_API_KEY}
|
|
base-url: https://api.openai.com/v1
|
|
chat:
|
|
options:
|
|
model: gpt-4-turbo
|
|
temperature: 0.8
|
|
max-tokens: 2048
|
|
```
|
|
|
|
---
|
|
|
|
#### Ollama 配置(本地模型)
|
|
|
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
|--------|------|--------|------|
|
|
| `spring.ai.ollama.base-url` | String | http://localhost:11434 | Ollama 地址 |
|
|
| `spring.ai.ollama.chat.options.model` | String | llama3 | 模型名称 |
|
|
|
|
**示例**:
|
|
```yaml
|
|
spring:
|
|
ai:
|
|
ollama:
|
|
base-url: http://localhost:11434
|
|
chat:
|
|
options:
|
|
model: qwen:7b
|
|
```
|
|
|
|
---
|
|
|
|
#### 通义千问配置
|
|
|
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
|--------|------|--------|------|
|
|
| `spring.ai.dashscope.api-key` | String | - | API Key |
|
|
| `spring.ai.dashscope.chat.options.model` | String | qwen-plus | 模型名称 |
|
|
|
|
**示例**:
|
|
```yaml
|
|
spring:
|
|
ai:
|
|
dashscope:
|
|
api-key: ${DASHSCOPE_API_KEY}
|
|
chat:
|
|
options:
|
|
model: qwen-max
|
|
```
|
|
|
|
---
|
|
|
|
## 数据类型参考
|
|
|
|
### Node 接口
|
|
|
|
```java
|
|
@FunctionalInterface
|
|
public interface Node<I, O> {
|
|
O execute(I input);
|
|
|
|
default String getName() {
|
|
return this.getClass().getSimpleName();
|
|
}
|
|
|
|
static <I, O> Node<I, O> of(String name, Function<I, O> function) {
|
|
return new SimpleNode<>(name, function);
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Condition 接口
|
|
|
|
```java
|
|
@FunctionalInterface
|
|
public interface Condition {
|
|
boolean evaluate(Object context);
|
|
|
|
static Condition of(Predicate<Object> predicate) {
|
|
return predicate::test;
|
|
}
|
|
}
|
|
```
|