在AI编程、AI应用开发和AI Agent快速普及的背景下,技术人每天都会产生大量与AI模型的对话。这些对话里确实包含解决问题的关键信息,但绝大多数人处理这些信息的方式还停留在最原始阶段:把聊天记录截图、复制完整对话、把历史会话链接发给同事。结果是信息传出去了,知识并没有传出去。项目标题给出的观点非常直接:Share what you learned, not just your AI conversation。也就是要分享你从对话中学到的结论、验证过的方案和总结出的经验,而不是把AI交互本身当作交付物。这篇文章围绕AI辅助开发中的知识沉淀问题展开,适合正在使用AI编程工具、准备写AI应用开发笔记、或者需要把AI经验整理成团队文档和技术博客的开发者阅读。读完可以建立一套从对话到笔记、从笔记到博客的完整流程。
1. 为什么只分享AI对话是低效的知识传递方式
1.1 原始对话天然缺少上下文
无论是用Cursor生成代码,还是用通用大模型讨论Spring AI集成方案,对话本身都是分轮次进行的。每一轮回答都会受到前一轮问题的影响,但当你把这段对话分享出去时,接收者并不知道你最初的项目背景、已有的代码结构、使用的Spring Boot版本、依赖里引入了什么包。一个问题本身没有上下文,回答也很难被正确理解。对话里经常出现这种情况:AI说“在你的配置里加上这个参数”,但接收者根本不知道“你的配置”指哪个文件。
记录上下文不止是记录问题,还要记录环境信息。这里建议在每次对话开头先说明版本、框架、目标。看似多了一步,但后续分享时可以节省大量解释成本。在工程实践里,一段没有上下文的AI对话,和一段没有注释的代码一样,都是一种负债。
1.2 对话内容没有经过验证
AI生成的内容并不保证正确。代码可能因为版本变化而过时,API可能因为模型幻觉而被虚构,配置可能在实际运行环境中出现冲突。把未经验证的对话直接分享出去,等于把风险转嫁给接收者。接收者如果直接照抄,可能在自己的环境里遇到完全不同的错误,然后再反过来追问你,浪费双倍时间。
正确的做法是:对话里任何一段代码或配置,都至少要在本地环境跑通一次,再确认可以写入正式文档。如果暂时没有条件运行,要明确标注“未验证”三个字。这样接收者看到未验证内容时,会有意识去检查,而不是当成权威答案。
1.3 分享对话不等于分享经验,这是最容易被忽略的一点
对话记录描述的是“我做了什么”和“AI回答了什么”,但并没有回答“我学到了什么”、“这个方案为什么可行”和“哪些坑需要避开”。AI编程工具生成代码只是工程的一部分,真正的经验来自对代码的理解、对方案的取舍、对失败路径的记录。
举个典型场景:开发者在Cursor里让AI生成一段调用大模型接口的代码,第一次生成的接口地址和参数是错的,然后根据报错不断修正,最终调通。如果直接分享这段对话,接收者看到的是大量来回纠错的过程。如果分享总结出来的结论,接收者只需要看最终可用的代码、报错原因和修正方案。后者才是真正可以复用的经验。
也许有人会说,长截图更“真实”。但工程知识传播的关键不是真实,而是可用。分享原始对话只证明你用过AI,分享沉淀后的内容才能证明你解决了问题。
2. 建立AI对话知识沉淀流程:环境与工具准备
2.1 先定目标,再选工具
开始沉淀之前,先区分内容要服务谁。个人临时笔记、团队项目文档、公开技术博客三者对文档的完整度要求完全不同。
| 目标 | 使用对象 | 典型格式 | 存放位置 | 详细程度 |
|---|---|---|---|---|
| 个人临时笔记 | 自己 | Markdown,可只有要点 | 本地Obsidian或笔记软件 | 只需要自己能看懂 |
| 团队项目文档 | 同事 | Markdown,包含决策原因 | Git仓库docs目录、内部知识库 | 需要可执行、可排查 |
| 公开技术博客 | 未知开发者 | Markdown或平台编辑器 | CSDN、博客园、掘金等 | 需要完整可复现 |
个人临时笔记可以粗糙,因为上下文在你的大脑里。但一旦要分享给他人,就必须补全背景、验证状态和运行步骤。很多开发者跳过了中间步骤,直接把自己的临时笔记发布到技术平台,结果读者根本读不懂,这不是写作能力问题,而是内容层级没有匹配读者。
2.2 推荐的工具链和目录结构
对话沉淀不需要复杂系统,一个Git仓库加上Markdown文件就够了。推荐按下面目录组织:
ai-knowledge/ ├── records/ # 原始对话导出,只存档,不修改 │ └── 2025-06-14-cursor-spring-ai.md ├── notes/ # 提炼后的学习笔记 │ └── spring-ai-openai-compatible.md ├── blogs/ # 已整理可发布的技术博客草稿 │ └── spring-ai-integration.md ├── scripts/ # 转换脚本、批量处理脚本 │ └── convert_conversation.py └── assets/ # 图片、日志截图records目录保存原始对话,目的是留痕;notes目录保存经过验证和补充的内容;blogs目录只放准备发布或已发布的完整文章。脚本目录用于自动处理导出的对话。这个结构既适合个人,也适合小团队。
2.3 环境准备清单
开始写转换脚本之前,先确认本机环境。通常只需要Python 3.9及以上版本,不需要额外依赖,因为脚本只使用标准库。如果后续要处理HTML格式的对话导出,再考虑引入BeautifulSoup等解析库,并提前确认版本兼容。
| 项目 | 要求 | 说明 |
|---|---|---|
| Python | 3.9及以上 | 使用标准库json、re、pathlib |
| Git | 任意稳定版本 | 管理文档版本,保留每次沉淀快照 |
| Markdown编辑器 | 任意 | Typora、VS Code、Obsidian都可 |
| 开发验证环境 | 按实际项目而定 | 用于运行AI生成的代码,确认是否可复现 |
学习环境可以用最简单的方式跑通脚本,生产环境使用同一套脚本批量处理历史对话时,要额外注意文件编码、敏感信息脱敏和路径兼容性。这里的“生产环境”指团队正式的文档生成流程,而不是线上系统。
3. 用最小案例演示“对话转文档”的完整过程
3.1 案例背景:一次Spring AI接入对话
为了把流程讲具体,假设一个真实场景:开发者在Spring Boot项目中需要接入一个AI模型的聊天接口。他打开AI编程工具,问了几个问题,包括依赖怎么加、配置怎么填、代码怎么写。AI把方案给了出来。如果直接把这段对话发给同事,对方很难判断哪些步骤已经验证过。现在用脚本把它转换成结构化文档。
先准备一份简化后的对话记录文件conversation.json,结构可以自己定义:
[ { "role": "user", "content": "Spring Boot 项目里要接入一个 OpenAI 兼容接口,使用 Spring AI,依赖怎么加?" }, { "role": "assistant", "content": "引入 spring-ai-openai 依赖,版本需要和 Spring Boot 版本一起在 BOM 中管理。示例:\n```xml\n<dependency>\n <groupId>org.springframework.ai</groupId>\n <artifactId>spring-ai-openai</artifactId>\n</dependency>\n```" }, { "role": "user", "content": "接口地址和密钥怎么配置?" }, { "role": "assistant", "content": "在 application.yml 中配置 base-url 和 api-key,比如:\n```yaml\nspring:\n ai:\n openai:\n base-url: https://api.example.com/v1\n api-key: ${OPENAI_API_KEY}\n```" } ]实际从AI平台导出的格式可能是HTML或Markdown,可能比这个复杂,但核心信息都是角色和内容。脚本只要解析出这两项就可以继续处理。
3.2 提炼有效信息:什么该保留,什么该删掉
转换不是简单拼接,而是过滤。下面几种内容可以优先保留:
- 最终可用的代码块和配置片段
- 关键版本说明和依赖坐标
- 错误现象和对应的修复方式
- 需要人工确认的边界条件
下面几种内容可以删掉或折叠:
- 多轮重复的表述
- AI的道歉和换一种说法重试
- 与最终结论无关的示例数据
- 临时密钥、真实凭证等敏感信息
这一判断无法完全自动化,最好在脚本处理之后人工扫一遍。
3.3 用Python脚本把对话转成结构化Markdown
下面脚本将解析上面的JSON文件,把连续代码块整理成带语言标识的代码块,并为每段内容生成一个标题。为了保持脚本可读,这里只处理最简单的情况。
import json import re from pathlib import Path def extract_code_blocks(content: str): """从文本中提取 ```lang ... ``` 代码块,返回 (代码块列表, 剩余文本)""" code_blocks = [] remaining = [] lines = content.splitlines() i = 0 while i < len(lines): m = re.match(r"^```(\w*)", lines[i]) if m: lang = m.group(1) or "text" code = [] i += 1 while i < len(lines) and not lines[i].startswith("```"): code.append(lines[i]) i += 1 i += 1 code_blocks.append({"lang": lang, "code": "\n".join(code)}) else: remaining.append(lines[i]) i += 1 return code_blocks, "\n".join(remaining) def convert_conversation_to_markdown(input_path: str, output_path: str): with open(input_path, "r", encoding="utf-8") as f: conversations = json.load(f) lines = [ "> 本文档由 AI 对话自动转换生成,未经验证的内容必须人工确认后再使用。", "", ] section_no = 1 for item in conversations: role = item.get("role", "") content = item.get("content", "") code_blocks, text = extract_code_blocks(content) if role == "user": lines.append(f"## 问题 {section_no}") lines.append("") lines.append(text.strip()) lines.append("") section_no += 1 elif role == "assistant": lines.append("### 回答与结论") lines.append("") lines.append(text.strip()) lines.append("") for block in code_blocks: lines.append(f"```{block['lang']}") lines.append(block["code"]) lines.append("```") lines.append("") output = Path(output_path) output.parent.mkdir(parents=True, exist_ok=True) output.write_text("\n".join(lines), encoding="utf-8") print(f"转换完成:{output_path}") if __name__ == "__main__": convert_conversation_to_markdown( "conversation.json", "notes/spring-ai-integration.md" )这段脚本只做了一件事:把对话中的文本和代码拆分后重新组织成Markdown。脚本中提取代码块的正则要求代码块必须独立成行,且以```开头,这是Markdown的常规写法。实际导出的对话如果不满足这种格式,需要先对文本做预处理。
3.4 运行脚本并检查生成结果
在项目根目录执行:
python scripts/convert_conversation.py预期输出:
转换完成:notes/spring-ai-integration.md然后打开生成的Markdown文件,按顺序检查:
- 每个问题是否完整可读
- 每个代码块是否带有语言标识
- 生成的依赖配置是否可以直接复制到项目中
- 密钥占位符是否已经替换为环境变量写法
这个生成结果只是半成品。真正发布之前,还需要在Spring Boot项目中运行一遍,确认依赖版本能解析、配置能被读取、接口能够一次调通。如果发现某个配置项已经过时或缺少依赖,就必须在文档中修正,并把修正内容同步回原始对话记录,方便后续追溯。
4. 把AI生成内容变成可验证工程资产的关键步骤
4.1 每段代码都要在本地跑通,再写入正式文档
AI生成代码看起来完整,但离“可运行”还有一段距离。常见情况包括:缺少导入语句、版本和Spring Boot不匹配、依赖没有在BOM里管理、配置项在不同版本中命名不同。处理方式是按最小可运行原则逐个验证。
以Spring AI为例,验证顺序应该是:
- 新建一个最小Spring Boot项目,只引入必要依赖。
- 把AI生成的配置写入application.yml。
- 启动项目,观察是否报错。
- 调用一次接口,看是否能返回预期结果。
- 再把验证过的版本复制到正式文档。
如果你使用的是Cursor或类似工具,可以在生成代码后直接让AI继续检查“当前项目版本下这段代码是否有兼容性问题”。但AI的自我检查仍然可能出错,最终还是要以本地运行结果为准。
注意:验证不是一次性的。当你升级Spring Boot版本或更换依赖时,之前验证过的AI生成代码可能再次失效,需要重新跑通并更新文档。
4.2 补充“为什么”和边界条件,而不是只写“怎么做”
技术博客和AI对话的最大差别在于,AI回答通常直接给结论,不会解释完整的设计取舍。当你把结论转化成文档时,要主动补上为什么。
比如在Spring AI配置中,只写“把api-key放入application.yml”不够。读者会问:为什么使用环境变量而不是直接写在文件里?答案是避免密钥进入Git历史,降低泄露风险。只写“引入spring-ai-openai依赖”不够,还需要说明版本为什么不能在Spring Boot项目中随意指定,因为Spring AI依赖与Spring Boot版本有对应关系,通常需要引入官方BOM统一管理。
边界条件也要写清楚。例如:哪几个版本适用、使用国内模型时需要打开哪个兼容开关、请求超时设置在哪里调整、不同模型对上下文的支持差异等。AI对话不会主动把这些边界条件列全,需要你从对话中挖掘,或者做针对性提问。
4.3 记录失败路径,失败本身是最有价值的学习材料
很多人的对话记录里其实包含了宝贵的失败路径:第一次用错API、第二次参数格式不对、第三次才成功。但把这些过程全部平铺到文档里,阅读体验会很差。推荐做法是保留“失败现象+原因+解决方案”的表格形式,不保留冗长对话。
例如:
| 失败现象 | 根因 | 解决方案 |
|---|---|---|
| 启动时提示找不到spring-ai-openai相关类 | 没有引入BOM,版本解析失败 | 在dependencyManagement中添加Spring AI BOM |
| 接口返回401 | base-url配置错误或密钥无效 | 检查base-url路径,确认使用环境变量注入密钥 |
| 调用正常但中文回答截断 | 未设置max-tokens | 在配置中显式设置max-tokens参数 |
这种表格用一次AI对话就能总结出来,但对读者来说,比一段来回纠错的历史记录高效得多。
5. 对话沉淀过程中最常见的三类问题与排查
5.1 对话太碎,整理无从下手
现象是:打开历史对话,内容几十轮,有大量无意义来回,不知道怎么提炼。原因是提问时没有引导AI输出结构化内容,导致回答一直在变化。解决方法是建立一套固定的提问模板,让AI从第一轮开始就按结构输出。
推荐在AI编程工具的对话开头加入这样的要求:
请按以下结构回答: 1. 问题背景确认 2. 推荐方案 3. 关键依赖和版本说明 4. 可直接运行的代码示例 5. 需要注意的边界条件 6. 如果当前方案失败,可能的排查路径使用结构化模板之后,输出内容天然适合后续转文档。很多开发者反馈“AI偶尔不听话”,这种情况需要在提问中追加一句:“如果当前信息不足以回答某个部分,请明确说明缺失信息,不要猜测。”这能显著减少内容空洞。
5.2 直接照抄AI代码导致运行失败
现象是:把AI给的代码复制进项目,编译失败或者运行报错。这类问题的根源通常不是AI完全不可用,而是版本上下文缺失。AI训练数据存在截止时间,代码生成时不会自动知道你当前项目依赖了哪些包、用的是什么Spring Boot版本。
检查顺序按照优先级来:
- 检查报错栈最底部的异常类型,是类找不到还是参数不匹配。
- 检查导入语句是否完整,缺少哪个类。
- 检查依赖版本是否协调,Spring Boot和Spring AI版本是否匹配。
- 检查配置项是否被正确读取,是否出现了拼写错误。
- 用最小项目复现,把出错范围缩小到单模块。
如果错误是“NoClassDefFoundError”,优先怀疑依赖缺失;如果是“Could not resolve placeholder”,优先怀疑配置项名称不一致;如果是HTTP 404,优先怀疑base-url路径拼接错误。解决之后,把这次排查过程写成一条排错知识,比单纯保留对话更有效。
5.3 沉淀文档没人看,甚至自己也不想看
很多人写了笔记之后发现文档积灰。原因通常是文档没有面向阅读场景设计。笔记只是记录的堆积,没有搜索入口、没有概览、没有和代码仓库的关联。
改善方式有三个:
- 每篇笔记开头必须有“适用场景、验证状态、使用版本”三要素。
- 每篇笔记保留一个“快速开始”部分,代码必须能直接运行。
- 在团队内部知识库建立“AI辅助开发沉淀”目录,并在新人文档里给出索引链接。
| 问题现象 | 常见原因 | 检查方式 | 解决建议 |
|---|---|---|---|
| 对话太碎难整理 | 提问没有结构引导 | 回看第一轮提问是否指定了输出格式 | 使用结构化提问模板重新生成内容 |
| 照抄代码运行失败 | 版本上下文缺失 | 看异常栈、依赖版本、配置项 | 最小项目逐段验证后写入文档 |
| 文档写了没人看 | 文档没有使用场景入口 | 检查开头是否有快速开始和索引 | 补充适用场景、验证状态和运行示例 |
这张表也可以直接沉淀进团队文档,作为新人使用AI开发时的统一排错入口。
6. 从个人笔记到可分享技术博客的扩展实践
6.1 博客和笔记的差异在哪里
个人笔记允许跳步,因为写的人知道上下文。技术博客要面对完全未知的读者,读者不知道你的项目结构、不知道你使用的依赖版本、不知道你在哪一步遇到过什么坑。把笔记升级成博客需要做三次补充:补全准备步骤、补全验证结果、补全问答式排错。
一个可用的博客结构可以这样组织:
- 先说明要解决什么问题
- 再给环境准备和依赖清单
- 然后给出核心代码和配置
- 接着写运行结果和预期输出
- 最后列常见错误和排查路径
这个方法在CSDN、博客园、掘金都适用。写博客时不要直接把AI对话的长截图放进去,代码块要能复制,路径和版本要写完整。
6.2 把对话片段改造成可运行示例
AI对话中生成的代码通常是片段,需要补全为一个可运行的最小示例。改造时注意三点。
第一,把真实密钥替换成环境变量占位符。不要在博客和代码里出现真实API Key。示例中可以直接写${OPENAI_API_KEY},并在文中说明执行前需要设置环境变量。
export OPENAI_API_KEY="你的密钥"第二,补全读者需要知道但AI对话中没有提及的文件。比如application.yml放在src/main/resources目录下,依赖写在pom.xml里。
第三,给出预期输出。没有预期输出的博客像是没有测试的代码,读者无法判断自己是否操作成功。输出即使只有一行日志,也比不写强。
注意:任何需要密钥的命令都不要写入团队共享脚本,确保密钥仅存在于个人环境变量或密钥管理服务中。
6.3 让每次AI对话都成为知识库增量
沉淀不是一次性大工程,而是每次对话结束后的一个小动作。建议在完成一次AI辅助开发后立刻记录三个字段:目标、结果、坑。每次只花三到五分钟,长期稳定积累。
如果团队使用AI编程,可以建立统一约定:
- 对话中涉及生产环境和敏感数据的部分,不进入公共文档
- 文档必须标注验证状态:已本地验证、已测试环境验证、未验证
- 涉及版本升级后,要同步回查历史文档是否仍然适用
长期来看,这个机制的价值不只是留档,而是让下一次AI对话可以站在之前的结论上继续。当你把历史文档作为上下文喂给AI时,AI给出的答案会更贴近你的项目,而不是泛泛的通用建议。
以“分享你学到的东西,而不是分享AI对话本身”作为核心原则,最终沉淀出来的内容才是团队资产。对话会过时,模型会升级,但经过验证的知识、精简过的结论和清晰的排错路径,在任何时间拿出来都有价值。