Skip to content

AI 能力 ​

后端基于 Spring AI 接入 OpenAI 兼容协议的大模型,为代码生成、动态表单、审批流提供 AI 辅助。默认关闭,未配置密钥不影响应用启动。

功能一览 ​

功能接口说明
代码生成配置推断POST /api/v1/codegen/{tableName}/ai-config读取表结构,回填业务名与字段的中文描述、表单/查询类型、显示位置,未推断出的字段沿用默认值
表单规则生成POST /api/v1/forms/ai-generate需求描述转 form-create 规则数组,产出经结构校验后才返回
审批摘要POST /api/v1/workflow/tasks/{taskId}/ai-summary汇总表单数据与审批记录生成摘要,需 workflow.enabled=true

AI 未开启时调用返回业务异常「AI 功能未开启,请将 spring.ai.model.chat 置为 openai 并配置 spring.ai.openai.api-key」,不影响应用启动与其余接口。

开启方式 ​

spring.ai.model.chat 在 application-{profile}.yml 中默认为 none,改为 openai 并补齐模型配置:

yaml
spring:
  ai:
    model:
      chat: openai
    openai:
      base-url: https://api.deepseek.com # OpenAI 兼容服务地址,以服务商文档为准
      api-key: ${AI_API_KEY:}
      chat:
        options:
          model: deepseek-chat

application.yml 已将 embedding、image、moderation、audio 置为 none,仅对话模型参与自动装配,因此不配密钥也能正常启动。

核心组件 ​

组件位置职责
AiChatServicesupport/ai/AiChatService.java模型调用统一入口:chat 返回纯文本,chatEntity 映射为实体,chatJsonList 映射为 JSON 数组
PromptLoadersupport/ai/PromptLoader.java启动时载入 resources/prompts 下的提示词并缓存

chatEntity 由框架按实体结构生成 JSON Schema 并校验,结构不符时自动重试,无需手工解析 JSON;chatJsonList 的元素结构开放,产出后需业务侧校验。

提示词配置 ​

提示词一个功能一个文件,放在 src/main/resources/prompts 下:

text
prompts/
├── codegen/system.md      # 表结构 → 生成配置
├── form/system.md         # 需求 → form-create 规则
└── workflow/summary.md    # 审批摘要

PromptLoader 启动时全部载入,文件缺失或读取失败直接启动失败。文本中的占位符由 render 替换为变量值,替换后仍残留占位符则抛异常,避免残缺提示词发给模型:

java
// 提示词中的 {{formTypes}} 在此被替换为实际枚举清单
String systemPrompt = promptLoader.render("codegen/system.md",
        Map.of("formTypes", "INPUT(输入框)|SELECT(下拉框)"));

不含变量的提示词直接取原文:promptLoader.get("form/system.md")。

codegen 提示词中的表单类型与查询类型清单由 FormTypeEnum、QueryTypeEnum 运行时拼装注入,新增枚举值无需改动提示词。

新增 AI 模块 ​

1. 编写提示词 ​

新建 src/main/resources/prompts/order/summary.md:

text
你是订单助手,根据订单数据生成一句话摘要。
要求:
- 50 字以内
- 包含订单号、金额、状态

2. 编写 Service ​

java
@Service
@RequiredArgsConstructor
public class OrderAiServiceImpl implements OrderAiService {

    /** 系统提示词名称,对应 resources/prompts 下的相对路径 */
    private static final String SYSTEM_PROMPT_PATH = "order/summary.md";

    private final AiChatService aiChatService;
    private final PromptLoader promptLoader;

    @Override
    public String summarize(String orderNo) {
        return aiChatService.chat(promptLoader.get(SYSTEM_PROMPT_PATH), "订单号:" + orderNo);
    }
}

3. 编写 Controller ​

java
@Tag(name = "订单")
@RestController
@RequestMapping("/api/v1/orders")
@RequiredArgsConstructor
public class OrderAiController {

    private final OrderAiService orderAiService;

    @Operation(summary = "AI 生成订单摘要")
    @PostMapping("/{orderNo}/ai-summary")
    public Result<String> summarize(@PathVariable String orderNo) {
        return Result.success(orderAiService.summarize(orderNo));
    }
}

需要结构化结果时改用 chatEntity,传入返回的实体类型:

java
return aiChatService.chatEntity(systemPrompt, userPrompt, OrderSummaryVO.class);

注意事项 ​

  • 提示词随代码版本发布,修改后需重新构建部署,不支持热更新
  • 模型输出不可靠,涉及落库或执行的结果需业务侧校验,参考 FormRuleValidator 对表单规则的处理

下一步 ​

基于 MIT 许可发布 · 如需部署协助或二开定制,请查看 支持与合作