@flink-app/fake-llm-adapter

中文文档
2.0.0-alpha.134发布于 2026/11/07MITTypeScriptCommonJS零依赖近 30 天下载 2831

Fake LLM adapter for Flink AI framework - perfect for demos and testing

原始使用文档
文档目录33 节
  1. Overview
  2. Installation
  3. Quick Start
  4. Creating an Agent with Fake Adapter
  5. Configuration
  6. Structured Output and Tool Choice
  7. Modes Explained
  8. balanced (Default)
  9. tool-heavy
  10. text-only
  11. random
  12. Context-Aware Tool Calling
  13. Example: Intelligent Tool Selection
  14. Custom Response Templates
  15. Reproducible Testing with Seeds
  16. Simulating Network Delays
  17. Token Usage Simulation
  18. Personality Presets
  19. Debug Mode
  20. Tool Input Generation
  21. Fake Image Model
  22. Comparison: fake-llm-adapter vs mockLLMAdapter
  23. Use Cases
  24. 1. Development Without API Keys
  25. 2. Demos and Presentations
  26. 3. Testing Tool Calling Logic
  27. 4. UI Development
  28. 5. Integration Tests
  29. Advanced Example: Custom E-commerce Agent
  30. Limitations (Phase 1)
  31. TypeScript Types
  32. License
  33. Contributing

@flink-app/fake-llm-adapter

A fake LLM adapter for the Flink AI framework - perfect for demos, development, and testing without requiring real LLM API connections.

Overview

The FakeLLMAdapter implements the LLMAdapter interface and generates contextually relevant responses with intelligent tool calling decisions. Unlike simple mocks, it:

  • Intelligently decides when to call tools based on user messages and available tools
  • Generates realistic tool inputs by analyzing tool schemas and extracting values from user messages
  • Provides contextually relevant text responses using customizable templates
  • Simulates realistic token usage for testing cost/performance scenarios
  • Supports reproducible randomness via seeding for deterministic testing
  • Configurable behavior modes from text-only to tool-heavy

Installation

pnpm add @flink-app/fake-llm-adapter

Quick Start

import { FlinkApp } from "@flink-app/flink";
import { FakeLLMAdapter } from "@flink-app/fake-llm-adapter";

const app = new FlinkApp({
  ai: {
    llms: {
      fake: new FakeLLMAdapter()
    }
  }
});

Creating an Agent with Fake Adapter

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" }

Configuration

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
}

Structured Output and Tool Choice

When an agent requests structuredOutput, the adapter replies with a single JSON text chunk instead of prose or tool calls, so result.structured works in tests without an API key. By default the object is generated from the schema's properties (the same generator used for tool inputs: strings, numbers, booleans, arrays, with city names and numbers picked up from the message). Script the reply with 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 is honoured too: "none" never calls tools, "required" always calls one, and { type: "tool", name } calls exactly that tool.

Modes Explained

balanced (Default)

Mix of text responses and tool calls. Base 30% probability of calling tools, adjusted based on context.

Use when: General development and testing

new FakeLLMAdapter({ mode: "balanced" })

tool-heavy

Strongly prefers tool calls. Base 70% probability of calling tools.

Use when: Testing tool calling flows, demos showcasing tools

new FakeLLMAdapter({ mode: "tool-heavy" })

text-only

Never calls tools. Always returns text responses.

Use when: Testing pure conversation flows, UI without tool interactions

new FakeLLMAdapter({ mode: "text-only" })

random

Completely unpredictable behavior.

Use when: Stress testing agent error handling

new FakeLLMAdapter({ mode: "random" })

Context-Aware Tool Calling

The adapter intelligently decides when to call tools based on:

  1. Action verbs in user message ("get", "find", "search", "calculate", etc.) → +20% probability
  2. Tool name matches message content → +25% probability
  3. Temperature setting < 0.5 → +10% probability (more deterministic)
  4. Preferred tools configuration → Prioritized in selection

Example: Intelligent Tool Selection

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)

Custom Response Templates

Define domain-specific responses:

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
    }
  ]
});

Reproducible Testing with Seeds

Use seeds for deterministic output in tests:

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);
  });
});

Simulating Network Delays

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 Usage Simulation

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

Personality Presets

// 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..."

Debug Mode

Enable logging to understand decision-making:

const adapter = new FakeLLMAdapter({
  debugMode: true
});

// Logs:
// [FakeLLMAdapter] Processing message: What's the weather?
// [FakeLLMAdapter] Generated tool calls: [{ name: "get_weather", ... }]

Tool Input Generation

The adapter generates realistic tool inputs by:

  1. Extracting from message: Searches for cities, numbers, dates in user message
  2. Schema-based defaults: Generates appropriate values based on property types
  3. Smart field matching: Recognizes common field names (email, city, name, date)
// 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
}

Fake Image Model

FakeImageModel implements Flink's ImageModel interface for tests and demos: every requested image is a valid 1x1 PNG, and calls are recorded.

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();

It passes imageModelContractSpec() from @flink-app/test-utils, like the provider models. See the Image Models guide.

Comparison: fake-llm-adapter vs mockLLMAdapter

FeatureFakeLLMAdaptermockLLMAdapter (test-utils)
PurposeDevelopment & demosUnit testing only
Tool callingIntelligent, context-awareAlways returns predefined responses
ResponsesDynamic, template-basedStatic, hard-coded
ConfigurationHighly configurable modesMinimal config
ReproducibilitySeeded randomnessFully deterministic
Use caseRunning app without APIsMocking in tests

Rule of thumb:

  • Use FakeLLMAdapter for running your app, demos, and development
  • Use mockLLMAdapter for unit tests where you need exact, predictable outputs

Use Cases

1. Development Without API Keys

// Develop AI features without spending money or setting up API keys
const app = new FlinkApp({
  ai: {
    llms: {
      default: new FakeLLMAdapter()
    }
  }
});

2. Demos and Presentations

// 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. Testing Tool Calling Logic

// Test your agent's tool handling without real LLM
const testAdapter = new FakeLLMAdapter({
  toolCallProbability: 1.0, // Always call tools
  maxToolCallsPerTurn: 5
});

4. UI Development

// Test loading states and UI behavior
const uiTestAdapter = new FakeLLMAdapter({
  responseDelay: 1500,
  personality: "verbose" // Longer responses to test text wrapping
});

5. Integration Tests

// 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
  });
});

Advanced Example: Custom E-commerce Agent

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]
});

Limitations (Phase 1)

  • No streaming support: stream() method throws an error. Use execute() instead.
  • Simple tool input generation: Uses heuristics, may not handle complex nested schemas
  • Template matching: Basic regex patterns, not semantic understanding

Future phases may add streaming and more sophisticated input generation.

TypeScript Types

All types are fully exported:

import {
  FakeLLMAdapter,
  FakeLLMAdapterConfig,
  AdapterMode,
  PersonalityPreset,
  ResponseTemplate
} from "@flink-app/fake-llm-adapter";

License

MIT

Contributing

Issues and PRs welcome at https://github.com/FrostDigital/flink-framework

版本与发布记录

@flink-app/fake-llm-adapter 共发布 86 个版本,首次发布于 2026/02/10;过去 12 个月发布了 86 个版本。

版本发布日期距今
2.0.0-alpha.134latest2026/11/078 天前
2.0.0-alpha.1332026/11/069 天前
2.0.0-alpha.1322026/11/0510 天前
2.0.0-alpha.1312026/10/2818 天前
2.0.0-alpha.1302026/10/2521 天前
2.0.0-alpha.1292026/10/2521 天前

关于 @flink-app/fake-llm-adapter 的常见问题

@flink-app/fake-llm-adapter 是什么?

Fake LLM adapter for Flink AI framework - perfect for demos and testing

如何安装 @flink-app/fake-llm-adapter?

在项目目录运行 npm install @flink-app/fake-llm-adapter,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@flink-app/flink(>=2.0.0-alpha.134)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@flink-app/fake-llm-adapter 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@flink-app/fake-llm-adapter 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@flink-app/fake-llm-adapter 可以商用吗?

@flink-app/fake-llm-adapter 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@flink-app/fake-llm-adapter 的下载量有多少?

根据 npm 官方下载统计,@flink-app/fake-llm-adapter 在 2026/10/15 – 2026/11/13 这 30 天内被下载 2,831 次,日均约 94 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@flink-app/fake-llm-adapter 还在维护吗?

最新版本 2.0.0-alpha.134 发布于 2026/11/07(8 天前);至今共发布 86 个版本,其中过去 12 个月发布了 86 个;首次发布于 2026/02/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。