AI配置增加字段适配处理

This commit is contained in:
2025-12-23 16:51:53 +08:00
parent 2d033e6a3e
commit 7f89fd17d3
22 changed files with 2951 additions and 4 deletions
+294
View File
@@ -0,0 +1,294 @@
# Design Document
## Overview
本设计文档描述了Coze AI通用接口调用服务的架构设计,以及爽文剧本AI生成功能的实现方案。核心目标是重构AiChatServiceImpl,提供一个通用的、可配置的AI接口调用方法,支持通过config_key获取配置并调用Coze工作流API。
## Architecture
### 系统架构图
```mermaid
graph TB
subgraph "Controller Layer"
EC[EpicScriptController]
end
subgraph "Service Layer"
ESS[EpicScriptServiceImpl]
ACS[AiChatServiceImpl]
AICS[AiConfigServiceImpl]
end
subgraph "Data Layer"
ACM[AiConfigMapper]
ESM[EpicScriptMapper]
end
subgraph "External"
COZE[Coze API]
end
EC --> ESS
ESS --> ACS
ACS --> AICS
AICS --> ACM
ESS --> ESM
ACS --> COZE
```
### 调用流程图
```mermaid
sequenceDiagram
participant C as Controller
participant ESS as EpicScriptService
participant ACS as AiChatService
participant AICS as AiConfigService
participant DB as Database
participant COZE as Coze API
C->>ESS: createScript(request)
ESS->>ESS: assembleInput(request)
ESS->>ACS: callWorkflowByConfigKey(configKey, input, userId)
ACS->>AICS: getByConfigKey(configKey)
AICS->>DB: SELECT * FROM t_ai_config WHERE config_key = ?
DB-->>AICS: AiConfig
AICS-->>ACS: AiConfig
ACS->>ACS: buildWorkflowRequest(config, input, userId)
ACS->>COZE: POST /v1/workflow/stream_run
COZE-->>ACS: SSE Stream Response
ACS->>ACS: parseStreamResponse(response)
ACS-->>ESS: AI Generated Content
ESS->>ESS: parseAndSaveScript(content)
ESS->>DB: INSERT INTO t_epic_script
ESS-->>C: EpicScriptResponse
```
## Components and Interfaces
### 1. AiChatService 接口扩展
```java
/**
* AI聊天服务接口 - 新增通用工作流调用方法
*/
public interface AiChatService {
// ... 现有方法 ...
/**
* 通过配置键调用Coze工作流API
*
* @param configKey AI配置键(如:coze.course.life.generate
* @param input 输入参数,将作为parameters.input传递给工作流
* @param userId 用户ID
* @return AI生成的内容
*/
String callWorkflowByConfigKey(String configKey, String input, String userId);
/**
* 通过配置键调用Coze工作流API(带自定义参数)
*
* @param configKey AI配置键
* @param parameters 自定义参数Map,将合并到请求的parameters中
* @param userId 用户ID
* @return AI生成的内容
*/
String callWorkflowByConfigKey(String configKey, Map<String, Object> parameters, String userId);
}
```
### 2. AiConfigService 接口扩展
```java
/**
* AI配置服务接口 - 新增按配置键获取方法
*/
public interface AiConfigService {
// ... 现有方法 ...
/**
* 根据配置键获取AI配置
*
* @param configKey 配置键
* @return AI配置,如果不存在或已禁用则返回null
*/
AiConfig getByConfigKey(String configKey);
}
```
### 3. EpicScriptService 接口(无变化)
现有接口保持不变,实现层调用新的AI服务方法。
## Data Models
### Coze工作流请求格式
```json
{
"workflow_id": "7586262962160762926",
"user_id": "user_123",
"stream": true,
"parameters": {
"input": "用户填写的信息组装后的字符串",
"user_id": "user_123"
}
}
```
### Coze工作流响应格式(SSE
```
id: 0
event: Message
data: {"node_title":"End","node_execute_uuid":"","usage":{"token_count":1571,"output_count":812,"input_count":759},"node_is_finish":true,"node_seq_id":"0","content":"{\"output\":\"AI生成的内容...\"}","content_type":"text","node_type":"End","node_id":"900001"}
id: 1
event: Done
data: {"node_execute_uuid":"","debug_url":"..."}
```
### 用户输入组装格式
```
剧本标题:{title}
主题/渴望:{theme}
风格:{style}
篇幅:{length}
序幕(低谷回响):{plotIntro}
转折(契机出现):{plotTurning}
高潮(命运抉择):{plotClimax}
结局(新的开始):{plotEnding}
```
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
### Property 1: Request Format Correctness (请求格式正确性)
*For any* valid AiConfig and input parameters, the generated Coze workflow request SHALL contain:
- workflow_id from the AiConfig
- user_id from the call parameters
- stream set to true
- parameters.input containing the input string
- Authorization header with "Bearer {api_token}"
- Content-Type header set to "application/json"
**Validates: Requirements 2.1, 2.2, 2.3, 2.4, 2.5, 2.6**
### Property 2: Stream Response Parsing (流式响应解析)
*For any* valid Coze SSE stream response containing an "event: Message" line followed by a "data:" line with JSON containing "node_type": "End" and a "content" field with nested JSON containing "output", the parser SHALL extract and return the output value.
**Validates: Requirements 3.1, 3.2, 3.3**
### Property 3: Input Assembly Completeness (输入组装完整性)
*For any* EpicScriptCreateRequest with non-null field values, the assembled input string SHALL contain all provided field values (title, theme, style, length, plotIntro, plotTurning, plotClimax, plotEnding).
**Validates: Requirements 4.2**
### Property 4: Configuration Application (配置应用正确性)
*For any* AiConfig retrieved by config_key:
- If is_enabled = 0, the system SHALL reject the config and throw an exception
- The api_base_url, api_token, and workflow_id SHALL be used in the request construction
- The custom_params SHALL be merged with runtime parameters
**Validates: Requirements 1.3, 5.2, 5.3**
### Property 5: Error Message Quality (错误消息质量)
*For any* error that occurs during AI API calls:
- The error message SHALL be meaningful and descriptive
- The error message SHALL NOT contain sensitive information such as API tokens
- The error message SHALL include relevant context (config_key, status code if applicable)
**Validates: Requirements 6.4, 6.5**
## Error Handling
### 错误类型和处理策略
| 错误类型 | 处理策略 | 返回值 |
|---------|---------|--------|
| 配置不存在 | 抛出RuntimeException | "未找到AI配置: {configKey}" |
| 配置已禁用 | 抛出RuntimeException | "AI配置已禁用: {configKey}" |
| API调用超时 | 重试(根据配置) | 重试失败后返回错误消息 |
| HTTP非200响应 | 记录日志,返回错误 | "AI服务调用失败: {statusCode}" |
| 流式解析失败 | 记录原始数据,返回错误 | "AI响应解析失败" |
| JSON解析失败 | 返回原始内容 | 原始content字符串 |
### 日志记录规范
```java
// 请求日志
log.info("调用Coze工作流: configKey={}, workflowId={}, userId={}", configKey, workflowId, userId);
// 响应日志
log.info("Coze工作流响应: configKey={}, contentLength={}", configKey, content.length());
// 错误日志
log.error("Coze工作流调用失败: configKey={}, statusCode={}, error={}", configKey, statusCode, errorMsg);
```
## Testing Strategy
### 单元测试
1. **AiConfigService测试**
- 测试getByConfigKey返回正确配置
- 测试配置不存在时返回null
- 测试配置禁用时返回null
2. **请求构建测试**
- 测试buildWorkflowRequest生成正确的请求格式
- 测试参数合并逻辑
3. **响应解析测试**
- 测试parseStreamResponse正确解析SSE格式
- 测试extractOutputFromContent正确提取output字段
4. **输入组装测试**
- 测试assembleInput正确组装用户输入
### 属性测试
使用JUnit 5进行属性测试,每个属性测试至少运行100次迭代:
1. **Property 1: Request Format Correctness**
- 生成随机的AiConfig和输入参数
- 验证生成的请求包含所有必需字段
- 验证请求头正确设置
- **Feature: coze-ai-integration, Property 1: Request Format Correctness**
2. **Property 2: Stream Response Parsing**
- 生成各种有效的SSE格式响应
- 验证正确提取output内容
- 测试边界情况(空content、嵌套JSON等)
- **Feature: coze-ai-integration, Property 2: Stream Response Parsing**
3. **Property 3: Input Assembly Completeness**
- 生成随机的EpicScriptCreateRequest
- 验证所有非空字段都出现在组装结果中
- **Feature: coze-ai-integration, Property 3: Input Assembly Completeness**
4. **Property 4: Configuration Application**
- 生成随机的AiConfig
- 验证配置值正确应用到请求
- 验证禁用配置被拒绝
- **Feature: coze-ai-integration, Property 4: Configuration Application**
5. **Property 5: Error Message Quality**
- 模拟各种错误场景
- 验证错误消息有意义且不包含敏感信息
- **Feature: coze-ai-integration, Property 5: Error Message Quality**
### 集成测试
1. 端到端测试:从Controller到Coze API的完整调用流程
2. 配置变更测试:验证配置更新后立即生效
@@ -0,0 +1,91 @@
# Requirements Document
## Introduction
本文档定义了优化爽文剧本创建接口(EpicScriptServiceImpl#createScript)的需求,通过调用Coze AI API来生成剧本内容。同时重构AiChatServiceImpl中的AI调用封装,使其成为通用的AI接口调用服务,支持根据配置信息调用不同的AI接口。
## Glossary
- **Coze_API**: 扣子AI平台提供的工作流流式调用接口
- **AiConfig**: AI配置实体,存储在t_ai_config表中,包含API地址、Token、工作流ID等配置信息
- **config_key**: AI配置的唯一标识键,用于获取特定场景的配置
- **workflow_id**: Coze工作流ID,用于指定调用哪个AI工作流
- **Stream_Response**: 流式响应,Coze API以SSEServer-Sent Events)格式返回数据
- **EpicScript**: 爽文剧本实体,存储用户创建的剧本信息
- **input_parameter**: 传递给Coze工作流的输入参数,包含用户填写的信息
## Requirements
### Requirement 1: 通用AI接口调用服务
**User Story:** As a developer, I want to have a generic AI API calling service, so that I can easily call different AI configurations without duplicating code.
#### Acceptance Criteria
1. THE AiChatService SHALL provide a generic method to call Coze workflow API by config_key
2. WHEN a config_key is provided, THE AiChatService SHALL retrieve the corresponding AiConfig from database
3. WHEN the AiConfig is retrieved, THE AiChatService SHALL construct the request using api_base_url, api_token, and workflow_id from the config
4. THE AiChatService SHALL support passing custom input parameters to the workflow
5. THE AiChatService SHALL handle stream response by default and extract the output content from the response
6. IF the AiConfig is not found or disabled, THEN THE AiChatService SHALL throw an appropriate exception with clear error message
### Requirement 2: Coze工作流请求构建
**User Story:** As a developer, I want the system to correctly build Coze workflow requests, so that the AI can process my input and return expected results.
#### Acceptance Criteria
1. WHEN building a Coze workflow request, THE System SHALL include workflow_id from AiConfig
2. WHEN building a Coze workflow request, THE System SHALL include user_id parameter
3. WHEN building a Coze workflow request, THE System SHALL set stream to true for streaming response
4. WHEN building a Coze workflow request, THE System SHALL include the input parameter in the parameters object
5. THE System SHALL set Authorization header with Bearer token from AiConfig.api_token
6. THE System SHALL set Content-Type header to application/json
### Requirement 3: 流式响应解析
**User Story:** As a developer, I want the system to correctly parse Coze streaming responses, so that I can get the AI-generated content.
#### Acceptance Criteria
1. WHEN receiving a stream response, THE System SHALL parse SSE format data (event: and data: lines)
2. WHEN the event is "Message" and node_type is "End", THE System SHALL extract the content field
3. WHEN the content contains JSON with output field, THE System SHALL extract the output value as the final result
4. WHEN the event is "Done", THE System SHALL complete the stream processing
5. IF parsing fails, THEN THE System SHALL log the error and return an appropriate error message
### Requirement 4: 爽文剧本AI生成
**User Story:** As a user, I want to create epic scripts using AI, so that I can get professionally generated story content based on my input.
#### Acceptance Criteria
1. WHEN creating an epic script, THE EpicScriptService SHALL call Coze AI using config_key "coze.course.life.generate"
2. THE EpicScriptService SHALL assemble user input (title, theme, style, length, plotIntro, plotTurning, plotClimax, plotEnding) into a formatted input string
3. WHEN the AI returns the generated content, THE EpicScriptService SHALL parse and store the result in the EpicScript entity
4. THE EpicScriptService SHALL store the AI-generated content in appropriate fields (plotJson or dedicated content field)
5. IF the AI call fails, THEN THE EpicScriptService SHALL log the error and return null or throw an exception
### Requirement 5: 配置管理
**User Story:** As an administrator, I want to manage AI configurations in the database, so that I can easily update API settings without code changes.
#### Acceptance Criteria
1. THE System SHALL retrieve AiConfig by config_key using AiConfigService
2. THE System SHALL validate that the AiConfig is enabled (is_enabled = 1) before use
3. THE System SHALL use custom_params from AiConfig to merge with runtime parameters
4. THE System SHALL respect timeout_ms setting from AiConfig for API calls
5. THE System SHALL support retry logic based on retry_count and retry_delay_ms from AiConfig
### Requirement 6: 错误处理
**User Story:** As a developer, I want proper error handling for AI API calls, so that I can diagnose and fix issues quickly.
#### Acceptance Criteria
1. IF the API returns non-200 status code, THEN THE System SHALL log the error with status code and response body
2. IF the stream parsing fails, THEN THE System SHALL log the raw stream data for debugging
3. IF the network request times out, THEN THE System SHALL retry based on configuration
4. THE System SHALL provide meaningful error messages to the caller
5. THE System SHALL not expose sensitive information (like API tokens) in error messages
+107
View File
@@ -0,0 +1,107 @@
# Implementation Plan: Coze AI Integration
## Overview
本实现计划将重构AiChatServiceImpl,添加通用的Coze工作流调用方法,并优化EpicScriptServiceImpl#createScript接口以调用Coze AI生成剧本内容。实现采用增量方式,每个任务都建立在前一个任务的基础上。
## Tasks
- [x] 1. 扩展AiConfigService接口和实现
- [x] 1.1 在AiConfigService接口中添加getByConfigKey方法
- 添加方法签名:`AiConfig getByConfigKey(String configKey)`
- 添加方法级注释说明功能和参数
- _Requirements: 5.1_
- [x] 1.2 在AiConfigServiceImpl中实现getByConfigKey方法
- 使用LambdaQueryWrapper查询config_key匹配且is_enabled=1的配置
- 返回查询结果,不存在则返回null
- _Requirements: 1.2, 5.1, 5.2_
- [x] 2. 扩展AiChatService接口
- [x] 2.1 在AiChatService接口中添加callWorkflowByConfigKey方法
- 添加方法签名:`String callWorkflowByConfigKey(String configKey, String input, String userId)`
- 添加重载方法:`String callWorkflowByConfigKey(String configKey, Map<String, Object> parameters, String userId)`
- 添加方法级注释说明功能、参数和返回值
- _Requirements: 1.1, 1.4_
- [x] 3. 实现通用工作流调用方法
- [x] 3.1 在AiChatServiceImpl中实现callWorkflowByConfigKey方法
- 调用aiConfigService.getByConfigKey获取配置
- 验证配置存在且启用,否则抛出异常
- 构建工作流请求(workflow_id, user_id, stream=true, parameters.input
- 设置请求头(Authorization, Content-Type
- _Requirements: 1.2, 1.3, 1.6, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6_
- [x] 3.2 实现流式响应处理方法
- 解析SSE格式响应(event:和data:行)
- 提取event为Message且node_type为End的content
- 从content的JSON中提取output字段
- 处理Done事件完成流处理
- _Requirements: 3.1, 3.2, 3.3, 3.4_
- [x] 3.3 实现错误处理逻辑
- 处理配置不存在/禁用的情况
- 处理API调用失败(非200状态码)
- 处理流式解析失败
- 确保错误消息不包含敏感信息
- _Requirements: 1.6, 3.5, 6.1, 6.2, 6.4, 6.5_
- [x] 3.4 编写Property 1属性测试:请求格式正确性
- **Property 1: Request Format Correctness**
- **Validates: Requirements 2.1, 2.2, 2.3, 2.4, 2.5, 2.6**
- [x] 3.5 编写Property 2属性测试:流式响应解析
- **Property 2: Stream Response Parsing**
- **Validates: Requirements 3.1, 3.2, 3.3**
- [x] 4. Checkpoint - 验证通用AI调用服务
- 确保所有测试通过,如有问题请询问用户
- [x] 5. 实现爽文剧本AI生成
- [x] 5.1 在EpicScriptServiceImpl中添加输入组装方法
- 创建assembleScriptInput方法
- 将EpicScriptCreateRequest的字段组装为格式化字符串
- 包含title, theme, style, length, plotIntro, plotTurning, plotClimax, plotEnding
- _Requirements: 4.2_
- [x] 5.2 修改createScript方法调用AI生成
- 调用assembleScriptInput组装输入
- 调用aiChatService.callWorkflowByConfigKey("coze.course.life.generate", input, userId)
- 解析AI返回的内容并存储到EpicScript实体
- 处理AI调用失败的情况
- _Requirements: 4.1, 4.3, 4.4, 4.5_
- [x] 5.3 编写Property 3属性测试:输入组装完整性
- **Property 3: Input Assembly Completeness**
- **Validates: Requirements 4.2**
- [x] 6. 实现配置参数合并
- [x] 6.1 实现custom_params合并逻辑
- 解析AiConfig.customParams JSON字符串
- 将custom_params与运行时参数合并
- 运行时参数优先级高于custom_params
- _Requirements: 5.3_
- [x] 6.2 实现超时和重试配置
- 应用AiConfig.timeoutMs设置
- 实现基于retry_count和retry_delay_ms的重试逻辑
- _Requirements: 5.4, 5.5, 6.3_
- [x] 6.3 编写Property 4属性测试:配置应用正确性
- **Property 4: Configuration Application**
- **Validates: Requirements 1.3, 5.2, 5.3**
- [x] 7. 完善错误处理和日志
- [x] 7.1 完善错误消息格式
- 确保错误消息包含config_key和状态码
- 确保不暴露API token等敏感信息
- 添加详细的日志记录
- _Requirements: 6.1, 6.2, 6.4, 6.5_
- [x] 7.2 编写Property 5属性测试:错误消息质量
- **Property 5: Error Message Quality**
- **Validates: Requirements 6.4, 6.5**
- [x] 8. Final Checkpoint - 确保所有测试通过
- 运行所有单元测试和属性测试
- 确保所有测试通过,如有问题请询问用户
## Notes
- All tasks are required for comprehensive implementation
- Each task references specific requirements for traceability
- Checkpoints ensure incremental validation
- Property tests validate universal correctness properties
- Unit tests validate specific examples and edge cases
- 实现语言:Java (Spring Boot)
- 测试框架:JUnit 5