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

把 AI 当工具人:我在自动化项目里用 LLM 干的 6 件事
很多人用 AI 聊天、写代码、问问题。
但我觉得 AI 最实用的场景是:当成一个随叫随到的文本处理工具。
不是对话,而是调用。输入一段文本,输出一个结构化结果。就像 grep、sed、jq 一样,只不过它能处理自然语言。
这篇讲我在自动化项目里用 AI 干的 6 件事,以及一个统一的调用方式。
核心设计:Deterministic Core + AI Assist
在决定用不用 AI 之前,我先问自己一个问题:
这件事能用正则/规则穷举吗?
- 能 → 用纯逻辑,更稳定
- 不能 → 用 AI,更灵活
适合 AI:提取、分类、改写、总结、翻译、归因
适合纯逻辑:计算、校验、文件操作、数据库事务、鉴权
原则是:规则能搞定的不用 AI,AI 负责模糊的语义部分。
6 个实际应用场景
1. RSS 日报:批量摘要 + 翻译
每天抓 90 多个 RSS 源,英文文章居多。AI 做两件事:
- 把英文标题翻译成中文
- 用 1-2 句话总结核心观点
const prompt = `对于每篇文章:
1. 将英文标题翻译成简洁的中文
2. 用1-2句中文总结核心观点
技术术语保持英文原文。
返回 JSON 数组:[{index, titleZh, summary}]`;
每 5 篇一批,3 路并发,90 篇文章 30 秒跑完。
2. 链接抓取:双语对照摘要
看到一篇英文文章想保存,但不想存原文(太长)。AI 做三件事:
- 判断源语言
- 生成中文摘要
- 如果是英文,输出逐段双语对照
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 解析容错
请创建完整代码。