LLMPatterns llm-patterns

这是一个专注于利用大型语言模型(LLM)进行逻辑操作的技能,涵盖了从项目结构设计到LLM客户端模式、提示模式、测试策略以及成本和性能跟踪等多个方面,旨在提高AI应用的效率和准确性。

AI应用 0 次安装 0 次浏览 更新于 3/5/2026

LLM Patterns 技能

加载与: base.md + [语言].md

针对以AI为先导的应用,LLMs处理逻辑操作。


核心原则

LLM用于逻辑,代码用于管道。

使用LLMs进行:

  • 分类、提取、总结
  • 使用自然语言推理进行决策制定
  • 内容生成和转换
  • 在代码中会显得脆弱的复杂条件逻辑

使用传统代码进行:

  • 数据验证(Zod/Pydantic)
  • API路由和HTTP处理
  • 数据库操作
  • 认证/授权
  • 编排和错误处理

项目结构

project/
├── src/
│   ├── core/
│   │   ├── prompts/           # 提示模板
│   │   │   ├── classify.ts
│   │   │   └── extract.ts
│   │   ├── llm/               # LLM客户端和工具
│   │   │   ├── client.ts      # LLM客户端包装器
│   │   │   ├── schemas.ts     # 响应模式(Zod)
│   │   │   └── index.ts
│   │   └── services/          # 使用LLM的业务逻辑
│   ├── infra/
│   └── ...
├── tests/
│   ├── unit/
│   ├── integration/
│   └── llm/                   # LLM特定测试
│       ├── fixtures/          # 用于确定性测试的保存响应
│       ├── evals/             # 评估测试套件
│       └── mocks/             # 模拟LLM响应
└── _project_specs/
    └── prompts/               # 提示规范

LLM客户端模式

类型化的LLM包装器

// core/llm/client.ts
import Anthropic from '@anthropic-ai/sdk';
import { z } from 'zod';

const client = new Anthropic();

interface LLMCallOptions<T> {
  prompt: string;
  schema: z.ZodSchema<T>;
  model?: string;
  maxTokens?: number;
}

export async function llmCall<T>({
  prompt,
  schema,
  model = 'claude-sonnet-4-20250514',
  maxTokens = 1024,
}: LLMCallOptions<T>): Promise<T> {
  const response = await client.messages.create({
    model,
    max_tokens: maxTokens,
    messages: [{ role: 'user', content: prompt }],
  });

  const text = response.content[0].type === 'text'
    ? response.content[0].text
    : '';

  // 解析并验证响应
  const parsed = JSON.parse(text);
  return schema.parse(parsed);
}

结构化输出

// core/llm/schemas.ts
import { z } from 'zod';

export const ClassificationSchema = z.object({
  category: z.enum(['support', 'sales', 'feedback', 'other']),
  confidence: z.number().min(0).max(1),
  reasoning: z.string(),
});

export type Classification = z.infer<typeof ClassificationSchema>;

提示模式

模板函数

// core/prompts/classify.ts
export function classifyTicketPrompt(ticket: string): string {
  return `将此支持票分类为以下类别之一:
- support: 技术问题或帮助请求
- sales: 价格、计划或购买咨询
- feedback: 建议或投诉
- other: 其他任何事情

以JSON格式响应:
{
  "category": "...",
  "confidence": 0.0-1.0,
  "reasoning": "简短解释"
}

票:
${ticket}`;
}

提示版本控制

// core/prompts/index.ts
export const PROMPTS = {
  classify: {
    v1: classifyTicketPromptV1,
    v2: classifyTicketPromptV2,  // 提高准确性
    current: classifyTicketPromptV2,
  },
} as const;

测试LLM调用

1. 使用模拟的单元测试(快速,确定性)

// tests/llm/mocks/classify.mock.ts
export const mockClassifyResponse = {
  category: 'support',
  confidence: 0.95,
  reasoning: '用户正在寻求登录帮助',
};

// tests/unit/services/ticket.test.ts
import { classifyTicket } from '../../../src/core/services/ticket';
import { mockClassifyResponse } from '../../llm/mocks/classify.mock';

// 模拟LLM客户端
vi.mock('../../../src/core/llm/client', () => ({
  llmCall: vi.fn().mockResolvedValue(mockClassifyResponse),
}));

describe('classifyTicket', () => {
  it('返回票的分类', async () => {
    const result = await classifyTicket('我无法登录');

    expect(result.category).toBe('support');
    expect(result.confidence).toBeGreaterThan(0.9);
  });
});

2. 固定装置测试(确定性,测试解析)

// tests/llm/fixtures/classify.fixtures.json
{
  "support_ticket": {
    "input": "我无法重置我的密码",
    "expected_category": "support",
    "raw_response": "{\"category\":\"support\",\"confidence\":0.98,\"reasoning\":\"密码重置是支持问题\"}"
  }
}

// tests/llm/classify.fixture.test.ts
import fixtures from './fixtures/classify.fixtures.json';
import { ClassificationSchema } from '../../src/core/llm/schemas';

describe('分类响应解析', () => {
  Object.entries(fixtures).forEach(([name, fixture]) => {
    it(`正确解析 ${name}`), () => {
      const parsed = JSON.parse(fixture.raw_response);
      const result = ClassificationSchema.parse(parsed);

      expect(result.category).toBe(fixture.expected_category);
    });
  });
});

3. 评估测试(慢速,在CI夜间运行)

// tests/llm/evals/classify.eval.test.ts
import { classifyTicket } from '../../../src/core/services/ticket';

const TEST_CASES = [
  { input: '专业计划的费用是多少?', expected: 'sales' },
  { input: '点击保存时应用程序崩溃', expected: 'support' },
  { input: '你们应该添加暗色模式', expected: 'feedback' },
  { input: '东京现在几点?', expected: 'other' },
];

describe('分类准确性(评估)', () => {
  // 在常规CI中跳过,夜间运行
  const runEvals = process.env.RUN_LLM_EVALS === 'true';

  it.skipIf(!runEvals)('在测试集上实现>90%的准确性', async () => {
    let correct = 0;

    for (const testCase of TEST_CASES) {
      const result = await classifyTicket(testCase.input);
      if (result.category === testCase.expected) correct++;
    }

    const accuracy = correct / TEST_CASES.length;
    expect(accuracy).toBeGreaterThan(0.9);
  }, 60000); // 60s超时LLM调用
});

GitHub Actions用于LLM测试

# .github/workflows/quality.yml(添加到现有)
jobs:
  quality:
    # ...现有步骤...

    - name: 运行测试(带有LLM模拟)
      run: npm run test:coverage

  llm-evals:
    runs-on: ubuntu-latest
    # 夜间运行或按需运行
    if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
    steps:
      - uses: actions/checkout@v4

      - name: 设置Node
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: 安装依赖项
        run: npm ci

      - name: 运行LLM评估
        run: npm run test:evals
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          RUN_LLM_EVALS: 'true'

成本和性能跟踪

// core/llm/client.ts - 添加跟踪
interface LLMMetrics {
  model: string;
  inputTokens: number;
  outputTokens: number;
  latencyMs: number;
  cost: number;
}

export async function llmCallWithMetrics<T>(
  options: LLMCallOptions<T>
): Promise<{ result: T; metrics: LLMMetrics }> {
  const start = Date.now();

  const response = await client.messages.create({...});

  const metrics: LLMMetrics = {
    model: options.model,
    inputTokens: response.usage.input_tokens,
    outputTokens: response.usage.output_tokens,
    latencyMs: Date.now() - start,
    cost: calculateCost(response.usage, options.model),
  };

  // 记录或发送到监控
  console.log('[LLM]', metrics);

  return { result: parsed, metrics };
}

LLM反模式

  • ❌ 硬编码提示在业务逻辑中 - 使用提示模板
  • ❌ LLM响应上没有模式验证 - 始终使用Zod
  • ❌ CI中使用实时LLM调用进行测试 - 单元测试使用模拟
  • ❌ 没有成本跟踪 - 监控令牌使用情况
  • ❌ 忽略延迟 - LLM调用很慢,设计为异步
  • ❌ LLM故障没有备用方案 - 处理超时和错误
  • ❌ 提示没有版本控制 - 跟踪提示更改
  • ❌ 没有评估套件 - 随时间测量准确性
  • ❌ 使用LLM进行确定性逻辑 - 使用代码进行验证、认证、数学
  • ❌ 巨大的单一提示 - 组合更小的专注提示