第13篇:《把PDF变成AI能懂的"密码":我用向量数据库建了个知识库》

作者:第一行代码HW日期:2026/7/29

承上:上一篇我们把文档切成了高质量的小碎片,但它们还只是文本。AI不认识文本,只认识数字。今天,我们要把这些文本碎片变成一串串数字——向量,存入向量数据库,让AI真正能"理解"你的私有知识。

1. 先搞懂:什么是Embedding?

1.1. 用后端老鸟的类比

假设你是数据库管理员,要给1000本书建立索引:

1传统索引:
2"Java编程思想"  按书名倒排  J字母开头  3排第5
3
4向量索引:
5"Java编程思想"  转成一串数字[0.23, -0.15, 0.78, ...]  
6  1536维空间里找一个坐标点  
7  "Java入门"  也转成坐标  找最近的点  就是这本书!
8

Embedding 就是把文本映射到高维空间的坐标点。语义越相似,坐标越接近。

1"年假怎么请"  [0.12, -0.34, 0.56, ...]   1536个数字
2"休假政策"    [0.13, -0.32, 0.54, ...]   坐标非常接近!
3"今天天气"    [-0.78, 0.45, -0.23, ...]  坐标很远
4

Spring AI 2.0 通过统一的 EmbeddingModel 接口支持多种模型:

模型维度最大输入价格
text-embedding-ada-002(OpenAI)15368191 Token¥0.008/千Token
text-embedding-3-small(OpenAI)15368191 Token¥0.002/千Token
通义千问 Embedding15362048 Token¥0.0007/千Token

本篇使用通义千问的Embedding模型,和我们的对话模型一致,国内访问稳定,价格便宜。

2. 第一步:配置Embedding模型

2.1. 添加依赖

1<dependency>
2    <groupId>org.springframework.ai</groupId>
3    <artifactId>spring-ai-starter-openai</artifactId>
4</dependency>
5

注意:和之前的对话模型用同一个Starter。通义千问的Embedding也通过OpenAI兼容接口提供。

2.2. 配置Embedding

1spring:
2  ai:
3    openai:
4      api-key: xxxx
5      base-url: https://ws-xxxx.cn-beijing.maas.aliyuncs.com/compatible-mode/v1
6      chat:
7        options:
8          model: qwen3.7-max
9      embedding:
10        options:
11          model: qwen3.7-text-embedding
12

2.3. 第一个Embedding测试

1package com.oldbird.ai.chapter13.embedding;
2
3import org.springframework.ai.embedding.EmbeddingModel;
4import org.springframework.ai.embedding.EmbeddingResponse;
5import org.springframework.stereotype.Component;
6
7import java.util.List;
8
9@Component
10public class EmbeddingDemo {
11
12    private final EmbeddingModel embeddingModel;
13
14    public EmbeddingDemo(EmbeddingModel embeddingModel) {
15        this.embeddingModel = embeddingModel;
16    }
17
18    public void testEmbedding() {
19        // 将文本转成向量
20        EmbeddingResponse response = embeddingModel.embedForResponse(
21                List.of("入职满1年享有5天带薪年假", "年假怎么申请")
22        );
23
24        List<float[]> vectors = response.getResults().stream()
25                .map(result -> result.getOutput())
26                .toList();
27
28        System.out.println("向量维度:" + vectors.get(0).length);  // 1536
29        System.out.println("第一个向量前5个值:" +
30                vectors.get(0)[0] + ", " +
31                vectors.get(0)[1] + ", " +
32                vectors.get(0)[2] + ", " +
33                vectors.get(0)[3] + ", " +
34                vectors.get(0)[4]);
35
36        // 计算相似度
37        double similarity = cosineSimilarity(vectors.get(0), vectors.get(1));
38        System.out.println("两句话的余弦相似度:" + similarity);
39        // 输出:0.92(高度相似)
40    }
41
42    /**
43     * 余弦相似度:衡量两个向量在多维空间中的夹角
44     * 1.0 = 完全同向(语义相同)
45     * 0.0 = 正交(无关)
46     * -1.0 = 完全反向(语义相反)
47     */
48    private double cosineSimilarity(float[] a, float[] b) {
49        double dotProduct = 0;
50        double normA = 0;
51        double normB = 0;
52        for (int i = 0; i < a.length; i++) {
53            dotProduct += a[i] * b[i];
54            normA += a[i] * a[i];
55            normB += b[i] * b[i];
56        }
57        return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
58    }
59}
60

运行结果

1向量维度:1024
2第一个向量前5个值:0.023570376, -0.009924047, -0.025762115, 0.0029585415, 0.02347242
3两句话的余弦相似度:0.643651355275984
4

关键认知:文本→1024个浮点数→一个坐标。从此以后,"语义相似"可以用"坐标距离"来数学计算。这就是AI能"理解"文本的底层原理。

3. 第二步:选择向量数据库

3.1. 主流向量的数据库对比

向量数据的选型我没有经验可谈哈,但是用于学习实战和公司小型知识库我觉得redis足够。

数据库类型优势劣势适用场景
Redis Stack内存+磁盘已有Redis可复用,毫秒级内存贵,大规模成本高中小规模、已有Redis
Milvus专业向量库十亿级向量,索引丰富独立部署,运维复杂大规模生产
PGVectorPostgreSQL插件和业务库一体,SQL查询百万级以上性能下降已有PostgreSQL
Elasticsearch搜索引擎混合检索(关键词+向量)向量检索非原生已有ES

3.2. 本篇选择:Redis Stack

理由

  1. 上一篇第9篇(ChatMemory)已经用了Redis,不引入新中间件
  2. 开发阶段零成本,Docker一行命令搞定
  3. 向量检索性能足够(百万级以下)

3.3. 部署Redis Stack

1docker run -d \
2  --name redis-stack \
3  -p 6379:6379 \
4  -p 8001:8001 \
5  redis/redis-stack:latest
6

Redis Stack 包含了 RediSearch 模块,支持向量检索。普通Redis不行。

4. 第三步:向量化并写入Redis

4.1. 添加依赖

1<dependency>
2    <groupId>org.springframework.ai</groupId>
3    <artifactId>spring-ai-starter-vector-store-redis</artifactId>
4</dependency>
5

4.2. 配置向量存储Bean

1package com.yunxi.ai.config;
2
3import org.springframework.ai.embedding.EmbeddingModel;
4import org.springframework.ai.vectorstore.redis.RedisVectorStore;
5import org.springframework.beans.factory.annotation.Value;
6import org.springframework.context.annotation.Bean;
7import org.springframework.context.annotation.Configuration;
8import redis.clients.jedis.JedisPoolConfig;
9import redis.clients.jedis.RedisClient;
10
11@Configuration
12public class VectorStoreConfig {
13    @Bean
14    public RedisVectorStore vectorStore(RedisClient jedisRedisClient, EmbeddingModel embeddingModel) {
15        return RedisVectorStore.builder(jedisRedisClient, embeddingModel)
16                .indexName("spring-ai-knowledge")
17                .prefix("doc:")
18                .metadataFields(
19                        RedisVectorStore.MetadataField.tag("source")
20                )
21                .initializeSchema(true)
22                .build();
23    }
24}
25

4.3. 完整的导入服务

1package com.yunxi.ai.controller;
2
3import com.yunxi.ai.entity.Result;
4import lombok.extern.slf4j.Slf4j;
5import org.springframework.ai.document.Document;
6import org.springframework.ai.reader.tika.TikaDocumentReader;
7import org.springframework.ai.transformer.splitter.TokenTextSplitter;
8import org.springframework.ai.vectorstore.VectorStore;
9import org.springframework.beans.factory.annotation.Autowired;
10import org.springframework.core.io.Resource;
11import org.springframework.web.bind.annotation.RequestMapping;
12import org.springframework.web.bind.annotation.RequestParam;
13import org.springframework.web.bind.annotation.RestController;
14import org.springframework.web.multipart.MultipartFile;
15
16import java.util.List;
17
18@RestController
19@RequestMapping("/rag")
20@Slf4j
21public class RagController {
22
23    /**
24     * 导入文档到向量数据库
25     * 完整流程:读取  分割  向量化  存储
26     */
27    @RequestMapping("/uploadAndEmbedding")
28    public Result uploadAndEmbedding(@RequestParam("file") MultipartFile file, @RequestParam(value = "chunkSize", defaultValue = "500") Integer chunkSize) {
29        if (file == null || file.isEmpty()) {
30            return Result.failed(500, "文件为空");
31        }
32        try {
33            log.info("开始处理文件:{},分片大小:{}", file.getOriginalFilename(), chunkSize);
34            Resource resource = file.getResource();
35            TikaDocumentReader tikaDocumentReader = new TikaDocumentReader(resource);
36            List<Document> read = tikaDocumentReader.read();
37            log.info("文件解析完成,原始文档数:{}", read.size());
38            TokenTextSplitter splitter = TokenTextSplitter.builder().withChunkSize(chunkSize).build();
39            List<Document> apply = splitter.apply(read);
40            log.info("分片完成,总分片数:{}", apply.size());
41            // 向量化存储
42            vectorStore.add(apply);
43            return Result.successed(apply);
44        } catch (Exception e) {
45            log.error("文件处理异常", e);
46            return Result.failed(500, "文件处理异常:" + e.getMessage());
47        }
48    }
49
50}
51

核心代码就一句:vectorStore.add(apply);

4.4. 验证导入

生成了10个分片,Redis里发生了什么?

1Key: doc:4dd6f53b-bd60-4327-b566-131247fcf9ee
2Type: Hash
3Value: {
4  "chunk_index": 4,
5  "parent_document_id": "5f0a7d4a-b53f-4cc6-b5fd-8b6e5541120c",
6  "embedding": [
7    0.01784777,
8    0.014171031,
9    -0.020203378,
10    -0.052795503...
11  ],
12  "source": "1001.docx",
13  "total_chunks": 10,
14  "content": "- 迟到:未在规定上班时间内完成有效打卡,且无有效请假、外勤审批记录的行为\n- 早退:未在规定下班时间完成有效打卡提前离岗,且无有效审批记录的行为\n4.2 梯度处罚标准\n1. 月度内单次迟到/早退时长在10分钟以内,累计不超过3次的,不予扣款,给予口头提醒\n2. 月度内迟到/早退累计超过3次,或单次时长在10-30分钟的,每次扣除当月全勤奖的20%\n3. 月度内迟到/早退累计超过5次,或单次时长在30-60分钟的,每次扣除当日工资的20%,全公司通报批评\n4. 月度内单次迟到/早退时长超过60分钟的,按旷工半天核算,扣除当日全额工资\n5. 年度内迟到/早退累计超过36次的,取消当年年度调薪、晋升资格,人力资源部下发绩效改进通知\n4.3 特殊豁免场景\n员工因暴雨、暴雪、地铁故障等不可抗力公共事件导致迟到的,经行政部核实后可豁免迟到处罚,不纳入月度考勤统计。\n第五章 旷工管理\n5.1 旷工判定情形\n员工出现以下任意一种情形,直接判定为旷工:\n1."
15}
16

每个文档块都存了:原始文本 + 元数据 + 向量

5. 第四步:向量检索

5.1. 检索逻辑

1    /**
2     * 向量检索
3     */
4    @RequestMapping("/searchEmbedding")
5    public Result searchEmbedding(String query, Integer topK) {
6        try{
7            SearchRequest request = SearchRequest.builder()
8                    .query(query)
9                    .topK(topK)
10                    .build();
11            List<Document> results = vectorStore.similaritySearch(request);
12            return Result.successed(results);
13        } catch (Exception e) {
14            return Result.failed(500, "系统异常");
15        }
16    }
17

5.2. 测试检索效果

查询1:年假相关

分析:第一个结果精准命中"年假"内容。第二个和第三个虽然也是休假相关,但和年假不完全匹配——这就是向量检索的特点:找语义相似的,不一定是关键词完全匹配的。

查询2:长期超过50天

用户问的是"出差超过50天",AI精准检索到了"长期出差"那段,长期出差超过30天。用户可能用了口语化表达,但向量检索理解了他的语义。

6. 向量数据库里到底存了什么?

用Redis CLI看一下:

1# 查看索引信息
2redis-cli FT.INFO spring-ai-knowledge
3FT.INFO spring-ai-knowledge
41) "key_table_size_mb"
52) 0.0001659393310546875
63) "geoshapes_sz_mb"
74) 0
85) "bytes_per_record_avg"
96) 89.2532730102539
107) "index_name"
118) "spring-ai-knowledge"
129) "attributes"
1310)     1)      1) "identifier"
14        2) "$.content"
15        3) "attribute"
16        4) "content"
17        5) "type"
18        6) "TEXT"
19        7) "WEIGHT"
20        8) 1
21        9) "flags"
22        10) 
23        2)      1) "algorithm"
24        2) "HNSW"
25        3) "distance_metric"
26        4) "COSINE"
27        5) "flags"
28        6) 
29        7) "identifier"
30        8) "$.embedding"
31        9) "data_type"
32        10) "FLOAT32"
33        11) "dim"
34        12) 1024
35        13) "M"
36        14) 16
37        15) "ef_construction"
38        16) 200
39        17) "attribute"
40        18) "embedding"
41        19) "type"
42        20) "VECTOR"
43        3)      1) "identifier"
44        2) "$.source"
45        3) "attribute"
46        4) "source"
47        5) "type"
48        6) "TAG"
49        7) "SEPARATOR"
50        8) ""
51        9) "flags"
52        10) 
5311) "sortable_values_size_mb"
5412) 0
5513) "offset_bits_per_record_avg"
5614) 8
5715) "number_of_uses"
5816) 1
5917) "num_records"
6018) 229
6119) "total_index_memory_sz_mb"
6220) 0.043750762939453125
6321) "cleaning"
6422) 0
6523) "inverted_sz_mb"
6624) 0.019492149353027344
6725) "gc_stats"
6826)     1) "bytes_collected"
69        2) 0
70        3) "total_ms_run"
71        4) 0
72        5) "total_cycles"
73        6) 0
74        7) "average_cycle_time_ms"
75        8) NaN
76        9) "last_run_time_ms"
77        10) 0
78        11) "gc_numeric_trees_missed"
79        12) 0
80        13) "gc_blocks_denied"
81        14) 0
8227) "num_terms"
8328) 196
8429) "offset_vectors_sz_mb"
8530) 0.000385284423828125
8631) "doc_table_size_mb"
8732) 0.015834808349609375
8833) "records_per_doc_avg"
8934) 45.79999923706055
9035) "offsets_per_term_avg"
9136) 1.7641921043395996
9237) "dialect_stats"
9338)     1) "dialect_1"
94        2) 0
95        3) "dialect_2"
96        4) 0
97        5) "dialect_3"
98        6) 0
99        7) "dialect_4"
100        8) 0
10139) "field statistics"
10240)     1)      1) "identifier"
103        2) "$.content"
104        3) "attribute"
105        4) "content"
106        5) "Index Errors"
107        6)      1) "indexing failures"
108        2) 0
109        3) "last indexing error"
110        4) "N/A"
111        5) "last indexing error key"
112        6) "N/A"
113        2)      1) "identifier"
114        2) "$.embedding"
115        3) "attribute"
116        4) "embedding"
117        5) "Index Errors"
118        6)      1) "indexing failures"
119        2) 0
120        3) "last indexing error"
121        4) "N/A"
122        5) "last indexing error key"
123        6) "N/A"
124        3)      1) "attribute"
125        2) "source"
126        3) "Index Errors"
127        4)      1) "last indexing error key"
128        2) "N/A"
129        3) "indexing failures"
130        4) 0
131        5) "last indexing error"
132        6) "N/A"
133        5) "identifier"
134        6) "$.source"
13541) "index_options"
13642) 
13743) "num_docs"
13844) 5
13945) "tag_overhead_sz_mb"
14046) 0.00002765655517578125
14147) "Index Errors"
14248)     1) "background indexing status"
143        2) "OK"
144        3) "indexing failures"
145        4) 0
146        5) "last indexing error"
147        6) "N/A"
148        7) "last indexing error key"
149        8) "N/A"
15049) "index_definition"
15150)     1) "key_type"
152        2) "JSON"
153        3) "prefixes"
154        4)      1) "doc:"
155        5) "default_score"
156        6) 1
15751) "total_inverted_index_blocks"
15852) 2246
15953) "text_overhead_sz_mb"
16054) 0.006542205810546875
16155) "percent_indexed"
16256) 1
16357) "hash_indexing_failures"
16458) 0
16559) "total_indexing_time"
16660) 1.5779999494552612
16761) "indexing"
16862) 0
16963) "cursor_stats"
17064)     1) "global_idle"
171        2) 0
172        3) "global_total"
173        4) 0
174        5) "index_capacity"
175        6) 128
176        7) "index_total"
177        8) 0
17865) "max_doc_id"
17966) 5
18067) "vector_index_sz_mb"
18168) 4.216209411621094
182

数据存储结构

1索引:spring-ai-knowledge
2├── 向量字段:embedding(1536维浮点数向量)
3├── 文本字段:content(原始文本)
4├── 元数据字段:source、chunk_index(可过滤)
5└── 相似度算法:余弦相似度(COSINE)
6

7. 本篇避坑指南

7.1. 坑1:普通Redis不支持向量检索

1错误:docker run -d redis
2正确:docker run -d redis/redis-stack
3

Redis Stack 才包含 RediSearch 模块。普通Redis启动后,向量存储会报 ERR unknown command 'FT.CREATE'

7.2. 坑2:Embedding维度不匹配

通义千问Embedding是1536维,但代码里如果配置了其他模型(如1024维),向量写入和检索会因维度不一致失败。

解决:确认 spring.ai.openai.embedding.options.model 和实际用的模型一致。

7.3. 坑3:向量检索结果看似不相关

症状:搜"年假",第2、3名结果是"婚假"、"病假"。

原因:它们在向量空间里确实很近(都是休假相关段落)。这不是bug,是特征。

解决:后续用 Reranker 或混合检索提升精确度。

7.4. 坑4:Redis内存占用预估

每条向量存储约占用:1536 × 4字节(float32) ≈ 6KB。加上文本和元数据,每个文档块约10-20KB。

建议:万级文档块没问题,十万级以上考虑 Milvus。

7.5. 八、本篇小结

这一篇我们完成了RAG的第二步——向量化与存储:

步骤工具要点
EmbeddingEmbeddingModel文本→1536维向量
向量存储RedisVectorStore向量+文本+元数据
语义检索similaritySearch()用户问题→向量→找最近邻居

核心心法

1Embedding的本质:把"语义相似"变成"坐标距离"
2向量的数据库的本质:用空间索引加速最近邻搜索
3
4当你把100个文档、1000个文档块都转成向量存入Redis后,
5你的AI就不再是"外人"——它能通过数学计算,
6在你的知识库里找到最相关的那句话。
7

现在向量数据库里已经有我们的私有知识了,能搜到最相关的文档块。

下一篇,我们要把这些检索到的文档块注入Prompt模板,让AI看着资料回答问题,跑通完整的RAG链路。


本文与DeepSeek协作完成


第13篇:《把PDF变成AI能懂的"密码":我用向量数据库建了个知识库》》 是转载文章,点击查看原文


相关推荐


Python 函数式编程:从思想到实践
卷无止境2026/7/21

函数式编程(Functional Programming,FP)是一种把"计算"看作数学函数求值的编程范式——它不像面向对象那样关注"对象状态",而是强调用函数来描述数据的变换过程。Python 并非纯函数式语言,但它对这套思想的支持相当完善,掌握它能让你的代码更简洁、更易测试、更少 bug。下面我们一层一层把这件事讲清楚。 🧭 核心思想:函数式编程在想什么? 函数式编程的哲学核心只有一句话:数据流过一系列纯函数,产生结果,过程中不改变任何外部状态。 这和流水线工厂很像——每道工序只做一件


Kotlin Flow 深入解析:`stateIn()` 的真正核心,其实是 SharingStarted
潜龙勿用之化骨龙2026/7/13

很多 Android 开发者使用 stateIn() 时,代码几乎都是以下这种: stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(5000), initialValue = UiState.Loading ) 这其实已经是标准写法了。 实际上: stateIn 做的事情只有两件: 1、把冷流升级为热流 2、通过 SharingStarted 控制上游生命周期 这里最关


Claude Sonnet 5 上线:别再让 Claude Code 一律烧 Opus
鲁大猿2026/7/5

Claude Sonnet 5 上线:别再让 Claude Code 一律烧 Opus 6 月 30 日,Anthropic 发布 Claude Sonnet 5。 如果你平时用 Claude Code,这条消息不应该只理解成“又来了一个更强模型”。 它真正影响的是一个更具体的团队决策:以后 Claude Code 到底什么时候用 Sonnet,什么时候用 Opus,什么时候必须让人接管? 我的判断很直接: 不要全员默认 Opus。 也不要一听 Sonnet 5 便宜、上下文长,就把所有 Ag


你好,我叫Token——AI世界里最忙的搬砖工
Kfaino2026/6/27

码农的AI翻身之旅(一) 你好,我叫Token——AI世界里最忙的搬砖工 大家好。 我叫 Token。 别看我名字洋气,其实我就是个打零工的。 AI世界里,所有人都认识ChatGPT,认识DeepSeek,认识Claude,认识Gemini…… 可是,没有几个人认识我。 然而,没有我,他们一句话都说不出来。 我的出生 某一天。 一个程序员打开了ChatGPT。 他说: 帮我写一个Spring Boot项目。 于是,我出生了。 准确来说,不是我一个。 而是一大群兄弟。 因为AI眼里,根本没


一篇看懂 VKE AI Profiling:AI 应用性能分析优化实战
火山引擎Agent社区2026/6/18

你有没有遇到过这样的情况: AI 模型在训练时 GPU 利用率忽高忽低,容器资源明明给够了,训练时长却总是超出预期?或者在推理服务上线后,延迟时不时抖动,重启一下又好了,但问题根本找不到? “我的模型在裸机上跑只要 2 小时,放到容器里怎么变成 3 小时了?” “资源都给了,CPU 和内存也没瓶颈,我不知道还要看什么。” 很多团队在模型效果验证通过后,真正进入上线或规模化使用时,往往会遇到一个共同问题:GPU 看起来很忙,但整体效率并不高;系统投入不少,性能瓶颈却不容易快速定位。 这正是 A


架构视图与文档:C4 模型从入门到实战
ltl2026/6/10

你上次打开团队的架构图是什么时候? 大多数团队都有架构图。Confluence 上躺着一张两年前画的系统拓扑图,Visio 文件在某个共享盘里,PowerPoint 里有几页"技术方案评审"的框线图。问题是:没人信它们。新人入职时看一眼,发现和实际系统对不上,从此再也不看。老人心里有一张"真正的架构图",但那张图只存在于他的脑子里。 这不是个别现象。Simon Brown 在 2018 年的调查中发现,超过半数的开发者认为自己团队的架构文档"基本没用"或"严重过时"(Simon Brown, "


Java MyBatis-Flex 实战指南:从 BaseMapper 到 QueryWrapper 的轻量 ORM 用法
唐青枫2026/6/3

简介 MyBatis-Flex 是一个基于 MyBatis 的增强框架。 它的定位很直接: 保留 MyBatis 写 SQL 的灵活性,同时补上通用 CRUD、链式查询、分页、逻辑删除、乐观锁等常用能力。 普通 MyBatis 项目里,常见代码结构是: Entity Mapper 接口 Mapper XML Service Controller 如果只是做一张表的增删改查,也要写不少重复 SQL。 MyBatis-Flex 的思路是: 简单 CRUD 交给 BaseMapper 复杂条件交给


我用AI一小时撸了个单词学习站,每天自动生成5个单词
修己xj2026/5/26

AI编程热度居高不下,我也一直在用CodeBuddy辅助开发。最近发现了一个有意思的功能——Skill(技能包),灵机一动:不如写个技能,每天自动生成英文单词并部署成网页,这样打开浏览器就能学。 说干就干,全程AI辅助,一个多小时就搞定了。过程分享给大家。 以下是项目地址及在线地址 在线访问:xiuji008.github.io/everyday-en… 项目完全开源:github.com/xiuji008/ev… 灵感来源 CodeBuddy的Skill功能可以定义一套自动化流程。比如我说“


claudeCode+DeepSeekV4pro[1m]
冰镇生鲜2026/5/5

Claude Code 完美调和配置 这是经过多轮磨合后的全局配置,可以直接复制到新电脑的 ~/.claude/settings.json 使用。 也可以直接让 AI 处理一切。 完整配置文件 ~/.claude/settings.json { "env": { "ANTHROPIC_AUTH_TOKEN": "sk-你的token", "ANTHROPIC_BASE_URL": "https://api.deepseek.com/anthropic", "AN


【AI Agent | 第七篇】Skill的使用:将经验沉淀成可复用工作流
程序员夏末2026/4/25

前言   此文是我近期学习Agent中关于Skill使用的一点心得,结合AI整理总结而来,分享给大家。一是为了记录,二是用于日后的回顾,三也是希望能给其他初学者带来一点点帮助。 目录 1. 为什么我会开始关注 Skill?2. Skill 到底解决了什么问题?3. 从写博客这个例子理解 Skill 的价值4. 一个 Skill 通常包含哪些内容?5. Skill 使用时会加载哪些上下文?6. 写 Skill 时我踩到的几个细节7. 什么样的工作流适合沉淀成 Skill?8. 总结

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读