如何将他人文档整理为LLM-Wiki笔记.md 12 KB

如何将他人文档整理为 LLM Wiki 笔记

流程:源材料 → raw/ 学习笔记(含代码 + 通俗解释) → wiki/ 知识页。

以 STM32 学习笔记和 FreeRTOS 笔记为例。


1. 源材料分析

1.1 识别源类型

类型 处理方式 工具
DOCX 教程 pandoc 转 MD,提取图片 pandoc + --extract-media
PDF 手册 markitdown 或直接 OCR markitdown skill
视频教程 已有配套讲义则直接处理,无讲义需先转录
网页/博客 webfetch 抓取 webfetch tool

1.2 评估教学内容

拿到文档后先扫描目录结构,理解其教学法:

  • 按什么顺序讲解?(外设逐个?还是功能分类?)
  • 代码风格是什么?(寄存器?标准库?HAL?)
  • 有什么独特的教学方法?(例如尚硅谷的"三步进化法":裸地址 → 结构体 → 位宏定义)

2. 文档转换与图片提取

2.1 DOCX → Markdown

# 提取到 temp 目录,保留所有图片
pandoc "源文档.docx" -t markdown --wrap=none `
  --extract-media="C:\temp\docx_media" `
  -o "C:\temp\docx_media\笔记.md"

这会生成:

  • .md 文件(含图片引用路径)
  • media/ 目录(含所有 PNG、EMF 等图片)

2.2 阅读并理解转换后的文档

用 Read tool 逐段阅读 MD 文件,在 read 时注意:

  • 图片上下文:每张图片前后文字说明该图片内容
  • 章节结构:编号标题(1.、1.1、2.等)反映原文档组织方式
  • 代码块:注意代码风格和教学顺序

    # 读取文档的前 200 行了解结构
    Read offset=1 limit=200
    
    # 跳读找到关键章节
    Read offset=N limit=50
    

2.3 图片筛选(核心步骤)

不要盲目全部复制到仓库! 大多数 DOCX 图片是 IDE 截图、安装步骤图等无长期参考价值的内容。

筛选策略:

  1. 用 API 视觉模型逐张验证(可调用兼容 OpenAI API 的 VLM)

    # 调用视觉 API 识别图片内容
    $b64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes($path))
    $body = @{
    model = "qwen3.5-9b-uncensored-nothink"  # 非推理模型,content 直接出结果
    messages = @(@{ role = "user"; content = @(
    @{ type = "text"; text = "图中内容是什么?用一句话回答" }
    @{ type = "image_url"; image_url = @{ url = "data:image/png;base64,$b64" } }
    )})
    max_tokens = 100
    }
    $r = Invoke-RestMethod -Uri "https://api.example.com/v1/chat/completions" ...
    $r.choices[0].message.content
    
  2. 只保留以下类型图片

    • 寄存器位域图(Register bit-field diagram)
    • 外设框图(Peripheral block diagram)
    • 时序图(Timing diagram)
    • 电路原理图(Schematic)
    • 协议帧格式图(Protocol frame format)
  3. 删除以下类型

    • IDE 安装/配置截图(Keil, CubeMX, VS Code)
    • 项目创建步骤截图
    • 驱动安装截图
    • 内存映射表(Memory map)
    • 2x2 像素小图标
  4. 重命名image1.pngrcc_register_description.png


3. 笔记架构设计

3.1 目录结构

raw/{source-category}/
  {topic}/                          # 每个主题一个目录
    01-第一篇章.md
    02-第二篇章.md
    assets/                         # 该主题的图片资源
      gpio_pin_structure.png
      usart_block.png

3.2 笔记粒度

粒度 适用场景 示例
单篇完整笔记 内容单一的文档 01-环境搭建与工程模板.md
分篇笔记 内容多的文档,按外设拆分 02-GPIO详解.md ~ 17-FSMC与LCD显示.md

3.3 多源融合策略

当有多个教程源(寄存器教程 + 标准库教程 + HAL 教程)时:

# 在每个笔记中按"三层代码"结构组织
## 寄存器方式(尚硅谷风格)
~~~c
// 裸地址操作 → 结构体宏定义
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
~~~

## 标准库方式(江协科技风格)
~~~c
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
~~~

## HAL 库方式
~~~c
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
~~~

4. 讲解正文撰写规范

4.1 每个外设笔记应包含

  1. 基本概念:该外设是什么、有什么用
  2. 工作原理:结合框图/时序图讲解
  3. 寄存器详解:关键寄存器位域说明(表格形式)
  4. 代码实战:三层代码 + 逐行注释
  5. 核心函数速查:表格汇总

4.2 位操作注释规范

寄存器操作的每行代码必须标注操作符含义:

REG |= BITMASK;       // |= 按位或: 保持其他位不变,只将目标位置1
REG &= ~BITMASK;      // &= ~ 按位与+取反: 保留其他位,只将目标位清0
REG ^= BITMASK;       // ^= 按位异或: 翻转目标位
x << N;               // << 左移N位
~x;                   // ~ 按位取反
REG & BITMASK         // & 按位与: 测试特定位是否为1
while (条件);          // 轮询等待硬件标志位

示例:

// 使能 GPIOD 时钟(APB2ENR 寄存器第 5 位置 1)
RCC->APB2ENR |= RCC_APB2ENR_IOPDEN;   // |= 按位或: 保持其他时钟位不变
                                        // 只将 IOPDEN(IOPD 时钟使能位) 置 1

// 配置 PD13 为推挽输出 50MHz
GPIOD->CRH &= ~GPIO_CRH_CNF13;        // &= ~ 按位与+取反: 清除 CNF13 位域
GPIOD->CRH |= GPIO_CRH_MODE13;        // |= 按位或: 设置 MODE13=11 (50MHz)
                                        // MODE[1:0]=11 + CNF[1:0]=00
                                        // = 推挽输出、最高速度

5. 图片管理

5.1 获取图片

# pandoc 提取
pandoc source.docx --extract-media=./media -o output.md

# 或手动复制(如果已有图片文件)
Copy-Item source/*.png assets/

5.2 大图压缩后再传 API

问题:pandoc 提取的 PNG 经常 >200KB(最大可达 1.7MB),直接 base64 传入视觉 API 会导致超时(connection timeout 或空响应)。

解决:先压缩到宽度 800px、质量 80%,体积可缩小 10~50 倍。

# 压缩图片到 800px 宽、质量 80%,存入 temp
Add-Type -AssemblyName System.Drawing

function Compress-Image {
  param($srcPath, $destPath, $maxWidth = 800, $quality = 80)
  $img = [System.Drawing.Image]::FromFile($srcPath)
  $ratio = [Math]::Min(1.0, $maxWidth / $img.Width)
  $w = [int]($img.Width * $ratio)
  $h = [int]($img.Height * $ratio)
  $bmp = New-Object System.Drawing.Bitmap($w, $h)
  $g = [System.Drawing.Graphics]::FromImage($bmp)
  $g.DrawImage($img, 0, 0, $w, $h)
  $g.Dispose()
  $encParams = New-Object System.Drawing.Imaging.EncoderParameters(1)
  $encParams.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter(
    [System.Drawing.Imaging.Encoder]::Quality, [int64]$quality)
  $codec = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() |
    Where-Object { $_.MimeType -eq 'image/jpeg' }
  $bmp.Save($destPath, $codec, $encParams)
  $bmp.Dispose(); $img.Dispose()
}

# 使用示例:压缩原图后传给 API 验证
Compress-Image "原始大图.png" "C:\temp\压缩小图.jpg" 800 80

5.3 验证与筛选

压缩后调用视觉 API 验证每张图片是否与其文件名匹配:

function Test-Img {
  param($path, $question)
  # 大图先压缩
  if ((Get-Item $path).Length -gt 150KB) {
    $compressed = Join-Path $env:TEMP "tmp_$(Get-Random).jpg"
    Compress-Image $path $compressed 800 80
    $sendPath = $compressed
  } else {
    $sendPath = $path
  }
  $b64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes($sendPath))
  $body = @{ model = "qwen3.5-9b-uncensored-nothink"
    messages = @(@{ role = "user"; content = @(
      @{ type = "text"; text = $question }
      @{ type = "image_url"; image_url = @{ url = "data:image/jpeg;base64,$b64" } }
    )})
    max_tokens = 60 } | ConvertTo-Json -Depth 10
  $r = Invoke-RestMethod -Uri "https://api.1808366.xyz/v1/chat/completions" ...
  if ($compressed) { Remove-Item $compressed -Force }
  return $r.choices[0].message.content
}

foreach ($f in $allImages) {
  $result = Test-Img $f "图中内容是什么?一句话回答"
  if ($result -match "超时|空|null") { Write-Warning "$f 仍需手动检查" }
  Write-Host "$f => $result"
}

5.4 常见图片尺寸参考

图片宽度 高度 文件大小 典型内容 是否需要压缩
960×154 窄长 ~43KB 寄存器位域图
700×250 适中 ~14KB 小结构图
2500×1500 ~260KB 完整框图
1200×1700 ~400KB 波形图
1800×1600 ~1.7MB 复杂框图 必须压缩

5.5 命名约定

  • 全部小写英文
  • 蛇形命名(snake_case)
  • 前缀表示所属:{外设}_{内容}.png
  • 如:gpio_pin_structure.png, usart_block_diagram.png, i2c_start_stop.png

5.6 引用

在笔记中使用相对路径引用:

![GPIO 引脚结构图](assets/gpio_pin_structure.png)
*来源:STM32 参考手册*

6. 仓库提交规范

6.1 提交类型

前缀 场景
ingest 导入新资料 + 同步更新 wiki
wiki 纯知识页整理(不伴随导入)
raw 仅涉及原始资料资产,不改 wiki
lint 知识库健康检查与修复
docs 仓库说明文档与协作规则更新

6.2 每次 ingest 必须

  1. 创建或更新 wiki/index.md
  2. 追加 wiki/log.md
  3. 最终提交使用 ingest: 简短摘要

6.3 每次操作后

git add .
git commit -m "<类型>: <摘要>"

7. 大文件与图片处理策略

7.1 仓库 vs Temp

位置 用途
assets/ 最终选定的高质量图片(精选后≤50张)
C:\Users\<你>\AppData\Local\Temp\opencode\ 原始提取的全部图片(按需保留)

7.2 不提交的文件

  • EMF 格式图片(矢量图,Markdown 不直接支持)
  • IDE 安装/配置截图
  • 2x2 像素小图标
  • 超过 1MB 的非必要大图

8. 代码整合规范

8.1 核心原则

不要把整个代码项目复制到笔记中。而是:

  1. freertos_demo.c(或 main.c)提取核心示例
  2. 只保留关键代码段,删除重复的模板代码(任务配置、启动调度器等重复部分只保留一次)
  3. 每段代码必须有通俗解释(可以举生活中的例子)
  4. 复杂概念必须配通俗类比,确保小白能看懂

8.2 代码项目组织

原始代码项目(文件夹)整体复制到 code/ 子目录,笔记中通过相对路径引用:

raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/
├── code/
│   ├── 09_消息队列/          ← 完整工程代码
│   ├── 10_二值信号量/
│   └── ...
├── 07-消息队列与队列集.md    ← 只嵌入核心代码段
└── 08-信号量与互斥信号量.md

8.3 嵌入式代码注意事项

  1. 统一用 vTaskDelay() 而不是 HAL_Delay()(主动让出 CPU)
  2. portMAX_DELAY 表示"无限等待"
  3. 每个重要 API 函数旁标注通俗解释注释
  4. 需要 #include 的头文件要写清楚
  5. 关键配置项(configUSE_XXX)要说明含义

9. 完整工作流速查

flowchart TD
    A[拿到源文档 DOCX/PDF/网页] --> B[pandoc 转 MD + 提取图片]
    B --> C[阅读 MD 理解教学结构与风格]
    C --> D[设计笔记架构<br/>拆分外设/概念]
    D --> E[通读配套代码]
    E --> F[提取核心代码段<br/>删除重复模板]
    F --> G[撰写讲解正文<br/>代码 + 通俗解释]
    G --> H[API 视觉模型验证图片]
    H --> I[精选+重命名图片到 assets/]
    I --> J[整体复制代码项目到 code/]

    J --> K[创建 raw/ 学习笔记]

    K --> L[从 raw 笔记提炼 wiki 知识页]
    L --> M[更新 wiki/index.md + log.md]
    M --> N[git commit<br/>ingest/raw/wiki]

10. 注意事项

  1. 不要覆盖原始文档raw/ 目录只读不改
  2. 不要全部图片都提交 — 精选有用的,其余放 temp
  3. 不要猜测图片内容 — 用 API 视觉模型验证
  4. 不要省略位操作注释 — 每行 |=&=~<< 都要解释
  5. 不要混用提交意图 — 一次提交只做一件事
  6. 不要直接复制整个代码项目 — 只提取核心代码段嵌入笔记
  7. 每个复杂概念都要有通俗类比 — 用生活中的例子解释,确保小白能懂
  8. 先 raw 再 wiki — 所有原始资料先进 raw/ 的对应分类,再提炼到 wiki/