@deepstorm/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -0
- package/dist/agents/reef-inspect-figma.md +77 -0
- package/dist/agents/reef-review-backend.md.tmpl +112 -0
- package/dist/agents/reef-review-frontend.md.tmpl +78 -0
- package/dist/agents/reef-review-infra.md +47 -0
- package/dist/agents/reef-review-security.md.tmpl +80 -0
- package/dist/agents/reef-scope-analysis.md +64 -0
- package/dist/build-registry.js +375 -0
- package/dist/cli.js +8581 -0
- package/dist/config-schema.json +133 -0
- package/dist/env-examples/context7.env-example +19 -0
- package/dist/env-examples/feishu-wiki.env-example +16 -0
- package/dist/env-examples/figma.env-example +16 -0
- package/dist/env-examples/github.env-example +20 -0
- package/dist/env-examples/jira.env-example +20 -0
- package/dist/hooks/mcp-hook.sh +77 -0
- package/dist/hooks/reef-auto-format.sh.tmpl +72 -0
- package/dist/hooks/reef-block-dangerous.sh +70 -0
- package/dist/hooks/reef-hooks.json +72 -0
- package/dist/hooks/reef-intent-detect.sh +129 -0
- package/dist/hooks/reef-protect-files.sh +55 -0
- package/dist/hooks/reef-run-tests.sh +84 -0
- package/dist/hooks/reef-scope-check.sh +386 -0
- package/dist/hooks/reef-scope-ci.sh +28 -0
- package/dist/hooks/reef-scope-gate.sh +115 -0
- package/dist/hooks/reef-scope-pre-commit.sh.tmpl +28 -0
- package/dist/hooks/reef-scope-setup.sh +204 -0
- package/dist/hooks/reef-scope-split.sh +203 -0
- package/dist/hooks/sweep-hooks.json +14 -0
- package/dist/hooks/sweep-mcp-hook.sh +77 -0
- package/dist/hooks/tide-hooks.json +14 -0
- package/dist/hooks/tide-session-preload.sh +17 -0
- package/dist/mcp/code-hosting/github.json +20 -0
- package/dist/mcp/design-tools/figma.json +19 -0
- package/dist/mcp/docs-reference/context7.json +28 -0
- package/dist/mcp/e2e-testing/playwright.json +13 -0
- package/dist/mcp/knowledge-base/feishu-wiki.json +19 -0
- package/dist/mcp/project-management/jira.json +27 -0
- package/dist/mcp-skills/deepflow-mcp-feishu-wiki-read/SKILL.md +65 -0
- package/dist/mcp-skills/deepflow-mcp-feishu-wiki-write/SKILL.md +63 -0
- package/dist/mcp-skills/deepflow-mcp-figma-read/SKILL.md +98 -0
- package/dist/mcp-skills/deepflow-mcp-github-read/SKILL.md +62 -0
- package/dist/mcp-skills/deepflow-mcp-github-write/SKILL.md +63 -0
- package/dist/mcp-skills/deepflow-mcp-jira-read/SKILL.md +80 -0
- package/dist/mcp-skills/deepflow-mcp-jira-write/SKILL.md +74 -0
- package/dist/mcp-skills/deepflow-mcp-playwright-read/SKILL.md +79 -0
- package/dist/mcp-skills/deepstorm-mcp-feishu-wiki-read/SKILL.md +65 -0
- package/dist/mcp-skills/deepstorm-mcp-feishu-wiki-write/SKILL.md +63 -0
- package/dist/mcp-skills/deepstorm-mcp-figma-read/SKILL.md +98 -0
- package/dist/mcp-skills/deepstorm-mcp-github-read/SKILL.md +62 -0
- package/dist/mcp-skills/deepstorm-mcp-github-write/SKILL.md +63 -0
- package/dist/mcp-skills/deepstorm-mcp-jira-read/SKILL.md +80 -0
- package/dist/mcp-skills/deepstorm-mcp-jira-write/SKILL.md +74 -0
- package/dist/mcp-skills/deepstorm-mcp-playwright-read/SKILL.md +79 -0
- package/dist/registry.json +818 -0
- package/dist/skills/atoll-ops/SKILL.md +46 -0
- package/dist/skills/reef-commit/SKILL.md +127 -0
- package/dist/skills/reef-gen-backend/SKILL.md.tmpl +87 -0
- package/dist/skills/reef-gen-backend/variants/java/steps.md +28 -0
- package/dist/skills/reef-gen-backend/variants/python/steps.md +70 -0
- package/dist/skills/reef-gen-frontend/SKILL.md.tmpl +83 -0
- package/dist/skills/reef-gen-frontend/variants/angular/steps.md +30 -0
- package/dist/skills/reef-harden/EXAMPLES.md +89 -0
- package/dist/skills/reef-harden/SKILL.md +136 -0
- package/dist/skills/reef-pr/SKILL.md +97 -0
- package/dist/skills/reef-review/SKILL.md.tmpl +107 -0
- package/dist/skills/reef-scope/SKILL.md +134 -0
- package/dist/skills/reef-start/SKILL.md.tmpl +562 -0
- package/dist/skills/reef-start/references/jira-start-subagent.md +60 -0
- package/dist/skills/reef-style-backend/SKILL.md.tmpl +134 -0
- package/dist/skills/reef-style-backend/fragments/java/ai/spring-ai/examples/chat-client.md +96 -0
- package/dist/skills/reef-style-backend/fragments/java/ai/spring-ai/examples/rag.md +94 -0
- package/dist/skills/reef-style-backend/fragments/java/ai/spring-ai/examples/structured-output.md +62 -0
- package/dist/skills/reef-style-backend/fragments/java/ai/spring-ai/examples/tool-calling.md +68 -0
- package/dist/skills/reef-style-backend/fragments/java/ai/spring-ai/quick-reference.md +220 -0
- package/dist/skills/reef-style-backend/fragments/java/api-spec/quick-reference.md +148 -0
- package/dist/skills/reef-style-backend/fragments/java/db-migration/liquibase/examples/database-migration.md +131 -0
- package/dist/skills/reef-style-backend/fragments/java/db-migration/liquibase/quick-reference.md +103 -0
- package/dist/skills/reef-style-backend/fragments/java/dependency-management/quick-reference.md +119 -0
- package/dist/skills/reef-style-backend/fragments/java/exception-handling/examples/error-code-enum.md +101 -0
- package/dist/skills/reef-style-backend/fragments/java/exception-handling/quick-reference.md +181 -0
- package/dist/skills/reef-style-backend/fragments/java/framework/spring-boot/examples/controller.md +95 -0
- package/dist/skills/reef-style-backend/fragments/java/framework/spring-boot/examples/dto-mapper.md +121 -0
- package/dist/skills/reef-style-backend/fragments/java/framework/spring-boot/examples/infrastructure.md +179 -0
- package/dist/skills/reef-style-backend/fragments/java/framework/spring-boot/examples/service-entity.md +202 -0
- package/dist/skills/reef-style-backend/fragments/java/framework/spring-boot/examples/testing.md +107 -0
- package/dist/skills/reef-style-backend/fragments/java/framework/spring-boot/quick-reference.md +83 -0
- package/dist/skills/reef-style-backend/fragments/java/orm/hibernate/quick-reference.md +150 -0
- package/dist/skills/reef-style-backend/fragments/java/security-redlines/quick-reference.md +197 -0
- package/dist/skills/reef-style-backend/fragments/java/test/data-jpa-test/examples/user-repository-test.md +69 -0
- package/dist/skills/reef-style-backend/fragments/java/test/data-jpa-test/quick-reference.md +101 -0
- package/dist/skills/reef-style-backend/fragments/java/test/junit5/examples/user-service-test.md +61 -0
- package/dist/skills/reef-style-backend/fragments/java/test/junit5/quick-reference.md +100 -0
- package/dist/skills/reef-style-backend/fragments/java/test/spring-mvc-test/examples/user-controller-test.md +61 -0
- package/dist/skills/reef-style-backend/fragments/java/test/spring-mvc-test/quick-reference.md +85 -0
- package/dist/skills/reef-style-backend/fragments/java/test/spring-service-test/examples/user-service-integration-test.md +56 -0
- package/dist/skills/reef-style-backend/fragments/java/test/spring-service-test/quick-reference.md +83 -0
- package/dist/skills/reef-style-backend/fragments/python/alembic-migration/quick-reference.md +77 -0
- package/dist/skills/reef-style-backend/fragments/python/api-spec/quick-reference.md +164 -0
- package/dist/skills/reef-style-backend/fragments/python/dependency-management/quick-reference.md +139 -0
- package/dist/skills/reef-style-backend/fragments/python/exception-handling/quick-reference.md +177 -0
- package/dist/skills/reef-style-backend/fragments/python/fastapi-quick-reference/quick-reference.md +101 -0
- package/dist/skills/reef-style-backend/fragments/python/langchain/quick-reference.md +135 -0
- package/dist/skills/reef-style-backend/fragments/python/pytest-testing/quick-reference.md +111 -0
- package/dist/skills/reef-style-backend/fragments/python/ruff-mypy-toolchain/quick-reference.md +83 -0
- package/dist/skills/reef-style-backend/fragments/python/security-redlines/quick-reference.md +207 -0
- package/dist/skills/reef-style-backend/fragments/python/sqlalchemy-orm/quick-reference.md +91 -0
- package/dist/skills/reef-style-backend/variants/java/examples/code-wrapping.md +227 -0
- package/dist/skills/reef-style-backend/variants/java/examples/contributor-pattern.md +97 -0
- package/dist/skills/reef-style-backend/variants/java/quick-reference.md +117 -0
- package/dist/skills/reef-style-backend/variants/python/examples/crud-router.md +71 -0
- package/dist/skills/reef-style-backend/variants/python/examples/pydantic-schema.md +45 -0
- package/dist/skills/reef-style-backend/variants/python/examples/pytest-fixture.md +60 -0
- package/dist/skills/reef-style-backend/variants/python/examples/sqlalchemy-model.md +31 -0
- package/dist/skills/reef-style-backend/variants/python/quick-reference.md +111 -0
- package/dist/skills/reef-style-frontend/SKILL.md.tmpl +70 -0
- package/dist/skills/reef-style-frontend/fragments/css/tailwind/quick-reference.md +79 -0
- package/dist/skills/reef-style-frontend/fragments/test/vitest/examples/testing.md +150 -0
- package/dist/skills/reef-style-frontend/fragments/test/vitest/quick-reference.md +141 -0
- package/dist/skills/reef-style-frontend/fragments/ts-config/strict/quick-reference.md +112 -0
- package/dist/skills/reef-style-frontend/fragments/ui-lib/primeng/examples/ui-components.md +134 -0
- package/dist/skills/reef-style-frontend/fragments/ui-lib/primeng/quick-reference.md +66 -0
- package/dist/skills/reef-style-frontend/variants/angular/examples/code-wrapping.md +252 -0
- package/dist/skills/reef-style-frontend/variants/angular/examples/component-types-pipes.md +56 -0
- package/dist/skills/reef-style-frontend/variants/angular/examples/entity-types.md +100 -0
- package/dist/skills/reef-style-frontend/variants/angular/examples/forms-layer.md +119 -0
- package/dist/skills/reef-style-frontend/variants/angular/examples/service-routing.md +95 -0
- package/dist/skills/reef-style-frontend/variants/angular/quick-reference.md +100 -0
- package/dist/skills/reef-testcase/SKILL.md +138 -0
- package/dist/skills/reef-testcase/references/coverage-dimensions.md +99 -0
- package/dist/skills/reef-testcase/references/test-case-template.md +63 -0
- package/dist/skills/sweep-init/SKILL.md +286 -0
- package/dist/skills/sweep-init/scripts/flow-selector.mjs +305 -0
- package/dist/skills/sweep-plan/SKILL.md.tmpl +312 -0
- package/dist/skills/sweep-plan/references/test-flow-template.md +46 -0
- package/dist/skills/sweep-run/SKILL.md +437 -0
- package/dist/skills/sweep-run/scripts/env-manager.mjs +208 -0
- package/dist/skills/sweep-run/scripts/flow-parser.mjs +329 -0
- package/dist/skills/sweep-run/scripts/flow-selector.mjs +483 -0
- package/dist/skills/sweep-run/scripts/mcp-manager.mjs +208 -0
- package/dist/skills/sweep-run/scripts/spec-compiler.mjs +303 -0
- package/dist/skills/tide-discuss/SKILL.md.tmpl +449 -0
- package/dist/skills/tide-discuss/references/checklists.md +88 -0
- package/dist/skills/tide-discuss/references/data-format.md +237 -0
- package/dist/skills/tide-discuss/references/prd-template.md +134 -0
- package/dist/skills/tide-discuss/references/publish-flow.md +167 -0
- package/dist/skills/tide-discuss/references/role-prompts.md +105 -0
- package/package.json +38 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reef-style-backend
|
|
3
|
+
description: 后端编码规范({{reef.backend.language.label}})。包含实体层次、DTO、Service/Controller/Repository 模式、MapStruct、多租户安全等完整规范。创建/修改后端代码时必须按本技能输出。
|
|
4
|
+
user-invocable: false
|
|
5
|
+
allowed-tools: Bash(git:*), Bash({{reef.backend.language.buildTool}})
|
|
6
|
+
deepstorm:
|
|
7
|
+
tool: reef
|
|
8
|
+
configKey: reef.backend.language
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# 后端编码规范
|
|
12
|
+
|
|
13
|
+
## ⚠️ 触发条件(必须遵守)
|
|
14
|
+
|
|
15
|
+
创建或修改任何后端文件时,必须通过 Skill tool 加载本技能,并按本技能中所有规范输出代码。对应技术栈:{{reef.backend.language.label}}。
|
|
16
|
+
|
|
17
|
+
> **仅对本次新增/修改的代码应用规范,不格式化已有代码。** 已有的、本次未修改的代码行保持原样。
|
|
18
|
+
|
|
19
|
+
## 维度规范
|
|
20
|
+
|
|
21
|
+
{{#if reef.backend.language.styleRef}}
|
|
22
|
+
### 语言/平台规范
|
|
23
|
+
{{reef.backend.language.styleRef}}
|
|
24
|
+
{{/if}}
|
|
25
|
+
|
|
26
|
+
{{#if reef.backend.java.framework.styleRef}}
|
|
27
|
+
### Java 框架规范
|
|
28
|
+
{{reef.backend.java.framework.styleRef}}
|
|
29
|
+
{{/if}}
|
|
30
|
+
|
|
31
|
+
{{#if reef.backend.java.orm.styleRef}}
|
|
32
|
+
### ORM 框架规范
|
|
33
|
+
{{reef.backend.java.orm.styleRef}}
|
|
34
|
+
{{/if}}
|
|
35
|
+
|
|
36
|
+
{{#if reef.backend.java.dbMigration.styleRef}}
|
|
37
|
+
### 数据库迁移规范
|
|
38
|
+
{{reef.backend.java.dbMigration.styleRef}}
|
|
39
|
+
{{/if}}
|
|
40
|
+
|
|
41
|
+
{{#if reef.backend.java.ai.styleRef}}
|
|
42
|
+
### AI 框架规范
|
|
43
|
+
{{reef.backend.java.ai.styleRef}}
|
|
44
|
+
{{/if}}
|
|
45
|
+
|
|
46
|
+
{{#if reef.backend.java.test.styleRef}}
|
|
47
|
+
### 🧪 测试规范
|
|
48
|
+
|
|
49
|
+
#### 通用原则
|
|
50
|
+
- **测试金字塔**:Unit(单元测试)→ Integration(集成测试)→ E2E(端到端测试)。越底层测试越多,运行速度越快
|
|
51
|
+
- **FIRST 原则**:Fast(快速)、Independent(独立)、Repeatable(可重复)、Self-validating(自验证)、Timely(及时)
|
|
52
|
+
- **AAA 模式**:Arrange(准备测试数据)→ Act(执行被测方法)→ Assert(验证结果)
|
|
53
|
+
|
|
54
|
+
#### 框架规范
|
|
55
|
+
{{reef.backend.java.test.styleRef}}
|
|
56
|
+
{{/if}}
|
|
57
|
+
|
|
58
|
+
{{#if reef.backend.java.framework.styleRef}}
|
|
59
|
+
### 📐 API 规范
|
|
60
|
+
→ 参考 [API 规范](api-spec.md)
|
|
61
|
+
|
|
62
|
+
包括:RESTful 资源命名、统一响应体 `ApiResponse<T>` / `PageResponse<T>` / `ErrorResponse`、版本策略、OpenAPI 文档注解、分页约定、错误码命名规范。
|
|
63
|
+
{{/if}}
|
|
64
|
+
|
|
65
|
+
{{#if reef.backend.java.framework.styleRef}}
|
|
66
|
+
### 📦 依赖管理规范
|
|
67
|
+
→ 参考 [依赖管理规范](dependency-management.md)
|
|
68
|
+
|
|
69
|
+
包括:Gradle Version Catalog(`libs.versions.toml`)、禁止硬编码版本号、版本一致性规则、Gradle Versions Plugin、CVE 管理、禁止使用的依赖。
|
|
70
|
+
{{/if}}
|
|
71
|
+
|
|
72
|
+
{{#if reef.backend.java.framework.styleRef}}
|
|
73
|
+
### 🚨 异常处理深度规范
|
|
74
|
+
→ 参考 [异常处理规范](exception-handling.md)
|
|
75
|
+
|
|
76
|
+
包括:业务异常继承层次、错误码枚举约定(`{MODULE}_{NNN}`)、`@RestControllerAdvice` 全局处理、`ErrorResponse` 结构、异常与 HTTP Status 映射。
|
|
77
|
+
{{/if}}
|
|
78
|
+
|
|
79
|
+
{{#if reef.backend.java.framework.styleRef}}
|
|
80
|
+
### 🔒 安全红线
|
|
81
|
+
→ 参考 [安全红线](security-redlines.md)
|
|
82
|
+
|
|
83
|
+
包括:密码存储(BCrypt)、SQL 注入防范、危险初始化(`@PostConstruct`)、硬编码密钥、敏感信息脱敏、文件上传验证。**所有 P0 红线不得违反。**
|
|
84
|
+
{{/if}}
|
|
85
|
+
|
|
86
|
+
{{#if reef.backend.python.framework.styleRef}}
|
|
87
|
+
### 📐 API 规范(Python)
|
|
88
|
+
→ 参考 [API 规范](api-spec.md)
|
|
89
|
+
|
|
90
|
+
包括:RESTful 资源命名、统一响应体 `ApiResponse` / `PageResponse` / `ErrorResponse`、版本策略、FastAPI OpenAPI 配置、分页约定。
|
|
91
|
+
{{/if}}
|
|
92
|
+
|
|
93
|
+
{{#if reef.backend.python.framework.styleRef}}
|
|
94
|
+
### 📦 依赖管理规范(Python)
|
|
95
|
+
→ 参考 [依赖管理规范](dependency-management.md)
|
|
96
|
+
|
|
97
|
+
包括:`pyproject.toml` 结构、禁止通配符版本、`uv` 命令速查、依赖分组(运行/开发)、CVE 审计(`uv audit`)。
|
|
98
|
+
{{/if}}
|
|
99
|
+
|
|
100
|
+
{{#if reef.backend.python.framework.styleRef}}
|
|
101
|
+
### 🚨 异常处理深度规范(Python)
|
|
102
|
+
→ 参考 [异常处理规范](exception-handling.md)
|
|
103
|
+
|
|
104
|
+
包括:`AppError(HTTPException)` 继承层次、错误码枚举、FastAPI `@app.exception_handler` 全局处理、兜底 500 处理。
|
|
105
|
+
{{/if}}
|
|
106
|
+
|
|
107
|
+
{{#if reef.backend.python.framework.styleRef}}
|
|
108
|
+
### 🔒 安全红线(Python)
|
|
109
|
+
→ 参考 [安全红线](security-redlines.md)
|
|
110
|
+
|
|
111
|
+
包括:密码哈希(bcrypt/passlib)、SQL 注入防范、硬编码密钥、敏感信息脱敏、Pydantic 输入验证红线、CORS 配置、生产环境禁用调试接口。**所有 P0 红线不得违反。**
|
|
112
|
+
{{/if}}
|
|
113
|
+
|
|
114
|
+
## 知识文件
|
|
115
|
+
|
|
116
|
+
以下文件位于本技能目录,安装时自动复制。内容按所选维度定制。
|
|
117
|
+
|
|
118
|
+
加载本技能时先用 `Read` 读取 `quick-reference.md` 了解核心规范,再按照上方「维度规范」中的链接选择对应文件加载(如 `spring-boot.md`、`hibernate.md`),最后根据当前变更类型在 `examples/` 目录中选择示例文件:
|
|
119
|
+
|
|
120
|
+
| 文件 | 说明 |
|
|
121
|
+
|------|------|
|
|
122
|
+
| `quick-reference.md` | **编码规范速查**。包含核心规则和约定 |
|
|
123
|
+
| `{value}.md` | **维度规范**(如 `spring-boot.md`、`hibernate.md`)。按上方链接加载 |
|
|
124
|
+
| `api-spec.md` | **API 规范**。RESTful 命名、统一响应体、版本策略、OpenAPI |
|
|
125
|
+
| `dependency-management.md` | **依赖管理规范**。Version Catalog、版本一致性、CVE |
|
|
126
|
+
| `exception-handling.md` | **异常处理深度规范**。异常层次、错误码、全局处理 |
|
|
127
|
+
| `security-redlines.md` | **安全红线**。P0/P1 安全规则及代码示例 |
|
|
128
|
+
| `examples/{文件}` | 按需加载示例文件(仅读与当前变更相关的) |
|
|
129
|
+
|
|
130
|
+
## 使用方式
|
|
131
|
+
|
|
132
|
+
- **创建/修改后端代码时**:Skill tool 自动加载(见触发条件)
|
|
133
|
+
- `reef:reef-gen-backend` — 编写后端代码时自动加载
|
|
134
|
+
- `reef:reef-review-backend` — 审查后端代码时自动加载
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Spring AI ChatClient 示例
|
|
2
|
+
|
|
3
|
+
## 基础用法
|
|
4
|
+
|
|
5
|
+
```java
|
|
6
|
+
@Configuration
|
|
7
|
+
public class AiConfig {
|
|
8
|
+
|
|
9
|
+
@Bean
|
|
10
|
+
ChatClient chatClient(ChatClient.Builder builder) {
|
|
11
|
+
return builder
|
|
12
|
+
.defaultSystem("你是一个专业的 Java 后端开发助手")
|
|
13
|
+
.defaultFunctions("getCurrentTime") // 注册默认工具
|
|
14
|
+
.build();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Service 层集成
|
|
20
|
+
|
|
21
|
+
```java
|
|
22
|
+
@Service
|
|
23
|
+
public class AiAssistantService {
|
|
24
|
+
|
|
25
|
+
private final ChatClient chatClient;
|
|
26
|
+
|
|
27
|
+
public AiAssistantService(ChatClient.Builder builder) {
|
|
28
|
+
this.chatClient = builder
|
|
29
|
+
.defaultSystem("""
|
|
30
|
+
你是企业应用开发助手。
|
|
31
|
+
回答问题时:
|
|
32
|
+
1. 引用代码规范
|
|
33
|
+
2. 提供完整的代码示例
|
|
34
|
+
3. 说明设计理由
|
|
35
|
+
""")
|
|
36
|
+
.build();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 生成代码建议
|
|
41
|
+
*/
|
|
42
|
+
public String generateSuggestion(String question) {
|
|
43
|
+
return chatClient.prompt()
|
|
44
|
+
.user(u -> u.text("""
|
|
45
|
+
问题是: {question}
|
|
46
|
+
请用 Java + Spring Boot 实现。
|
|
47
|
+
""")
|
|
48
|
+
.param("question", question))
|
|
49
|
+
.call()
|
|
50
|
+
.content();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 多轮对话
|
|
56
|
+
|
|
57
|
+
```java
|
|
58
|
+
@Service
|
|
59
|
+
public class ConversationService {
|
|
60
|
+
|
|
61
|
+
private final ChatClient chatClient;
|
|
62
|
+
|
|
63
|
+
public ConversationService(ChatClient.Builder builder) {
|
|
64
|
+
this.chatClient = builder.build();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public ChatResponse chat(String sessionId, String message) {
|
|
68
|
+
return chatClient.prompt()
|
|
69
|
+
.user(message)
|
|
70
|
+
.advisors(new MessageChatMemoryAdvisor(
|
|
71
|
+
new InMemoryChatMemory(), sessionId, 10 // 保留最近 10 轮
|
|
72
|
+
))
|
|
73
|
+
.call()
|
|
74
|
+
.chatResponse();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 流式响应
|
|
80
|
+
|
|
81
|
+
```java
|
|
82
|
+
@RestController
|
|
83
|
+
@RequestMapping("/api/ai")
|
|
84
|
+
public class AiController {
|
|
85
|
+
|
|
86
|
+
private final ChatClient chatClient;
|
|
87
|
+
|
|
88
|
+
@PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
|
89
|
+
public Flux<String> streamResponse(@RequestBody @Valid ChatRequest request) {
|
|
90
|
+
return chatClient.prompt()
|
|
91
|
+
.user(request.message())
|
|
92
|
+
.stream()
|
|
93
|
+
.content(); // 返回 Flux<String>
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Spring AI RAG 示例
|
|
2
|
+
|
|
3
|
+
## 向量存储配置
|
|
4
|
+
|
|
5
|
+
```java
|
|
6
|
+
@Configuration
|
|
7
|
+
public class VectorStoreConfig {
|
|
8
|
+
|
|
9
|
+
@Bean
|
|
10
|
+
VectorStore pgVectorStore(JdbcTemplate jdbcTemplate) {
|
|
11
|
+
return new PgVectorStore(jdbcTemplate, new VectorStoreConfig());
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## 文档入库
|
|
17
|
+
|
|
18
|
+
```java
|
|
19
|
+
@Service
|
|
20
|
+
public class DocumentIngestionService {
|
|
21
|
+
|
|
22
|
+
private final VectorStore vectorStore;
|
|
23
|
+
|
|
24
|
+
@PostConstruct
|
|
25
|
+
public void init() {
|
|
26
|
+
// 应用启动时加载知识库
|
|
27
|
+
loadDocuments("classpath:/docs/coding-standards/");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public void loadDocuments(String path) {
|
|
31
|
+
var reader = new JsonReader(new FileSystemResource(path));
|
|
32
|
+
List<Document> documents = reader.get();
|
|
33
|
+
|
|
34
|
+
// 添加元数据
|
|
35
|
+
documents.forEach(doc -> {
|
|
36
|
+
doc.getMetadata().put("source", "coding-standards");
|
|
37
|
+
doc.getMetadata().put("version", "1.0");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
vectorStore.accept(documents);
|
|
41
|
+
log.info("已加载 {} 份规范文档", documents.size());
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## RAG 查询
|
|
47
|
+
|
|
48
|
+
```java
|
|
49
|
+
@Service
|
|
50
|
+
public class RagQueryService {
|
|
51
|
+
|
|
52
|
+
private final ChatClient chatClient;
|
|
53
|
+
private final VectorStore vectorStore;
|
|
54
|
+
|
|
55
|
+
public String query(String question) {
|
|
56
|
+
return chatClient.prompt()
|
|
57
|
+
.user(question)
|
|
58
|
+
.advisors(new QuestionAnswerAdvisor(
|
|
59
|
+
vectorStore,
|
|
60
|
+
SearchRequest.defaults().withTopK(3) // 检索 top-3 文档
|
|
61
|
+
))
|
|
62
|
+
.call()
|
|
63
|
+
.content();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 自定义 Advisor
|
|
69
|
+
|
|
70
|
+
```java
|
|
71
|
+
@Component
|
|
72
|
+
public class ContextFilterAdvisor implements CallAroundAdvisor {
|
|
73
|
+
|
|
74
|
+
@Override
|
|
75
|
+
public String getName() {
|
|
76
|
+
return "ContextFilterAdvisor";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@Override
|
|
80
|
+
public int getOrder() {
|
|
81
|
+
return 0;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@Override
|
|
85
|
+
public ChatClientResponse aroundCall(AdvisedRequest request, CallAroundAdvisorChain chain) {
|
|
86
|
+
// 在调用前过滤或增强上下文
|
|
87
|
+
AdvisedRequest filtered = AdvisedRequest.from(request)
|
|
88
|
+
.withSystemText(request.systemText() + "\n注意:仅基于现有文档回答问题,不要编造信息。")
|
|
89
|
+
.build();
|
|
90
|
+
|
|
91
|
+
return chain.nextAroundCall(filtered);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
package/dist/skills/reef-style-backend/fragments/java/ai/spring-ai/examples/structured-output.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Spring AI 结构化输出示例
|
|
2
|
+
|
|
3
|
+
## 简单 Record
|
|
4
|
+
|
|
5
|
+
```java
|
|
6
|
+
public record WeatherResponse(String city, double temperature, String unit) {}
|
|
7
|
+
|
|
8
|
+
// 使用
|
|
9
|
+
WeatherResponse weather = chatClient.prompt()
|
|
10
|
+
.user("北京今天天气怎么样?")
|
|
11
|
+
.call()
|
|
12
|
+
.entity(WeatherResponse.class);
|
|
13
|
+
|
|
14
|
+
log.info("城市: {}, 温度: {}{}", weather.city(), weather.temperature(), weather.unit());
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 嵌套结构
|
|
18
|
+
|
|
19
|
+
```java
|
|
20
|
+
public record CodeReviewResult(
|
|
21
|
+
String file,
|
|
22
|
+
List<Issue> issues,
|
|
23
|
+
int score
|
|
24
|
+
) {
|
|
25
|
+
public record Issue(
|
|
26
|
+
int line,
|
|
27
|
+
Severity severity,
|
|
28
|
+
String message,
|
|
29
|
+
String suggestion
|
|
30
|
+
) {
|
|
31
|
+
enum Severity { CRITICAL, WARNING, SUGGESTION }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// 使用
|
|
36
|
+
CodeReviewResult result = chatClient.prompt()
|
|
37
|
+
.user("""
|
|
38
|
+
审查以下代码:
|
|
39
|
+
```java
|
|
40
|
+
public class Test {
|
|
41
|
+
public void run() { }
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
""")
|
|
45
|
+
.call()
|
|
46
|
+
.entity(CodeReviewResult.class);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 列表输出
|
|
50
|
+
|
|
51
|
+
```java
|
|
52
|
+
public record TaskList(List<TaskItem> tasks) {
|
|
53
|
+
public record TaskItem(String title, String description, Priority priority) {
|
|
54
|
+
enum Priority { HIGH, MEDIUM, LOW }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
TaskList tasks = chatClient.prompt()
|
|
59
|
+
.user("将用户需求拆解为开发任务")
|
|
60
|
+
.call()
|
|
61
|
+
.entity(TaskList.class);
|
|
62
|
+
```
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Spring AI Tool 调用示例
|
|
2
|
+
|
|
3
|
+
## 基本 Tool
|
|
4
|
+
|
|
5
|
+
```java
|
|
6
|
+
@Service
|
|
7
|
+
public class OrderTools {
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 查询用户订单列表
|
|
11
|
+
*/
|
|
12
|
+
@Tool(description = "根据用户 ID 查询订单列表")
|
|
13
|
+
public List<OrderDTO> getOrdersByUser(
|
|
14
|
+
@ToolParam(description = "用户 ID,数字格式") Long userId) {
|
|
15
|
+
// 实际调用 OrderService
|
|
16
|
+
return orderService.findByUserId(userId);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 获取订单详情
|
|
21
|
+
*/
|
|
22
|
+
@Tool(description = "根据订单 ID 查询订单详情")
|
|
23
|
+
public OrderDTO getOrderDetail(
|
|
24
|
+
@ToolParam(description = "订单 ID") Long orderId) {
|
|
25
|
+
return orderService.findById(orderId);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 带权限校验的 Tool
|
|
31
|
+
|
|
32
|
+
```java
|
|
33
|
+
@Service
|
|
34
|
+
public class SecureTools {
|
|
35
|
+
|
|
36
|
+
private final SecurityContext securityContext;
|
|
37
|
+
|
|
38
|
+
@Tool(description = "创建新订单")
|
|
39
|
+
public OrderDTO createOrder(
|
|
40
|
+
@ToolParam(description = "订单创建请求") CreateOrderRequest request) {
|
|
41
|
+
// 权限校验
|
|
42
|
+
User currentUser = securityContext.getCurrentUser();
|
|
43
|
+
if (!currentUser.hasPermission("order:create")) {
|
|
44
|
+
throw new SecurityException("无创建订单权限");
|
|
45
|
+
}
|
|
46
|
+
return orderService.create(request, currentUser.getId());
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Tool 注册
|
|
52
|
+
|
|
53
|
+
```java
|
|
54
|
+
@Configuration
|
|
55
|
+
public class ToolConfig {
|
|
56
|
+
|
|
57
|
+
private final OrderTools orderTools;
|
|
58
|
+
private final UserTools userTools;
|
|
59
|
+
|
|
60
|
+
@Bean
|
|
61
|
+
ChatClient assistantChatClient(ChatClient.Builder builder) {
|
|
62
|
+
return builder
|
|
63
|
+
.defaultSystem("你是订单管理助手")
|
|
64
|
+
.defaultTools(orderTools, userTools) // 注册所有 Tool
|
|
65
|
+
.build();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Spring AI 开发规范
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
Spring AI 是 Spring 生态中的 AI 集成框架,提供统一的 API 来调用 LLM、管理对话、构建 RAG 应用。
|
|
6
|
+
|
|
7
|
+
## 核心概念
|
|
8
|
+
|
|
9
|
+
### ChatClient
|
|
10
|
+
Spring AI 的中央 API,用于与大语言模型交互。
|
|
11
|
+
|
|
12
|
+
```java
|
|
13
|
+
@Bean
|
|
14
|
+
ChatClient chatClient(ChatClient.Builder builder) {
|
|
15
|
+
return builder.defaultSystem("你是一个专业的 Java 开发者助手").build();
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**最佳实践:**
|
|
20
|
+
- `ChatClient` 声明为 `@Bean` 并注入使用,不直接创建实例
|
|
21
|
+
- `defaultSystem()` 设置默认系统提示词
|
|
22
|
+
- `builder.clone()` 创建独立的客户端实例(需要不同配置时)
|
|
23
|
+
|
|
24
|
+
### Tool(函数调用)
|
|
25
|
+
|
|
26
|
+
AI 模型调用外部工具的能力。
|
|
27
|
+
|
|
28
|
+
```java
|
|
29
|
+
@Tool(description = "获取用户订单信息")
|
|
30
|
+
public List<Order> getOrders(@ToolParam(description = "用户 ID") String userId) {
|
|
31
|
+
return orderRepository.findByUserId(userId);
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**最佳实践:**
|
|
36
|
+
- 每个 `@Tool` 方法加 `description` 描述,帮助模型选择正确的工具
|
|
37
|
+
- `@ToolParam` 的 `description` 帮助模型理解参数含义
|
|
38
|
+
- 工具方法放在 `@Service` 类中,统一管理
|
|
39
|
+
- 返回值类型明确,避免 `Object` 或泛型丢失
|
|
40
|
+
|
|
41
|
+
### Advisor(对话链)
|
|
42
|
+
|
|
43
|
+
构建多步骤的 AI 处理流程。
|
|
44
|
+
|
|
45
|
+
```java
|
|
46
|
+
ChatClientResponse response = chatClient.prompt()
|
|
47
|
+
.advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
|
|
48
|
+
.user("查询文档")
|
|
49
|
+
.call()
|
|
50
|
+
.content();
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**常见 Advisor:**
|
|
54
|
+
- `QuestionAnswerAdvisor` — RAG 支持
|
|
55
|
+
- `MessageChatMemoryAdvisor` — 对话记忆
|
|
56
|
+
- `LoggingAdvisor` — 日志记录
|
|
57
|
+
|
|
58
|
+
### VectorStore
|
|
59
|
+
|
|
60
|
+
向量数据库抽象,用于 RAG(检索增强生成)。
|
|
61
|
+
|
|
62
|
+
```java
|
|
63
|
+
@Service
|
|
64
|
+
public class DocumentService {
|
|
65
|
+
private final VectorStore vectorStore;
|
|
66
|
+
|
|
67
|
+
public DocumentService(VectorStore vectorStore) {
|
|
68
|
+
this.vectorStore = vectorStore;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public void storeDocuments(List<Document> documents) {
|
|
72
|
+
vectorStore.accept(documents);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public List<Document> searchSimilar(String query) {
|
|
76
|
+
return vectorStore.similaritySearch(SearchRequest.query(query)
|
|
77
|
+
.withTopK(5));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**最佳实践:**
|
|
83
|
+
- VectorStore 通过 Spring DI 注入,不同实现(PGVector、Redis、Chroma)切换只需改配置
|
|
84
|
+
- 文档入库时保留 metadata(来源、更新时间、权限)
|
|
85
|
+
|
|
86
|
+
### Structured Output(结构化输出)
|
|
87
|
+
|
|
88
|
+
将 AI 响应映射为 Java 对象。
|
|
89
|
+
|
|
90
|
+
```java
|
|
91
|
+
record WeatherResponse(String city, double temperature, String unit) {}
|
|
92
|
+
|
|
93
|
+
WeatherResponse weather = chatClient.prompt()
|
|
94
|
+
.user("北京今天天气怎么样?")
|
|
95
|
+
.call()
|
|
96
|
+
.entity(WeatherResponse.class);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**最佳实践:**
|
|
100
|
+
- 使用 `record` 而非 class 定义输出结构
|
|
101
|
+
- 字段类型明确,避免 `String` 滥用
|
|
102
|
+
|
|
103
|
+
## 配置
|
|
104
|
+
|
|
105
|
+
```yaml
|
|
106
|
+
spring:
|
|
107
|
+
ai:
|
|
108
|
+
openai:
|
|
109
|
+
api-key: ${OPENAI_API_KEY}
|
|
110
|
+
chat:
|
|
111
|
+
options:
|
|
112
|
+
model: gpt-4o
|
|
113
|
+
temperature: 0.7
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**最佳实践:**
|
|
117
|
+
- API Key 始终通过 `${}` 环境变量引用,不硬编码
|
|
118
|
+
- 敏感配置放在 `.env` 文件中,不提交到 Git
|
|
119
|
+
|
|
120
|
+
## DeepSeek
|
|
121
|
+
|
|
122
|
+
DeepSeek 是一个高性能的国产大语言模型,通过 `spring-ai-starter-model-deepseek` 集成。
|
|
123
|
+
|
|
124
|
+
### 配置
|
|
125
|
+
|
|
126
|
+
```yaml
|
|
127
|
+
spring:
|
|
128
|
+
ai:
|
|
129
|
+
deepseek:
|
|
130
|
+
api-key: ${DEEPSEEK_API_KEY}
|
|
131
|
+
chat:
|
|
132
|
+
options:
|
|
133
|
+
model: deepseek-chat
|
|
134
|
+
temperature: 0.7
|
|
135
|
+
max-tokens: 2048
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**可用模型:**
|
|
139
|
+
- `deepseek-chat` — 通用对话模型,适用于日常问答、代码生成、内容创作
|
|
140
|
+
- `deepseek-reasoner` — 推理模型,适用于复杂推理、数学问题、逻辑分析(通过 API 调用,Spring AI Starter 暂未直接封装)
|
|
141
|
+
|
|
142
|
+
### 使用示例
|
|
143
|
+
|
|
144
|
+
```java
|
|
145
|
+
@Service
|
|
146
|
+
public class AiService {
|
|
147
|
+
private final ChatClient chatClient;
|
|
148
|
+
|
|
149
|
+
public AiService(ChatClient.Builder builder) {
|
|
150
|
+
this.chatClient = builder
|
|
151
|
+
.defaultSystem("你是一个专业的 Java 开发者助手")
|
|
152
|
+
.build();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public String chat(String message) {
|
|
156
|
+
try {
|
|
157
|
+
return chatClient.prompt()
|
|
158
|
+
.user(message)
|
|
159
|
+
.call()
|
|
160
|
+
.content();
|
|
161
|
+
} catch (Exception e) {
|
|
162
|
+
log.error("DeepSeek 调用失败", e);
|
|
163
|
+
return "抱歉,服务暂时不可用";
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### 依赖
|
|
170
|
+
|
|
171
|
+
```groovy
|
|
172
|
+
// build.gradle
|
|
173
|
+
implementation 'org.springframework.ai:spring-ai-starter-model-deepseek'
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
或 Maven:
|
|
177
|
+
```xml
|
|
178
|
+
<dependency>
|
|
179
|
+
<groupId>org.springframework.ai</groupId>
|
|
180
|
+
<artifactId>spring-ai-starter-model-deepseek</artifactId>
|
|
181
|
+
</dependency>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 依赖管理
|
|
185
|
+
|
|
186
|
+
```groovy
|
|
187
|
+
// build.gradle
|
|
188
|
+
implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter'
|
|
189
|
+
// 如需 RAG
|
|
190
|
+
implementation 'org.springframework.ai:spring-ai-pgvector-store-spring-boot-starter'
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
或 Maven:
|
|
194
|
+
```xml
|
|
195
|
+
<dependency>
|
|
196
|
+
<groupId>org.springframework.ai</groupId>
|
|
197
|
+
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
|
|
198
|
+
</dependency>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## 错误处理
|
|
202
|
+
|
|
203
|
+
```java
|
|
204
|
+
try {
|
|
205
|
+
String response = chatClient.prompt().user("查询数据").call().content();
|
|
206
|
+
// 处理响应
|
|
207
|
+
} catch (AiException e) {
|
|
208
|
+
log.error("AI 调用失败", e);
|
|
209
|
+
// 降级处理
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**注意事项:**
|
|
214
|
+
- AI 调用可能失败或超时,必须有降级逻辑
|
|
215
|
+
- 记录 AI 调用的输入和输出,便于调试和审计
|
|
216
|
+
|
|
217
|
+
## 参考资料
|
|
218
|
+
|
|
219
|
+
- [Spring AI 官方文档](https://docs.spring.io/spring-ai/reference/)
|
|
220
|
+
- 示例文件见 `examples/` 目录
|