Share

外观
风格

把 AI 当工具人:我在自动化项目里用 LLM 干的 6 件事

2026年2月8日 · 专栏

封面图

把 AI 当工具人:我在自动化项目里用 LLM 干的 6 件事

很多人用 AI 聊天、写代码、问问题。

但我觉得 AI 最实用的场景是:当成一个随叫随到的文本处理工具

不是对话,而是调用。输入一段文本,输出一个结构化结果。就像 grepsedjq 一样,只不过它能处理自然语言。

这篇讲我在自动化项目里用 AI 干的 6 件事,以及一个统一的调用方式。


核心设计:Deterministic Core + AI Assist

在决定用不用 AI 之前,我先问自己一个问题:

这件事能用正则/规则穷举吗?

  • 能 → 用纯逻辑,更稳定
  • 不能 → 用 AI,更灵活
适合 AI:提取、分类、改写、总结、翻译、归因
适合纯逻辑:计算、校验、文件操作、数据库事务、鉴权

原则是:规则能搞定的不用 AI,AI 负责模糊的语义部分


6 个实际应用场景

1. RSS 日报:批量摘要 + 翻译

每天抓 90 多个 RSS 源,英文文章居多。AI 做两件事:

  1. 把英文标题翻译成中文
  2. 用 1-2 句话总结核心观点
const prompt = `对于每篇文章:
1. 将英文标题翻译成简洁的中文
2. 用1-2句中文总结核心观点
技术术语保持英文原文。
返回 JSON 数组:[{index, titleZh, summary}]`;

每 5 篇一批,3 路并发,90 篇文章 30 秒跑完。


2. 链接抓取:双语对照摘要

看到一篇英文文章想保存,但不想存原文(太长)。AI 做三件事:

  1. 判断源语言
  2. 生成中文摘要
  3. 如果是英文,输出逐段双语对照
interface AiDigest {
  source_language: "en" | "zh" | "mixed";
  title_zh: string;
  summary_zh: string;
  keywords: string[];
  bilingual_blocks: { en: string; zh: string }[];
}

最后自动落盘到 Obsidian,带回链到 Daily Note。


3. Git Commit Message 生成

写完代码不想写 commit message。扔 diff 给 AI:

bun tools/git-ai-commit-msg.ts --staged

输出:

feat(rss): add parallel summarization with 3 workers

- 新增 summarizer 模块,支持批量并行摘要
- 每 5 篇一批,3 路并发,提升处理速度
- 增加 JSON 解析容错,避免模型输出格式不稳定导致崩溃

Conventional Commit 格式,标题英文,描述中文。


4. 敏感信息脱敏

发布文章前,需要把 API Key、IP 地址、密码等敏感信息替换掉。

两层机制:

第一层:规则脱敏(Deterministic)

// 匹配 sk-xxx、Bearer xxx、公网 IP 等
const rules = [
  { label: "api-key", regex: /sk-[a-zA-Z0-9]{20,}/g, replace: "sk-..." },
  { label: "public-ip", regex: /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g, ... },
];

第二层:AI 兜底

规则漏掉的,让 AI 再扫一遍:

const prompt = `检查以下内容是否还有敏感信息:
- API Key / Token
- 密码
- 私有域名或 IP
如有,返回 JSON 数组说明位置和建议替换`;

发布时自动执行,不用手动检查。


5. 模型选型:按任务自动选

不同任务对模型要求不同:

任务类型 需要的能力 模型选择
提取/分类/摘要/翻译 速度快 fast(gemini-flash)
常规问答 平衡 balanced(gpt-4o)
规划/代码/推理 质量高 strong(gpt-4.5)

封装成一个函数,调用时指定任务类型,自动选模型:

const result = await chat(messages, { task: "summarize" }); // 自动用 fast
const result = await chat(messages, { task: "coding" });    // 自动用 strong

省心,不用每次想该用哪个模型。


6. JSON 输出 + 容错解析

AI 返回 JSON 经常出问题:

  • 有时候包了 ```json 代码块
  • 有时候前后有多余解释
  • 有时候格式不完整

统一的解析逻辑:

function extractJsonBlock(content: string): string {
  // 先找 ```json 代码块
  const fenced = content.match(/```(?:json)?\s*([\s\S]*?)\s*```/i);
  if (fenced?.[1]) return fenced[1].trim();

  // 再找裸 {} 或 []
  const objectMatch = content.match(/\{[\s\S]*\}/);
  if (objectMatch) return objectMatch[0];

  const arrayMatch = content.match(/\[[\s\S]*\]/);
  if (arrayMatch) return arrayMatch[0];

  return content;
}

配合 chatJson<T>() 泛型函数,调用时指定返回类型,自动解析 + 类型校验。


统一调用入口

所有 AI 调用都走一个 client:

import { chat, chatJson } from "./lib/ai-client";

// 普通调用
const result = await chat(messages, { task: "summarize" });

// JSON 调用(自动解析)
const { data } = await chatJson<{ title: string; tags: string[] }>(
  messages,
  { task: "extract" }
);

配置通过环境变量:

AI_BASE_URL=https://ai.chen.rs/v1
AI_API_KEY=sk-...
AI_MODEL_FAST=gemini-2.5-flash-lite
AI_MODEL_STRONG=gpt5.2

统一入口的好处:

  • 换模型只改环境变量
  • 统一超时、重试、日志
  • 方便统计 token 用量

工程要求

用 AI 写自动化脚本,有几个坑要注意:

1. AI 输出必须有兜底

模型可能超时、返回空、格式错误。每个调用都要有 fallback:

const result = summaries.get(url) || { titleZh: "", summary: "(解析失败)" };

2. 写入前做结构校验

拿到 JSON 后先验证字段存在、类型正确,再写入数据库或文件。

3. 涉及外部动作先确认

如果 AI 输出会触发发消息、改线上配置、公开发布等动作,必须先人工确认。


我踩过的坑

1. JSON 格式不稳定

同一个 prompt,模型有时候返回纯 JSON,有时候加解释。解决:用正则提取 [...]{...}

2. 批量太大 token 爆了

一次扔 50 篇文章进去,超 token 限制。解决:分批处理,每批 5-10 篇。

3. 快模型质量差

flash 模型速度快但偶尔翻译质量差。解决:关键场景用 strong,日常场景用 fast。


下一步

  • 加缓存:相同输入不重复调用,省 token
  • 加指标:统计每个任务的 token 消耗和延迟
  • 加 streaming:长输出场景用流式响应

AI 不是万能的,但在"规则难穷举"的场景,它是最省力的方案。关键是想清楚什么时候用、怎么用、出错了怎么兜底。


附录:给 AI 的复现指令

帮我搭建一个 AI 调用 client,统一管理所有 LLM API 调用。

目标:封装 OpenAI 兼容 API 调用,支持任务类型自动选模型、JSON 解析容错。

技术栈:Bun + TypeScript

项目结构:
tools/
  lib/
    ai-client.ts  -- 核心 client

功能要求:

1. 配置管理
   - 从环境变量读取:AI_BASE_URL, AI_API_KEY, AI_MODEL_FAST, AI_MODEL_BALANCED, AI_MODEL_STRONG
   - 提供默认值(除了 API Key)

2. 任务类型(AiTaskType)
   - fast 任务:extract, classify, rewrite, summarize, translate
   - strong 任务:plan, coding, reasoning
   - 其他:qa(默认 balanced)

3. 自动选模型
   - pickModel(config, task, effort) 函数
   - effort 可以是 fast/balanced/strong
   - 也可以根据 task 类型自动推断

4. chat() 函数
   - 输入:messages, options (task, effort, model, temperature, maxTokens, responseJson)
   - 输出:{ model, content, raw }
   - 支持超时控制

5. chatJson<T>() 泛型函数
   - 自动解析 JSON 响应
   - 容错:处理 ```json 代码块、裸 JSON、前后有解释的情况
   - 解析失败抛错,包含原始内容

6. JSON 提取逻辑
   - 先找 ```json 代码块
   - 再找裸 {} 或 []
   - 最后返回原文

环境变量示例:
  AI_BASE_URL=https://api.openai.com/v1
  AI_API_KEY=sk-...
  AI_MODEL_FAST=gpt-4o-mini
  AI_MODEL_BALANCED=gpt-4o
  AI_MODEL_STRONG=gpt-4.5

使用示例:
  const result = await chat(messages, { task: "summarize" });
  const { data } = await chatJson<{ title: string }>(messages, { task: "extract" });

成功标志:可以正常调用 API,自动选模型,JSON 解析容错

请创建完整代码。