我删掉了 350 行封装代码。取而代之的是这些。
“想要流式输出?SSE 我自己解析,有多难?”
难。离谱地难。我花了一个周末写了个能处理 OpenAI 格式的流式解析器,结果 Anthropic 改了他们的格式,我那所谓的“通用”解析器立刻就只通用于一家供应商了。
那一刻我决定不再写自定义 API 封装器。六个月后,伴随着一堆被删掉的代码,就是下面这 7 个把我样板代码替换掉的库。每个案例都遵循同一个模式:一个我反复手搓的问题、一个用几行代码就能解决它的库、以及 README 里通常不会写的“实话实说的局限”。

1. LiteLLM:一个接口打通所有 LLM 供应商
问题:你想对比 GPT-4、Claude、Llama。结果你要写三套客户端配置、三套响应解析、三套错误处理。
from litellm import completion
# Same interface. Any provider.
response = completion(
model="gpt-4",
messages=[{"role": "user", "content": "Explain RAG in one paragraph"}]
)
# Switch to Claude? Change one string.
response = completion(
model="claude-3-5-sonnet-20241022",
messages=[{"role": "user", "content": "Explain RAG in one paragraph"}]
)
我上个季度做了次成本对比:在相同工作负载下,GPT-4、Claude Sonnet、Llama 3 70B 之间的差额是 $847/月。没有 LiteLLM,要完成这次测试我至少得花一周时间重构。
替代了:3 套独立 SDK 集成 + 一张成本跟踪表。
实话实说的局限:当某家供应商改 API,你得等 LiteLLM 跟进更新。对关键生产业务,一些团队仍然倾向直连官方 SDK。
2. Instructor:结构化输出,真的能用
问题:你让 LLM 输出 JSON。结果给你一个被 markdown 反引号包起来的 JSON,或者多了个字段的 JSON,或者一个看起来像 JSON 但结尾多了逗号的字符串。
import instructor
from pydantic import BaseModel, Field
from openai import OpenAI
client = instructor.from_openai(OpenAI())
class ToolRecommendation(BaseModel):
name: str
category: str = Field(description="e.g. 'orchestration', 'observability'")
maturity: str = Field(description="'production-ready' or 'experimental'")
best_for: list[str]
avoid_when: list[str]
tools = client.chat.completions.create(
model="gpt-4",
messages=[{
"role": "user",
"content": "Recommend 3 Python tools for building RAG pipelines"
}],
response_model=list[ToolRecommendation]
)
# Validated list of structured objects. No parsing. No edge cases.
用 Instructor 之前,我有个 parse_llm_json(),里面处理了十二种边界情况。上线后一周还会翻一次车。像上面这种“嵌套提取”(经过校验的复杂对象列表),就是 Instructor 碾压的场景。试试用正则 + json.loads() 去做同样的事吧。
替代了:150 行带手动校验的 JSON 解析函数。
实话实说的局限:会增加时延。当模型的首次输出未通过校验时,Instructor 有时需要重试。高吞吐场景要评估这部分开销。
3. MarkItDown:把任何文档变成 LLM 友好的文本
问题:你的 RAG(检索增强生成)流水线需要摄取 PDF、Word、PowerPoint、Excel。于是你为 PDF 装 pdfminer,为 Word 装 python-docx,为 PPT 装 python-pptx,为表格装 pandas。四个库,四条解析管线,四套边界情况。
from markitdown import MarkItDown
md = MarkItDown()
# PDF? Done.
result = md.convert("quarterly_report.pdf")
# PowerPoint? Also done.
result = md.convert("client_deck.pptx")
# Excel? You get the idea.
result = md.convert("budget_2025.xlsx")
print(result.text_content) # Clean Markdown, every time
这是 Microsoft 做的(GitHub star 86K)。它能把标题、表格、列表保留成 Markdown。我做过一个内部知识库的文档问答系统,当时摄取管线占了 40% 的代码量。要是有 MarkItDown,几行就能搞定。
替代了:用 4 个解析库拼出来的自定义抽取管线。
实话实说的局限:PDF 仅提取文本层。扫描类图片无 OCR 会返回空。PDF 表格抽取也不总稳定,涉及财务或重表格内容的要核验。
4. FastMCP:构建 MCP 服务器,用分钟计,不用天
5. FastMCP:告别繁琐的 MCP 服务器实现
问题:Model Context Protocol (MCP) 正成为 LLM 访问外部工具与数据的标准,但从零实现一个合规的 MCP 服务器,需要编写大量传输处理、模式定义和协议样板代码,实现负担很重。
from fastmcp import FastMCP
mcp = FastMCP("My Data Tools")
@mcp.tool()
def search_database(query: str, limit: int = 10) -> list[dict]:
"""Search the product database."""
return db.search(query, limit=limit)
@mcp.tool()
def get_user_profile(user_id: str) -> dict:
"""Fetch user profile by ID."""
return db.get_user(user_id)
mcp.run()
这就是一个完整可用的 MCP 服务器。仅用两个工具装饰器,即可直接连接 Claude Desktop 或任何 MCP 客户端。其装饰器写法与 FastAPI 风格相似,让开发者倍感熟悉。使用 FastMCP,为一个内部搜索索引构建工具服务原型,大约只需 20 分钟,而此前纯手动的 MCP 实现已写了 200 多行,且尚未完善传输处理。
替代了:200+ 行的协议样板代码。
局限:FastMCP 项目仍处于早期发展阶段。如果你的技术栈不涉及 MCP,则此库不适用。此外,你仍需仔细评估通过工具暴露了哪些数据和能力。
6. PydanticAI:类型安全的 Agent 交互
问题:当你希望与 LLM 进行结构化、类型安全的交互时,引入一整套 Agent 框架往往会带来依赖膨胀、晦涩的抽象,以及调试深层框架调用时的复杂性问题。
from pydantic_ai import Agent
from pydantic import BaseModel
class CodeReview(BaseModel):
issues: list[str]
severity: str
suggested_fix: str
confidence: float
reviewer = Agent(
"openai:gpt-4",
result_type=CodeReview,
system_prompt="You review Python code for bugs and anti-patterns."
)
result = reviewer.run_sync("def connect(url): return requests.get(url, verify=False)")
print(result.data.issues)
# ['SSL verification disabled', 'No timeout specified', 'No error handling']
PydanticAI 定位在“直接调用 API”与“重量级框架”之间的平衡点。它提供了类型化输入/输出、工具定义和依赖注入等功能。该库由 Pydantic 团队打造,其校验库支撑着 OpenAI SDK、LangChain 等众多流行工具。对于比单次 Instructor 调用更复杂,但又无需完整 LangGraph 工作流的结构化任务,PydanticAI 是一个理想选择。
替代了:无类型的提示词链与手动响应校验。
局限:PydanticAI 中的 “Agent” 更侧重于“结构化的 LLM 交互”,而非“自主的多步推理”。复杂的多 Agent 持久化工作流,仍是 LangGraph 或 CrewAI 等框架更擅长的领域。
7. tiktoken:精准预测 API 调用成本
问题:在构建提示词时拼接动态上下文,常常难以预判是否会超出模型的上下文窗口,或将一次低成本调用误写成高成本请求。
import tiktoken
enc = tiktoken.encoding_for_model("gpt-4")
prompt = "Your very long prompt with lots of context..."
tokens = enc.encode(prompt)
print(f"Token count: {len(tokens)}")
# Estimate cost before calling
input_cost = len(tokens) * 0.00003 # GPT-4 input pricing
print(f"Estimated input cost: ${input_cost:.4f}")
开始使用 tiktoken 的契机,是一次递归函数将提示词拼接至 45,000 个 token,导致单次 API 调用花费了 1.35 美元,而该函数每小时被调用 200 次。现在,任何包含动态上下文的 LLM 调用前,都会先进行 token 计数检查。
替代了:盲目的 API 调用与意外的账单。
局限:tiktoken 仅适用于 OpenAI 模型。对于 Anthropic 模型,需使用其官方计数 API。LiteLLM 的 token_counter() 函数封装了多家 tokenizer,但准确度可能浮动。此外,像示例中那样硬编码单价,价格更新时容易导致估算错误。
8. Pydantic Evals:系统化的提示词评估
问题:修改 system prompt 后,如何客观评估其效果?手动测试几个看似不错的例子就上线,往往会在未覆盖的案例中出现回归问题。
from pydantic_evals import Case, Dataset
dataset = Dataset(
cases=[
Case(
name="basic_extraction",
inputs="Extract the company name: Apple announced new MacBooks",
expected_output="Apple",
),
Case(
name="ambiguous_input",
inputs="The orange company released a new phone",
expected_output="Orange",
),
]
)
report = dataset.evaluate(your_extraction_function)
report.print()
Pydantic Evals 允许你定义包含输入和期望输出的测试用例集,并自动评估你的提示词函数或链。它能生成包含通过率、失败案例等详细信息的报告,将提示词评估从“凭感觉”转变为可重复、可量化的过程。
替代了:基于少数样例的主观手动测试。
局限:构建一个全面且有代表性的测试数据集本身需要投入精力。它主要用于功能正确性评估,对于评估输出内容的“质量”或“风格”等更主观的维度,仍需结合人工判断。
我用血与泪学到的
我曾抵触评测框架好几个月,总认为“我的提示词挺好,手动测试就行”。直到有一次,我为了优化一个边角问题修改了 system prompt,结果它悄悄搞崩了另外三个我没检查的场景。这时我才意识到系统化评测的必要性。
Pydantic Evals 是我见过最简单的评测框架。你只需要定义好测试用例,运行一遍,就能拿到清晰的通过/失败报告。正是因为它足够简单,你才会真的去用它——而这正是关键所在。
它替代的是那种“看着还行”的、不可靠的人工测试,以及上线后才会暴露的意外问题。
当然,实话实说,它也有局限:这个库还很新,API 仍在演进。如果你需要构建大规模的生产评测流水线,Braintrust 或 Langfuse 这类工具提供了更深度的集成。但如果你的需求仅仅是“我改了提示词,它还好使吗?”,那么 Pydantic Evals 就刚刚好。
一年前,我可能会告诉你:最好的技术栈就是你自己造的,因为它完全可控、零依赖。
我错了。我后来花在维护各种 API 封装器上的时间,比打造产品本身还要多。上面提到的这 7 个库有一个共同的哲学:只做一件事,把它做好,然后让开。它们都不要求你“信仰注入”般地接入某个庞大框架;它们都能帮你删掉那些你本就不该写的重复代码。
最好的 AI 工程栈,不是最花哨、最复杂的那一个,而是能让你把东西按时交付的那一个。道理就这么简单。
关注“鲸栖”小程序,掌握最新AI资讯
本文来自网络搜集,不代表鲸林向海立场,如有侵权,联系删除。转载请注明出处:https://www.itsolotime.com/archives/22029
