@flink-app/ fake-llm-适应器
Flink AI框架的假LLM适配器 - 适合演示,开发,和测试而不需要真正的LLM API连接.
概览
这个 FakeLLMAdapter 执行 LLMAdapter 用智能工具调用决策,接口和生成与背景相关的响应。 与简单的嘲讽不同,它:
- 明智地决定何时调用工具 根据用户信息和可用工具
- 生成现实的工具输入 通过分析工具计划并从用户信件中提取值
- 提供与背景相关的文本答复 使用自定义模板
- 模拟现实的符号使用 测试成本/性能设想方案
- 支持可复制随机性 通过播种进行确定性测试
- 可配置的行为模式 从文本到工具重
安装
pnpm add @flink-app/fake-llm-adapter
快速启动
import { FlinkApp } from "@flink-app/flink";
import { FakeLLMAdapter } from "@flink-app/fake-llm-adapter";
const app = new FlinkApp({
ai: {
llms: {
fake: new FakeLLMAdapter()
}
}
});
用假适应器创建代理
import { createAgent } from "@flink-app/flink/ai";
import { FakeLLMAdapter } from "@flink-app/fake-llm-adapter";
const weatherAgent = createAgent({
llm: new FakeLLMAdapter({
mode: "tool-heavy", // Prefer calling tools
preferredTools: ["get_weather"], // Prioritize weather tool
}),
instructions: "You are a helpful weather assistant.",
tools: [
{
name: "get_weather",
description: "Get weather for a location",
input_schema: {
type: "object",
properties: {
city: { type: "string" },
unit: { type: "string", enum: ["celsius", "fahrenheit"] }
},
required: ["city"]
}
}
]
});
const result = await weatherAgent.execute("What's the weather in Stockholm?");
// Likely calls get_weather tool with { city: "Stockholm", unit: "celsius" }
配置
export interface FakeLLMAdapterConfig {
// Response behavior
mode?: AdapterMode; // "balanced" | "tool-heavy" | "text-only" | "random"
// Tool calling configuration
toolCallProbability?: number; // 0.0 to 1.0 (default: 0.3)
maxToolCallsPerTurn?: number; // default: 3
// Randomness control
seed?: number; // For reproducible responses
// Timing simulation
responseDelay?: number; // milliseconds (default: 0)
// Response customization
templates?: ResponseTemplate[];
personality?: PersonalityPreset; // "professional" | "friendly" | "technical" | "concise" | "verbose"
// Token simulation
tokenMultiplier?: number; // Adjust token counts (default: 1.0)
// Advanced options
debugMode?: boolean; // Log decision-making process
preferredTools?: string[]; // Prioritize these tool names
}
结构化输出和工具选择
当代理请求时 structuredOutput,适配器用一个 JSON 文本块来回答,而不是用发音或工具调用,所以 result.structured 在没有 API 键的测试中工作 。 默认对象由schema的属性生成(用于工具输入的同一生成器:字符串,数字,布林斯,数组,从消息中取出城市名和数字). 用 structuredResponse数字 :
// Fixed reply
new FakeLLMAdapter({ structuredResponse: { approved: true, reason: "Looks good" } });
// Per request
new FakeLLMAdapter({
structuredResponse: ({ name, schema, message }) =>
name === "verdict" ? { approved: message.includes("good"), reason: "scripted" } : {},
});
toolChoice 也很荣幸: "none" 从不叫工具, "required" 总是叫一个,和 { type: "tool", name } 完全调用这个工具.
模式解释
balanced (违约)
文本响应和工具呼叫的混合. 根据上下文调整调用工具的概率为30%.
使用时 : 一般开发和测试
new FakeLLMAdapter({ mode: "balanced" })
tool-heavy
强烈喜欢工具呼叫. 呼叫工具的概率为70%.
使用时 : 测试调用流量的工具, 演示显示工具
new FakeLLMAdapter({ mode: "tool-heavy" })
text-only
从不叫工具 总是返回文本回复.
使用时 : 测试纯对口流量, 无工具交互的 UI
new FakeLLMAdapter({ mode: "text-only" })
random
完全无法预测的行为.
使用时 : 压力测试代理错误处理
new FakeLLMAdapter({ mode: "random" })
背景辅助工具调用
适配器根据:
- 动作动词 在用户消息中(“获取”、“查找”、“搜索”、“计算”等) +20%的概率
- 工具名称匹配 信件内容 + 25% 概率
- 温度设置 < 0.5 = +10%(更具决定性)
- 首选工具 配置 + 优先选择
示例:智能工具选择
const adapter = new FakeLLMAdapter({
mode: "balanced",
preferredTools: ["search_database"]
});
// "Find user John" → Likely calls tool (has "find" action verb)
// "What's the weather?" → May or may not call tool (depends on available tools)
// "Hello!" → Unlikely to call tool (no action verbs)
自定义响应模板
定义特定域的响应 :
const adapter = new FakeLLMAdapter({
templates: [
{
pattern: /order|purchase|buy/i,
responses: [
"I'll help you with that order.",
"Let me process your purchase.",
"I can assist with buying that."
]
},
{
pattern: /cancel|refund/i,
responses: [
"I'll help you with the cancellation.",
"Let me process that refund request."
],
toolTrigger: "process_refund" // Prefer this tool when pattern matches
}
]
});
可复制种子测试
在测试中使用种子进行确定性输出 :
import { FakeLLMAdapter } from "@flink-app/fake-llm-adapter";
describe("Agent tests", () => {
it("should handle weather query consistently", async () => {
const adapter1 = new FakeLLMAdapter({ seed: 42 });
const adapter2 = new FakeLLMAdapter({ seed: 42 });
const agent1 = createAgent({ llm: adapter1, tools: weatherTools });
const agent2 = createAgent({ llm: adapter2, tools: weatherTools });
const result1 = await agent1.execute("Weather in Paris?");
const result2 = await agent2.execute("Weather in Paris?");
// Same seed = same behavior
expect(result1).toEqual(result2);
});
});
模拟网络延迟
const adapter = new FakeLLMAdapter({
responseDelay: 500 // 500ms delay per response
});
// Useful for:
// - Testing loading states in UI
// - Simulating production latency
// - Demo scenarios with realistic pacing
Token 使用模拟
const adapter = new FakeLLMAdapter({
tokenMultiplier: 2.0 // Double all token counts
});
// Useful for:
// - Testing token limit handling
// - Cost estimation in development
// - Performance testing with large contexts
个性预设
// Professional (default)
new FakeLLMAdapter({ personality: "professional" })
// → "I can assist with that request."
// Friendly
new FakeLLMAdapter({ personality: "friendly" })
// → "Sure thing! Let me help you out!"
// Technical
new FakeLLMAdapter({ personality: "technical" })
// → "Processing query. Executing tool call."
// Concise
new FakeLLMAdapter({ personality: "concise" })
// → "Processing."
// Verbose
new FakeLLMAdapter({ personality: "verbose" })
// → "I understand your request and I'll be happy to assist you with that. Let me process..."
调试模式
使伐木能够理解决策:
const adapter = new FakeLLMAdapter({
debugMode: true
});
// Logs:
// [FakeLLMAdapter] Processing message: What's the weather?
// [FakeLLMAdapter] Generated tool calls: [{ name: "get_weather", ... }]
工具输入生成
适配器通过:
- 从信件中提取: 搜索城市、 数字、 用户消息中的日期
- 基于 Schema 的默认: 根据属性类型生成适当的值
- 智能字段匹配: 确认常见的字段名称(电子邮件、城市、名称、日期)
// Tool schema:
{
name: "create_user",
input_schema: {
properties: {
email: { type: "string" },
city: { type: "string" },
age: { type: "number" }
}
}
}
// Message: "Create user in Stockholm"
// Generated input:
{
email: "[email protected]", // Smart default for email field
city: "Stockholm", // Extracted from message
age: 42 // Random number
}
假图像模型
FakeImageModel 执行 Flink 的 ImageModel 用于测试和演示的接口:每个请求的图像都是有效的1x1 PNG,并记录通话.
import { FakeImageModel } from "@flink-app/fake-llm-adapter";
const images = new FakeImageModel({
// all optional
capabilities: { mask: false, maxImagesPerCall: 1 },
image: { bytes: myPng, mediaType: "image/png" },
usage: { inputTokens: 10, outputTokens: 20 },
responseDelay: 50,
// error: new ImageModelError("provider", "down", { retryable: true }),
// emptyResult: true,
});
const app = new FlinkApp<AppCtx>({ ai: { images: { default: images } } });
// after exercising a handler
expect(images.calls[0].method).toBe("edit");
expect(images.calls[0].params.prompt).toBe("make it night");
images.reset();
已经过去了 imageModelContractSpec() 从 @flink-app/test-utils就像供应商的模型 见 图像模型指南。 。 。 .
比较:假的适应器对模拟LLLMAdapter
| 特性 | FakeLLMAdapter | mockLLMAdapter (试管) |
|---|---|---|
| 目的 | 开发和演示 | 仅测试单位 |
| 工具调用 | 智能, 上下文意识 | 总是返回预定义的响应 |
| 回应 | 基于模板的动态 | 静态硬码 |
| 配置 | 高度可配置模式 | 最小配置 |
| 可复制性 | 种子随机性 | 完全决定性 |
| 使用大小写 | 运行没有 API 的应用程序 | 在测试中模仿 |
拇指规则:
- 使用
FakeLLMAdapter用于运行您的应用程序、演示和开发 - 使用
mockLLMAdapter用于您需要准确、可预测的产出的单位测试
使用大小写
1. 没有API键的发展
// Develop AI features without spending money or setting up API keys
const app = new FlinkApp({
ai: {
llms: {
default: new FakeLLMAdapter()
}
}
});
2. 演示和演讲
// Reliable demos that don't depend on external APIs
const demoAdapter = new FakeLLMAdapter({
mode: "tool-heavy",
responseDelay: 800, // Realistic pacing
seed: 12345 // Same demo every time
});
3. 测试工具调用逻辑
// Test your agent's tool handling without real LLM
const testAdapter = new FakeLLMAdapter({
toolCallProbability: 1.0, // Always call tools
maxToolCallsPerTurn: 5
});
4. UI 发展
// Test loading states and UI behavior
const uiTestAdapter = new FakeLLMAdapter({
responseDelay: 1500,
personality: "verbose" // Longer responses to test text wrapping
});
5. 综合测试
// Consistent behavior across test runs
describe("Agent integration", () => {
const adapter = new FakeLLMAdapter({ seed: 999 });
it("should handle multi-turn conversation", async () => {
// Test logic here - same results every run
});
});
高级示例: 自定义电子商务代理
const ecommerceAdapter = new FakeLLMAdapter({
mode: "tool-heavy",
preferredTools: ["search_products", "get_order_status"],
templates: [
{
pattern: /track|status|where.*order/i,
responses: ["Let me check your order status."],
toolTrigger: "get_order_status"
},
{
pattern: /find|search|looking for/i,
responses: ["I'll search our catalog for you."],
toolTrigger: "search_products"
},
{
pattern: /return|refund/i,
responses: ["I'll help you process that return."],
toolTrigger: "process_return"
}
],
personality: "friendly",
debugMode: true
});
const agent = createAgent({
llm: ecommerceAdapter,
instructions: "You are a helpful e-commerce assistant.",
tools: [searchProducts, getOrderStatus, processReturn]
});
限制(第1阶段)
- 无流支持数字 :
stream()方法丢出错误。 使用execute()换句话说. - 简单工具输入生成: 使用高压,可能无法处理复杂的嵌入式方案
- 模板匹配: 基本正则图案,而非语义理解
未来阶段可能增加流出和更复杂的输入生成.
类型脚本
所有类型全部导出 :
import {
FakeLLMAdapter,
FakeLLMAdapterConfig,
AdapterMode,
PersonalityPreset,
ResponseTemplate
} from "@flink-app/fake-llm-adapter";
许可证
麻省理工学院
捐款
问题和企业责任 https://github.com/FrostDigital/flink-framework (中文(简体) )