Побудова перед API готова: без фізкультури brottle (Українська (Ukrainian))

Побудова перед API готова: без фізкультури brottle

Saturday, 13 December 2025

//

14 minute read

Вступ

Скільки разів вам заблокували очікування, що API сервера буде готовим, або скільки годин ви витратили на збереження крихких даних, що стають непотрібними, коли змінюються вимоги?

Ввести mostlylucid.mockllmapi - платформу, готову до виробництва, ASP. NET, яка використовує моделі Великої мови для створення реалістичних, контекстно обізнаних відповідей API на льоту. Замість підтримки фіксацій JSON, ви отримуєте розумні висміювання, які адаптуються до ваших запитів і запам' ятають стан через виклики.

Що вона підтримує: Будь- який з потрібних протоколів - REST, GraphQL, gRPC, SpectR, Server- Sent і OpenAPI. На відміну від статичних фіксацій, відповіді створюються динамічно на основі контексту вашого запиту, створення багатокрокових робочих місць і комплексних сценаріїв перевірки.

Посилання на проект

NuGet NuGet Випуск GitHub Ліцензія: Un license

Три способи, якими можна вживати його

Ви можете використовувати threelucid. mockllmapi у три способи, залежно від того, наскільки ізольованим має бути середовище dev:

  1. Пакунок ASP. NET Core NuGe - Додати до існуючих ваших проектів
  2. Інструмент Standalone CLI - Кросплатформовий виконуваний файл (звантажте з випуски)
  3. Контейнер панелі - Потрібне нульове встановлення

Можливість вбивці: контекстна пам'ять

Е-Е-Е-Е-Е-Е-Е-Е-Е-Е-Е-Е-Е-Е-Е-Е-Е-Е: Документація контексту API

Традиційний API- інтерфейс має фатальний недолік: кожен запит є незалежним. Звантажте користувача з ідентифікатором 42, а потім отримайте їх замовлення, і ви отримаєте замовлення для користувача 99. Без відповідності.

Контексти API Вирішіть це за допомогою спільної пам' яті між пов' язаними запитами:

// Request 1: Get a user
// Note: 'context' is a simple query parameter - no cookies or sessions needed
fetch('/api/users/123?context=checkout-session')
// Response: { id: 42, name: "Alice Smith", email: "alice@example.com" }

// Request 2: Get orders (same context parameter)
fetch('/api/orders?userId=42&context=checkout-session')
// Response: { userId: 42, customerName: "Alice Smith", items: [...] }
// Perfect! Same user, consistent data

LLM бачить попередні запити у тому ж контексті і створює послідовні дані. Це засіб зміни гри для декількох кроків роботи.

Можливості:

Життєвий цикл:

  • Автоматичне завершення через 15 хвилин бездіяльності (можна налаштувати)
  • Кожне з запитів оновлює таймер

Поведінка:

  • Інтелектуальне видобування полів ВСІ з відповідей

Безпека:

  • Нульова протока пам' яті - контексти вичищуються

Випадки використання:

  • Ідеально для CI/CD - між запусками немає стану

Швидкий запуск

Параметр 1: пакунок NuGet

dotnet add package mostlylucid.mockllmapi
// Program.cs
builder.Services.AddLLMockApi(builder.Configuration);
app.MapLLMockApi("/api/mock");

Варіант 2: інструмент CLI

# Download from https://github.com/scottgal/LLMApi/releases
llmock serve --port 5000

Варіант 3: Панель

Е-е-е-е-е-е-е: Довідник з впровадження Docker

git clone https://github.com/scottgal/LLMApi.git
cd LLMApi
docker compose up -d

Prerequisites: Сервер LLM

Вам потрібно один зOllama, OpenAI, або LM Studio:

# Recommended: Ollama with ministral-3:3b (ultra-fast, accurate JSON generation)
ollama pull ministral-3:3b

Див. Довідник з моделей Ollama за всі зразкові рекомендації та порівняння.

Спробуйте негайно

Після запуску зробіть свій перший запит:

curl http://localhost:5000/api/mock/users
# Response: [{"id": 1, "name": "Alice Johnson", "email": "alice@example.com"}, ...]

Тепер у вас є уявний API, який створює реальні дані за попитом.

Справжній приклад: пошук з macilid.net

Ось справжній пошуковий код з цього блогу - цей код є незмінним графічним інтерфейсом, не потрібно адаптацій для висміювання:

// typeahead.js from mostlylucid.net
export function typeahead() {
    return {
        query: '',
        results: [],
        search() {
            fetch(`/api/search/${encodeURIComponent(this.query)}`)
                .then(response => response.json())
                .then(data => { this.results = data; });
        }
    }
}

Посміхнись:

# Using CLI
llmock serve --port 5000

# Query returns contextual results
curl http://localhost:5000/api/search/markdown
# LLM generates blog posts about Markdown

curl http://localhost:5000/api/search/docker
# LLM generates blog posts about Docker

Кожна відповідь є унікальною і реалістичною, пристосовуючись до цього запиту.

Керування формами: визначте вашу схему

За межами лише створення випадкових даних, вам часто потрібен точний контроль над структурою JSON. Керування формою надає вам змогу вказати LLM саме ту структуру, яку слід створити - найпотужнішу можливість для розробки графічної оболонки.

Базова форма

# Without shape - random structure
curl http://localhost:5000/api/mock/users
# Response: { "userId": 1, "fullName": "Alice" }

# With shape - you control it
curl "http://localhost:5000/api/mock/users" \
  -H 'X-Response-Shape: {"id":0,"name":"string","email":"string"}'
# Response: { "id": 1, "name": "Alice", "email": "alice@example.com" }

Три способи визначення форми:

  1. Параметр запиту - ?shape={...}
  2. HTTP заголовок - X-Response-Shape: {...} (рекомендовано)
  3. Запитувати тіло - {"shape": {...}}

Форма з вішаннямStencils

const shape = {
  company: {
    id: 0,
    name: "string",
    employees: [{
      id: 0,
      firstName: "string",
      department: { id: 0, name: "string" },
      projects: [{ id: 0, title: "string" }]
    }]
  }
};

fetch('/api/mock/company', {
  headers: { 'X-Response-Shape': JSON.stringify(shape) }
});

Вирівнювання TypeScript

interface User {
  id: number;
  name: string;
  email: string;
}

const USER_SHAPE: Partial<User> = { id: 0, name: "", email: "" };

// Shape becomes your type definition AND mock schema!

Багатосторонні робочі потоки з контекстом

Тепер давайте поєднаємо керування формами з контекстами API для роботи зі складними, багатокроковими роботами. Пам' ятайте, що елемент пам' яті було згадано раніше? Ось як він сяє у асинхронних операціях у реальному світі.

Цей приклад служби перекладу qualsecid. net показує, як LLM зберігає стан через повний робочий потік асинхронів:

# Step 1: Start translation
curl -X POST http://localhost:5000/api/translate/start?context=translate-session \
  -d '{"language": "es", "markdown": "# Hello World"}'
# Response: { "taskId": "abc-123", "status": "processing" }

# Step 2: Check status (LLM remembers the task)
curl http://localhost:5000/api/translate/status/abc-123?context=translate-session
# Response: { "taskId": "abc-123", "status": "complete" }

# Step 3: Get result (same taskId!)
curl http://localhost:5000/api/translate/result/abc-123?context=translate-session
# Response: { "taskId": "abc-123", "translatedText": "# Hola Mundo" }

Зверніть увагу, як taskId по всему просьбе соответствуется. Контекст робить це можливим.

Beond REST: All the protocols

Поки що ми зосередилися на REST, але сучасним програмам потрібно ще щось: чи будуєте ви за допомогою GraphQL, чи втілюєте можливості реального часу за допомогою SNERR, чи працюєте з службами gRPC, у більшості випадків thumlucid.mockllmapi описано.

Підтримувані протоколи:

  • Приблизно 60 000 з них.
  • ⇩ GraphQL
  • теперь gRPC
  • бісаРunit description in lists
  • ▸ ep-Sent Times (SSE)
  • } OpenAPI / Swagger

GraphQL

А.Б.: Розділ GraphQL

curl -X POST http://localhost:5000/api/mock/graphql \
  -d '{"query": "{ users { id name email } }"}'

Запит - це форма - не потрібна окрема схема.

gRPC

Е-е-е-е-е-е-е: Підтримка gRPC

# Upload .proto file
curl -X POST http://localhost:5116/api/grpc-protos \
  --data-binary "@user_service.proto"

# Call via JSON or binary Protobuf
curl -X POST http://localhost:5116/api/grpc/userservice/UserService/GetUser \
  -d '{"user_id": 123}'

SignR Real- time

А.Б.: Посібник для демонстрацій сигналів (NewR)

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/hub/mock")
    .build();

connection.on("DataUpdate", (message) => {
    console.log(message.data); // Live generated data
});

await connection.start();
await connection.invoke("SubscribeToContext", "stock-prices");

Ідеально для створення прототипів панелі приладів.

Події, надіслані сервером (SSE) Noun, a currency

А.Б.: Режими потоку SSE

const eventSource = new EventSource('/api/mock/stream/users');
eventSource.onmessage = (event) => {
    const data = JSON.parse(event.data);
    console.log('Token:', data.chunk); // Progressive generation
};

OpenAPI / Swragger

Е-е-е-е-е-е-е: Можливості OpenAPI

# CLI: Load any OpenAPI spec
llmock serve --spec https://petstore3.swagger.io/api/v3/openapi.json

# All endpoints become live mocks automatically
curl http://localhost:5000/petstore/pet/123

Додаткові інструменти: Змішувати справжні і Mock- дані

Е-е-е-е-е-е-е: Інструменти & Дії

Іноді вам потрібен гібридний підхід - справжні дані з виробництва у поєднанні з створеними імітуючими даними. Система інструментів, які можна налаштувати, надає вам змогу називати справжні API під час створення висміювання, створюючи неймовірно реалістичні тестові сценарії.

{
  "Tools": [{
    "Name": "getUserData",
    "Type": "http",
    "HttpConfig": {
      "Endpoint": "https://api.production.com/users/{userId}",
      "Headers": { "Authorization": "Bearer ${PROD_API_KEY}" }
    }
  }]
}
curl "http://localhost:5000/api/mock/orders?useTool=getUserData&userId=123"

За допомогою висмішки можна отримувати справжні дані про користувача, а потім LLM створює замовлення за його допомогою. Надзвичайно корисно для реалістичних тестувань з гібридними та реальними роботами.

Інтеграція ядра ASP. NET

Якщо ви будуєте за допомогою ядра ASP.NET, інтеграція буде безперешкодно. змінено нульовий код на ваші служби - ви просто налаштовуєте HttpClient на глузуванні під час розробки і в реальному API у виробництві.

// Real code from mostlylucid.net
builder.Services.AddHttpClient<IMarkdownTranslatorService, MarkdownTranslatorService>(
    client => {
        var baseUrl = builder.Configuration["TranslationService:BaseUrl"]
            ?? "http://localhost:5000";  // Mock during dev
        client.BaseAddress = new Uri(baseUrl);
    }
);

appsettings.Development.json:

{
  "TranslationService": {
    "BaseUrl": "http://localhost:5000"  // Mock
  }
}

appsettings.Production.json:

{
  "TranslationService": {
    "BaseUrl": "https://api.production.com"  // Real
  }
}

Цей шаблон працює для будь- яких HttpClient у службах перекладу вашої програми, шлюзи сплат, зовнішні API, ви їх називаєте.

Коли слід це використовувати

Перш ніж ми поринемо в додаткові можливості, давайте розглянемо, коли цей інструмент має сенс для Вашого робочого процесу.

Досконало для:

  • Передбачати про створення програми до створення сервера - Припинити блокування команд сервера
  • Тестування багатокрокової обробки - Контекстна пам' ять керує складними сценаріями
  • Прототипування API - Експериментувати з формами відповіді перед виконанням
  • Автономний розвиток - Робота без мережевих залежностей
  • Тестування за сценарієм помилки - Імітувати помилки, не зриваючи виробництво
  • трубопроводи CI/CD - Немає зовнішніх залежностей означає швидше, більш надійне збирання

Не ідеальна для:

  • Виробництво середовищ - Це інструмент для розробки і тестування
  • Визначені дані - Використовуй фіксації, коли потрібна точна репродукція.
  • Контрактне тестування - Завжди перевіряти реальний API для виробничих контрактів

Тепер, коли ви знаєте, де вона підходить, давайте дослідимо додаткові можливості.

Додаткові можливості

Ці можливості не є обов' язковими - ви можете отримати величезне значення лише з основ, але якщо вам потрібен реалізм виробничого класу у масштабі, ці інструменти є тут.

Декілька серверів LLM

А.Б.: Декілька серверів LLM

# Fast for dev
curl http://localhost:5000/api/mock/users

# High quality for demos
curl "http://localhost:5000/api/mock/users?backend=quality"

# Cloud AI for production-like
curl "http://localhost:5000/api/mock/users?backend=openai"

Симуляція обмеження швидкості

А.Б.: Обмеження швидкості і пакетизація

Перевірте, як ваша програма керує обмеженнями швидкості:

{
  "EnableRateLimiting": true,
  "RateLimitDelayRange": "500-2000"
}

Помилка під час імітації

# Test 429 rate limiting
curl "http://localhost:5000/api/mock/users?error=429&errorMessage=Rate%20limit%20exceeded"

# Test 503 unavailable
curl "http://localhost:5000/api/mock/users?error=503"

Підтримує всі 4xx і 5xx- коди.

Кечування відповідей

# Generate and cache 10 variants
curl "http://localhost:5000/api/mock/users?shape={\"$cache\":10,\"id\":0,\"name\":\"string\"}"

Наступні запити отримують миттєве кешування відповідей.

Інструменти перевірки: threelucid. mockllmapi.Testing

А.Б.: threelucid. mockllmapi.Testing

А що сказати про автоматичні випробування? HttpClient зробити решту.

Встановлення

dotnet add package mostlylucid.mockllmapi.Testing

Основні прийоми користування

using mostlylucid.mockllmapi.Testing;

// Create a client with a single endpoint configuration
var client = HttpClientExtensions.CreateMockLlmClient(
    baseAddress: "http://localhost:5116",
    pathPattern: "/users",
    configure: endpoint => endpoint
        .WithShape(new { id = 0, name = "", email = "" })
        .WithCache(5)
);

// Make requests - configuration is automatically applied
var response = await client.GetAsync("/users");
var users = await response.Content.ReadFromJsonAsync<User[]>();

Декілька кінцевих точок

var client = HttpClientExtensions.CreateMockLlmClient(
    "http://localhost:5116",
    configure: handler => handler
        .ForEndpoint("/users", config => config
            .WithShape(new { id = 0, name = "", email = "" })
            .WithCache(10))
        .ForEndpoint("/posts", config => config
            .WithShape(new { id = 0, title = "", content = "", authorId = 0 })
            .WithCache(20))
        .ForEndpoint("/error", config => config
            .WithError(404, "Resource not found"))
);

// Each endpoint automatically uses its configuration
var usersResponse = await client.GetAsync("/users");
var postsResponse = await client.GetAsync("/posts");
var errorResponse = await client.GetAsync("/error"); // Returns 404

Параметри налаштування

Налаштування форми:

// Using anonymous objects
.WithShape(new { id = 0, name = "", active = true })

// Using JSON strings
.WithShape("{ \"id\": 0, \"name\": \"\", \"tags\": [] }")

// Complex nested structures
.WithShape(new
{
    user = new { id = 0, name = "" },
    posts = new[] { new { id = 0, title = "" } }
})

Симуляція помилки:

// Simple error
.WithError(404)

// With custom message
.WithError(404, "User not found")

// With details
.WithError(422, "Validation failed", "Email address is invalid")

Потік:

// Enable streaming with token-by-token output
.WithStreaming()
.WithSseMode("LlmTokens")

// Stream complete objects
.WithStreaming()
.WithSseMode("CompleteObjects")

// Stream array items individually
.WithStreaming()
.WithSseMode("ArrayItems")

Коефіцієнт залежності

Типований клієнт:

services.AddMockLlmHttpClient<IUserApiClient>(
    baseApiPath: "/api/mock",
    configure: handler => handler
        .ForEndpoint("/users", config => config
            .WithShape(new { id = 0, name = "", email = "" }))
);

Клієнт з назвою:

services.AddMockLlmHttpClient(
    name: "MockApi",
    baseApiPath: "/api/mock",
    configure: handler => handler
        .ForEndpoint("/data", config => config
            .WithShape(new { value = 0 }))
);

// Usage
var client = httpClientFactory.CreateClient("MockApi");

Приклад тестування інтеграції

[Fact]
public async Task Should_Handle_User_Creation()
{
    // Arrange
    var client = HttpClientExtensions.CreateMockLlmClient(
        "http://localhost:5116",
        "/users",
        config => config
            .WithMethod("POST")
            .WithShape(new { id = 0, name = "", email = "", createdAt = "" })
    );

    // Act
    var newUser = new { name = "John Doe", email = "john@example.com" };
    var response = await client.PostAsJsonAsync("/users", newUser);

    // Assert
    response.EnsureSuccessStatusCode();
    var created = await response.Content.ReadFromJsonAsync<User>();
    Assert.NotNull(created);
    Assert.NotEqual(0, created.Id);
}

[Fact]
public async Task Should_Handle_Not_Found_Error()
{
    // Arrange
    var client = HttpClientExtensions.CreateMockLlmClient(
        "http://localhost:5116",
        "/users/999",
        config => config.WithError(404, "User not found")
    );

    // Act
    var response = await client.GetAsync("/users/999");

    // Assert
    Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}

Як це працює

The MockLlmHttpHandler є a DelegatingHandler те:

  1. Інтерцепти вихідних запитів HTTP
  2. Запити пошуку за вказаними шаблонами кінцевої точки
  3. Висміювання налаштувань за допомогою параметрів запиту та заголовків HTTP
  4. Переспрямовує змінений запит на поточний глузливий LLM API

Це надасть вам змогу використовувати реалізацію HttpClient у ваших тестах з полегшенням керування поведінкою імітування API без зміни коду програми.

Найкращі вправи та поради

Після роботи з цим інструментом на основі декількох проектів, ось шаблони, які найкраще працюють:

  1. Завжди використовувати контексти для робіт - Обов' язкові ідентифікатори і дані за допомогою багато- крокових операцій
  2. Використовувати форму для безпеки типу - Зробити так, щоб він збігався з вашими інтерфейсами TypeScript
  3. Змішувати справжні та висміювання даних з інструментами - Найкращі з обох світів
  4. Виберіть правильну модель (Дивіться Довідник з моделей Ollama для всіх подробиць:
    • ПРИГОТОВЛЕНІ ДЛЯ ЗАГРОЗАConstellation name (optional): ministral-3:3b (3B парамс, 32K контекст) - КІЛЛЕР за JSON! Ультра- швидкий, дуже точний, мінімальний об' єм пам' яті
    • Виробництво схоже на: llama3 (8B параметри, контекст 8K) - найкращий баланс якості і швидкодії
    • Висока якість: mistral-nemo (12Б параметри, контекст 128K) - складні схеми і масивні набори даних
    • Виконаний виконавець: gemma3:4b або phi3 - Освітліші альтернативи

Повна документація

Висновки

Розробка з графічним інтерфейсом не зобов' язана чекати на API сервера. mostlylucid.mockllmapi дає вам:

  • Контекстна пам' ять - Відповідні, звітні дані через багато-крокові робочі потоки
  • Керування формами - Відповідні визначення схем, які відповідають вашим типам
  • Підтримка універсальних протоколів - REST, GraphQL, gRPC, OSR, SSE, OpenAPI
  • Перевірка гібриди - Змішуйте справжні виробничі дані з створеними витівками
  • Профілактика нульова - Немає фіксацій JSON, які оновлюються при зміні вимог
  • Перевірка програм - Вільний API для тестів інтеграції

Різниця між цим і традиційним висміюванням? Ваша оболонка працює проти реалістичних, контекстно обізнаних даних з першого дня. Більше " він не працював з висмієними даними, але зазнав невдачі з реальними даними ."

Без різниці, чи ви створюєте простий блог, чи комплексну програму підприємництва, ви будете повторювати швидше, більш ретельно перевіряти і доправляти з довір'ям.

Готові починати?

docker compose up -d

Не потрібен сервер.

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.