关于 ai-integration
ai-integration 是面向应用开发者的 AI 集成技能,涵盖从聊天与流式响应到 RAG、向量检索和工具调用的实现,并提供安全、测试与验证指导。
主要功能
- 01指导选择 AI 提供方与 SDK
- 02构建聊天界面和流式响应
- 03实现 RAG、嵌入与向量检索
- 04添加工具调用、限流与安全措施
- 05提供测试和集成验证流程
适用场景
- 01为应用加入 LLM 聊天功能
- 02构建文档检索问答流程
- 03集成外部函数调用能力
- 04检查 AI 集成的安全与成本控制
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mgd34msu/ goodvibes-plugin --skill ai-integration安装后在 Claude Code 中输入/ai-integration确认已加载。
附带文件references/ai-patterns.mdscripts/validate-ai-integration.sh
详细介绍
资源
scripts/
validate-ai-integration.sh
references/
ai-patterns.md
AI 集成实施
本技能将指导你将 AI 和大模型能力集成到应用中,从基础聊天界面到复杂的 RAG 工作流和函数调用。它利用 GoodVibes 精准工具和项目分析,助你实现可用于生产环境的 AI 功能。
何时使用此技能
在需要以下操作时使用此技能:
- 使用大模型提供商实现聊天界面
- 添加流式响应功能
- 构建 RAG(检索增强生成)工作流
- 集成嵌入和向量搜索
- 实现工具/函数调用模式
- 连接 OpenAI、Anthropic 或本地模型
- 处理 AI API 速率限制和错误恢复
工作流
按以下顺序进行 AI 集成:
1. 发现现有 AI 基础设施
在实现 AI 功能之前,先了解当前情况:
detect_stack:
project_root: "."
categories: ["ai", "llm"]
这可以识别:
- 使用中的 AI SDK(Vercel AI SDK、LangChain、LlamaIndex)
- 大模型提供商(OpenAI、Anthropic、Cohere)
- 向量数据库(Pinecone、pgvector、Weaviate)
- 现有聊天或补全端点
- 嵌入生成模式
检查项目记忆中的 AI 决策:
precision_read:
files:
- path: ".goodvibes/memory/decisions.json"
- path: ".goodvibes/memory/patterns.json"
verbosity: minimal
查找:
- 提供商选择(“为保证质量,使用 OpenAI GPT-4”)
- 成本优化模式(“将嵌入缓存 24 小时”)
- 流式传输偏好(“聊天 UI 始终使用流式传输”)
- 已知问题(“Anthropic 在 Claude Opus 上的速率限制”)
搜索现有 AI 模式:
precision_grep:
queries:
- id: openai-usage
pattern: "import.*openai|from 'openai'"
glob: "**/*.{ts,tsx,js,jsx}"
- id: streaming-endpoints
pattern: "stream|StreamingTextResponse|toDataStreamResponse"
glob: "**/*.{ts,tsx}"
- id: embeddings
pattern: "embed|embedding|vector"
glob: "**/*.{ts,tsx}"
output:
format: files_only
2. 选择提供商
根据需求选择合适的 AI 提供商和 SDK。
参见:references/ai-patterns.md,了解提供商对比。
关键决策因素:
| 需求 | 建议 |
|---|---|
| 最佳模型质量 | OpenAI GPT-4 或 Anthropic Claude Opus |
| 最快响应 | OpenAI GPT-4o 或 Anthropic Claude Haiku |
| 经济实惠 | Anthropic Claude Haiku 或 GPT-4o-mini |
| 本地/隐私 | 使用 Ollama 搭配 Llama 3 或 Mistral |
| 函数调用 | OpenAI(支持最佳)或 Anthropic |
| 长上下文 | Anthropic Claude(200K tokens) |
| React 集成 | Vercel AI SDK |
| 复杂工作流 | LangChain 或 LlamaIndex |
安装依赖:
precision_exec:
commands:
- cmd: "npm install ai @ai-sdk/openai @ai-sdk/anthropic zod"
expect:
exit_code: 0
verbosity: minimal
3. 配置 API 密钥
通过环境变量安全地管理 API 密钥。
检查 .env.example 中的文档:
precision_read:
files:
- path: ".env.example"
verbosity: minimal
添加所需的环境变量:
precision_edit:
operations:
- file: ".env.example"
edits:
- action: append
content: |
# AI Provider API Keys
OPENAI_API_KEY=your_openai_api_key_here
ANTHROPIC_API_KEY=sk-ant-...
# Optional: Model configuration
AI_MODEL=gpt-4o # or gpt-4o-mini, claude-3-5-sonnet-20241022, etc.
AI_TEMPERATURE=0.7
AI_MAX_TOKENS=4096
verbosity: minimal
验证不存在硬编码的密钥:
precision_grep:
queries:
- id: hardcoded-keys
pattern: "sk-[a-zA-Z0-9]{20,}"
glob: "**/*.{ts,tsx,js,jsx}"
output:
format: count_only
预期数量:0。如果发现密钥,请立即将其移至环境变量中。
4. 实现聊天界面
使用 Vercel AI SDK 模式创建聊天端点和 UI。
创建 API 路由:
precision_write:
files:
- path: "src/app/api/chat/route.ts"
mode: fail_if_exists
content: |
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
export const runtime = 'edge'; // Optional: Edge runtime for low-latency responses. Remove if using Node-only modules (ws, fs, etc.)
// Note: Import zod at the top of the file
// import { z } from 'zod';
export async function POST(req: Request) {
// Validate input with Zod (shown here, omitted in later examples for brevity)
const RequestSchema = z.object({
messages: z.array(z.object({
role: z.enum(['user', 'assistant', 'system']),
content: z.string().max(10000),
})),
});
const body = RequestSchema.safeParse(await req.json());
if (!body.success) {
return new Response('Invalid request', { status: 400 });
}
const { messages } = body.data;
const result = streamText({
model: openai('gpt-4o'),
messages,
temperature: 0.7,
maxTokens: 4096,
});
return result.toDataStreamResponse();
}
verbosity: minimal
创建聊天 UI 组件:
precision_write:
files:
- path: "src/components/chat.tsx"
mode: fail_if_exists
content: |
'use client';
import { useChat } from 'ai/react';
export function Chat() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat();
return (
<div className="flex flex-col h-screen">
<div className="flex-1 overflow-y-auto p-4 space-y-4">
{messages.map((m) => (
<div key={m.id} className={`flex ${m.role === 'user' ? 'justify-end' : 'justify-start'}`}>
<div className={`max-w-md px-4 py-2 rounded-lg ${
m.role === 'user' ? 'bg-blue-500 text-white' : 'bg-gray-200'
}`}>
{m.content}
</div>
</div>
))}
{isLoading && <div className="text-gray-500">Thinking...</div>}
</div>
<form onSubmit={handleSubmit} className="border-t p-4">
<input
value={input}
onChange={handleInputChange}
placeholder="Type a message..."
className="w-full px-4 py-2 border rounded-lg"
disabled={isLoading}
/>
</form>
</div>
);
}
verbosity: minimal
验证实现:
precision_exec:
commands:
- cmd: "npm run typecheck"
expect:
exit_code: 0
verbosity: minimal
5. 实现流式响应
通过逐个 token 的流式传输优化聊天体验。
Vercel AI SDK 内置了流式传输功能,通过 streamText() 和 useChat() 实现。上面的模式已使用流式传输。
对于自定义流式传输实现:
precision_write:
files:
- path: "src/lib/streaming.ts"
mode: fail_if_exists
content: |
import OpenAI from 'openai';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
export async function streamCompletion(prompt: string) {
const stream = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: prompt }],
stream: true,
});
const encoder = new TextEncoder();
return new ReadableStream({
async start(controller) {
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
if (content) {
controller.enqueue(encoder.encode(content));
}
}
controller.close();
},
});
}
verbosity: minimal
服务器发送事件(SSE)替代方案:
precision_write:
files:
- path: "src/app/api/stream/route.ts"
mode: fail_if_exists
content: |
import OpenAI from 'openai';
export const runtime = 'edge'; // Optional: Edge runtime for low-latency responses. Remove if using Node-only modules (ws, fs, etc.)
export async function POST(req: Request) {
// Add Zod validation as shown in first API route example
const { prompt } = await req.json();
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const stream = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: prompt }],
stream: true,
});
const encoder = new TextEncoder();
return new Response(
new ReadableStream({
async start(controller) {
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
if (content) {
controller.enqueue(encoder.encode(`data: ${JSON.stringify({ content })}\n\n`));
}
}
controller.enqueue(encoder.encode('data: [DONE]\n\n'));
controller.close();
},
}),
{
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
},
}
);
}
verbosity: minimal
6. 构建 RAG 工作流
实现文档导入、分块、嵌入和检索。
步骤 6.1:导入文档
precision_write:
files:
- path: "src/lib/rag/ingestion.ts"
mode: fail_if_exists
content: |
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
export async function chunkDocument(text: string, metadata: Record<string, unknown> = {}) {
const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 1000,
chunkOverlap: 200,
separators: ['\n\n', '\n', ' ', ''],
});
const chunks = await splitter.createDocuments([text], [metadata]);
return chunks.map((chunk, index) => ({
content: chunk.pageContent,
metadata: { ...chunk.metadata, chunk_index: index },
}));
}
verbosity: minimal
步骤 6.2:生成嵌入
precision_write:
files:
- path: "src/lib/rag/embeddings.ts"
mode: fail_if_exists
content: |
import { embed } from 'ai';
import { openai } from '@ai-sdk/openai';
export async function generateEmbedding(text: string): Promise<number[]> {
const { embedding } = await embed({
model: openai.embedding('text-embedding-3-small'),
value: text,
});
return embedding;
}
export async function generateEmbeddings(texts: string[]): Promise<number[][]> {
return Promise.all(texts.map(generateEmbedding));
}
verbosity: minimal
步骤 6.3:向量存储(Pinecone 示例)
precision_write:
files:
- path: "src/lib/rag/vector-store.ts"
mode: fail_if_exists
content: |
import { Pinecone } from '@pinecone-database/pinecone';
import { generateEmbedding } from './embeddings';
// Validate env vars at startup (example shown here, subsequent ! usage for brevity)
const apiKey = process.env.PINECONE_API_KEY;
if (!apiKey) throw new Error('PINECONE_API_KEY is required');
const pinecone = new Pinecone({ apiKey });
const index = pinecone.index('documents');
export async function storeDocument(id: string, text: string, metadata: Record<string, unknown>) {
const embedding = await generateEmbedding(text);
await index.upsert([{
id,
values: embedding,
metadata: { text, ...metadata },
}]);
}
export async function searchSimilar(query: string, topK: number = 5) {
const queryEmbedding = await generateEmbedding(query);
const results = await index.query({
vector: queryEmbedding,
topK,
includeMetadata: true,
});
return results.matches || [];
}
verbosity: minimal
步骤 6.4:RAG 补全端点
precision_write:
files:
- path: "src/app/api/rag/route.ts"
mode: fail_if_exists
content: |
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
import { searchSimilar } from '@/lib/rag/vector-store';
export const runtime = 'edge'; // Optional: Edge runtime for low-latency responses. Remove if using Node-only modules (ws, fs, etc.)
export async function POST(req: Request) {
// Add Zod validation as shown in first API route example
const { messages } = await req.json();
const lastMessage = messages[messages.length - 1];
// Retrieve relevant context
const context = await searchSimilar(lastMessage.content, 3);
const contextText = context
.map((match) => match.metadata?.text || '')
.join('\n\n');
// Augment prompt with context
const augmentedMessages = [
{
role: 'system',
content: `You are a helpful assistant. Use the following context to answer the user's question:\n\n${contextText}`,
},
...messages,
];
const result = streamText({
model: openai('gpt-4o'),
messages: augmentedMessages,
});
return result.toDataStreamResponse();
}
verbosity: minimal
7. 实现向量搜索
配置向量数据库以进行语义搜索。
提供商对比:
参见:references/ai-patterns.md,了解向量数据库对比。
Pinecone(托管):
precision_exec:
commands:
- cmd: "npm install @pinecone-database/pinecone"
expect:
exit_code: 0
verbosity: minimal
pgvector(PostgreSQL 扩展):
precision_write:
files:
- path: "src/lib/vector/pgvector.ts"
mode: fail_if_exists
content: |
import { sql } from 'drizzle-orm';
import { db } from '@/lib/db';
export async function enablePgvector() {
await db.execute(sql`CREATE EXTENSION IF NOT EXISTS vector`);
}
export async function searchSimilar(embedding: number[], limit: number = 5) {
return db.execute(sql`
SELECT id, content, metadata, 1 - (embedding <=> ${embedding}::vector) AS similarity
FROM documents
ORDER BY embedding <=> ${embedding}::vector
LIMIT ${limit}
`);
}
verbosity: minimal
Weaviate(混合搜索):
precision_write:
files:
- path: "src/lib/vector/weaviate.ts"
mode: fail_if_exists
content: |
import weaviate, { WeaviateClient } from 'weaviate-ts-client';
const client: WeaviateClient = weaviate.client({
scheme: 'https',
host: process.env.WEAVIATE_HOST!,
apiKey: { apiKey: process.env.WEAVIATE_API_KEY! },
});
export async function hybridSearch(query: string, limit: number = 5) {
return client.graphql
.get()
.withClassName('Document')
.withHybrid({ query, alpha: 0.5 })
.withFields('content metadata _additional { score }')
.withLimit(limit)
.do();
}
verbosity: minimal
8. 实现工具/函数调用
启用大模型调用外部函数和工具。
使用 Zod 模式定义工具:
precision_write:
files:
- path: "src/lib/ai/tools.ts"
mode: fail_if_exists
content: |
import { z } from 'zod';
import { tool } from 'ai';
export const weatherTool = tool({
description: 'Get the current weather for a location',
parameters: z.object({
location: z.string().describe('City name or zip code'),
unit: z.enum(['celsius', 'fahrenheit']).default('celsius'),
}),
execute: async ({ location, unit }) => {
// Call weather API using URL constructor for safe param encoding
const url = new URL('https://api.weather.com/v1/current');
url.searchParams.set('location', location);
url.searchParams.set('unit', unit);
const response = await fetch(url);
return response.json();
},
});
export const calculatorTool = tool({
description: 'Perform mathematical calculations',
parameters: z.object({
expression: z.string().describe('Mathematical expression to evaluate'),
}),
execute: async ({ expression }) => {
// Safe eval using mathjs
try {
const { evaluate } = await import('mathjs');
const result = evaluate(expression);
return { result };
} catch (error) {
return { error: 'Invalid expression' };
}
},
});
verbosity: minimal
在补全中使用工具:
precision_write:
files:
- path: "src/app/api/chat-tools/route.ts"
mode: fail_if_exists
content: |
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
import { weatherTool, calculatorTool } from '@/lib/ai/tools';
export const runtime = 'edge'; // Optional: Edge runtime for low-latency responses. Remove if using Node-only modules (ws, fs, etc.)
export async function POST(req: Request) {
// Add Zod validation as shown in first API route example
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4o'),
messages,
tools: {
weather: weatherTool,
calculator: calculatorTool,
},
maxSteps: 5, // Allow multi-step tool use
});
return result.toDataStreamResponse();
}
verbosity: minimal
在 UI 中处理工具结果:
precision_edit:
operations:
- file: "src/components/chat.tsx"
edits:
- action: replace
old_text: "export function Chat() {"
new_text: |
export function Chat() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
onToolCall: ({ toolCall }) => {
// Use proper logger in production: logger.info('Tool called:', toolCall.toolName, toolCall.args);
console.log('Tool called:', toolCall.toolName, toolCall.args);
},
});
verbosity: minimal
9. 添加安全防护和速率限制
防止滥用并控制成本。
速率限制中间件:
precision_write:
files:
- path: "src/middleware/rate-limit.ts"
mode: fail_if_exists
content: |
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';
const redis = new Redis({
url: process.env.UPSTASH_REDIS_REST_URL!,
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
});
export const ratelimit = new Ratelimit({
redis,
limiter: Ratelimit.slidingWindow(10, '60 s'), // 10 requests per minute
analytics: true,
});
export async function checkRateLimit(identifier: string) {
const { success, limit, remaining, reset } = await ratelimit.limit(identifier);
if (!success) {
throw new Error(`Rate limit exceeded. Try again in ${Math.ceil((reset - Date.now()) / 1000)}s`);
}
return { limit, remaining, reset };
}
verbosity: minimal
为路由应用速率限制:
precision_edit:
operations:
- file: "src/app/api/chat/route.ts"
edits:
- action: replace
old_text: "export async function POST(req: Request) {"
new_text: |
import { checkRateLimit } from '@/middleware/rate-limit';
export async function POST(req: Request) {
const ip = req.headers.get('x-forwarded-for') || 'anonymous';
try {
await checkRateLimit(ip);
} catch (error) {
const message = error instanceof Error ? error.message : 'Rate limit exceeded';
return new Response(message, { status: 429 });
}
verbosity: minimal
防止提示词注入:
precision_write:
files:
- path: "src/lib/ai/safety.ts"
mode: fail_if_exists
content: |
// Detect prompt injection attempts
export function detectInjection(input: string): boolean {
const injectionPatterns = [
/ignore (previous|above|all) (instructions|prompts)/i,
/you are now/i,
/new instructions:/i,
/system: /i,
/<\w+>/, // HTML-like tags
];
return injectionPatterns.some((pattern) => pattern.test(input));
}
// Sanitize user input
export function sanitizeInput(input: string): string {
// Remove potential injection markers
return input
.replace(/[<>]/g, '')
.replace(/system:/gi, '')
.trim()
.slice(0, 10000); // Limit length
}
verbosity: minimal
内容过滤:
precision_write:
files:
- path: "src/lib/ai/moderation.ts"
mode: fail_if_exists
content: |
import OpenAI from 'openai';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
export async function moderateContent(text: string) {
const moderation = await openai.moderations.create({ input: text });
const result = moderation.results[0];
if (result.flagged) {
const categories = Object.entries(result.categories)
.filter(([_, flagged]) => flagged)
.map(([category]) => category);
throw new Error(`Content flagged for: ${categories.join(', ')}`);
}
return result;
}
verbosity: minimal
10. 测试 AI 集成
实施确定性测试策略。
模拟大模型响应:
precision_write:
files:
- path: "src/lib/ai/__tests__/chat.test.ts"
mode: fail_if_exists
content: |
import { describe, it, expect, vi } from 'vitest';
import { streamText } from 'ai';
vi.mock('ai', () => ({
streamText: vi.fn(),
}));
describe('Chat API', () => {
it('should return streamed response', async () => {
const mockStream = {
toDataStreamResponse: () => new Response('mocked response'),
};
vi.mocked(streamText).mockResolvedValue(mockStream);
import { POST } from '@/app/api/chat/route';
const req = new Request('http://localhost/api/chat', {
method: 'POST',
body: JSON.stringify({ messages: [{ role: 'user', content: 'Hello' }] }),
});
const response = await POST(req);
expect(response.ok).toBe(true);
});
});
verbosity: minimal
使用确定性种子进行测试:
precision_write:
files:
- path: "src/lib/ai/__tests__/embeddings.test.ts"
mode: fail_if_exists
content: |
import { describe, it, expect } from 'vitest';
import { generateEmbedding } from '../embeddings';
describe('Embeddings', () => {
// Mock AI SDK to prevent real API calls in tests
vi.mock('ai', () => ({
embed: vi.fn().mockResolvedValue({ embedding: new Array(1536).fill(0.1) })
}));
it('should generate consistent embeddings', async () => {
const text = 'Hello world';
const embedding1 = await generateEmbedding(text);
const embedding2 = await generateEmbedding(text);
// Embeddings should be very similar (cosine similarity)
const similarity = cosineSimilarity(embedding1, embedding2);
expect(similarity).toBeGreaterThan(0.99);
});
});
function cosineSimilarity(a: number[], b: number[]): number {
const dotProduct = a.reduce((sum, val, i) => sum + val * b[i], 0);
const magnitudeA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
const magnitudeB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
return dotProduct / (magnitudeA * magnitudeB);
}
verbosity: minimal
成本跟踪:
precision_write:
files:
- path: "src/lib/ai/cost-tracker.ts"
mode: fail_if_exists
content: |
import { Redis } from '@upstash/redis';
const redis = new Redis({
url: process.env.UPSTASH_REDIS_REST_URL!,
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
});
const MODEL_COSTS = {
// Prices as of early 2026 -- verify current rates at provider sites
'gpt-4o': { input: 0.0025, output: 0.01 }, // per 1K tokens
'gpt-4o-mini': { input: 0.00015, output: 0.0006 },
'claude-opus-4': { input: 0.015, output: 0.075 },
'claude-sonnet-4-5': { input: 0.003, output: 0.015 },
'claude-haiku-4-5': { input: 0.0008, output: 0.004 },
};
export async function trackUsage(
model: keyof typeof MODEL_COSTS,
inputTokens: number,
outputTokens: number
) {
const costs = MODEL_COSTS[model];
const cost = (inputTokens / 1000) * costs.input + (outputTokens / 1000) * costs.output;
const today = new Date().toISOString().split('T')[0];
const key = `ai:cost:${today}`;
await redis.incrbyfloat(key, cost);
await redis.expire(key, 86400 * 90); // 90 days retention
return cost;
}
export async function getTodayCost(): Promise<number> {
const today = new Date().toISOString().split('T')[0];
const cost = await redis.get<number>(`ai:cost:${today}`);
return cost || 0;
}
verbosity: minimal
11. 验证
运行验证脚本,确保满足所有 AI 集成要求:
precision_exec:
commands:
- cmd: "bash plugins/goodvibes/skills/outcome/ai-integration/scripts/validate-ai-integration.sh ."
expect:
exit_code: 0
verbosity: standard
验证脚本会检查:
- 是否已安装 AI SDK 或大模型库
- 是否在 .env.example 中记录了 API 密钥
- 是否存在流式传输端点
- 源代码中是否存在硬编码的 API 密钥
- 是否已配置速率限制
- AI 调用周围是否进行了错误处理
- 是否采用了 Token/成本跟踪模式
部署前请修复所有违规项。
最佳实践
错误处理
- 始终使用 try/catch 块封装 AI 调用
- 使用指数退避处理速率限制
- 为外部 API 实施熔断器
- 记录错误时不要暴露 API 密钥
性能
- 缓存频繁访问内容的嵌入向量
- 对较长的补全请求使用流式传输
- 尽可能批量生成嵌入向量
- 实施请求去重
成本管理
- 为每个请求设置最大 Token 限制
- 跟踪每日/月度支出
- 简单任务使用成本较低的模型
- 适时缓存补全结果
安全
- 切勿将 API 密钥提交到源代码管理中
- 按用户/IP 实施速率限制
- 发送给大模型前清理用户输入
- 对用户生成的提示词使用内容审核
- 验证工具执行结果
监控
- 跟踪 Token 用量和成本
- 监控响应延迟
- 记录成功和失败的请求
- 对异常支出模式发出警报
常见陷阱
- 忘记使用流式传输:聊天界面始终使用流式传输,以改善用户体验
- 忽略速率限制:实施退避和重试逻辑
- 硬编码提示词:使用模板系统以便于维护
- 不对文档分块:RAG 需要对大型文档进行分块
- 跳过成本跟踪:AI 成本可能迅速攀升
- 信任用户输入:始终清理并验证
- 没有错误边界:发生故障时应优雅降级
- 上下文过大:限制上下文以控制在 Token 预算内
其他资源
详细的提供商比较和架构模式,请参阅 references/ai-patterns.md。