LLMApi: OpenAPI 动态模型生成器: 装入任何螺纹, 模拟任何 API (中文 (Chinese Simplified))

LLMApi: OpenAPI 动态模型生成器: 装入任何螺纹, 模拟任何 API

Wednesday, 05 November 2025

//

10 minute read

注:本文章主要是作为作为释放文件作为我的核素包的一部分产生的人工智能。

很有趣,所以我把它放在这里 但如果这是你的问题 请别管它

一. 导言 导言 导言 导言 导言 导言 一,导言 导言 导言 导言 导言 导言

你是否曾经需要测试 一个尚未准备好的API?

还是想在不受打击率限制的情况下 发展离线状态? OpenAPI 动态模型生成器允许您装入任何 OpenAPI 规格, 并立即生成一个功能齐全的模拟模型API, 包含现实的、 LLM 生成的数据 。

没有配置文件 。没有手工创建结束点 。只要把它指向OpenAPI的标本 然后开始请求

N Nuget 元数

N Nuget 元数

你可以找到

graph TD
    A[Your App] --> B{External API}
    B -->|Not Ready| C[Development Blocked]
    B -->|Rate Limited| D[Can't Test Freely]
    B -->|Requires Auth| E[Complex Setup]
    B -->|Expensive| F[Cost Concerns]
    B -->|Unreliable| G[Flaky Tests]

吉特Hub在这里

  • 对于项目,所有公共领域等等...
  • OpenApi 管理器
  • 问题:AIP 依赖性综合发展

现代应用取决于几十个外部API。

在发展过程中,你面临若干挑战:

  1. 传统解决办法包括:
  2. 手工编写模拟答复(繁琐,过时)
  3. 记录/重放 HTTP 流量( 易碎、 难以维护)
  4. 使用硬编码固定装置(不现实,不包括边缘情况)
sequenceDiagram
    participant Dev as Developer
    participant System as Mock System
    participant Spec as OpenAPI Spec
    participant LLM as Local LLM

    Dev->>System: Load spec from URL/file
    System->>Spec: Parse OpenAPI document
    Spec-->>System: Endpoints, schemas, descriptions
    System->>System: Register dynamic routes

    Dev->>System: GET /petstore/pet/123
    System->>LLM: Generate data for "Pet" schema
    LLM-->>System: Realistic pet data
    System-->>Dev: {"id": 123, "name": "Max", ...}

解决方案:动态的 OpenAPI 模拟

将系统指向任何 OpenAPI 标准, 自动 :

解析规格

graph TB
    A[HTTP Request] --> B{Route Matches?}
    B -->|No| C[404 Not Found]
    B -->|Yes| D[DynamicOpenApiManager]
    D --> E[Find Matching Endpoint]
    E --> F[OpenApiRequestHandler]
    F --> G[Extract Schema from Spec]
    G --> H[Build LLM Prompt]
    H --> I[PromptBuilder]
    I --> J[Include Context?]
    J -->|Yes| K[OpenApiContextManager]
    J -->|No| L[LLM Client]
    K --> L
    L --> M[Get Response]
    M --> N[JsonExtractor]
    N --> O[Return Mock Data]

发现所有终点

  1. 使用 LLM 生成现实的模拟数据将模拟APIP服务在本地机器上
  2. 如何运作建筑结构概览
  3. **OpenAPI系统由几个协调部分组成:**关键构件 :
  4. 动态开放管理器- 管理已加载的规格和路线匹配
  5. Open spispect 操作器- 获取和分割 OpenAPI 文档

OpenApi 请求手动器

  • 生成匹配终点的响应

即时建筑

POST /api/openapi/specs
Content-Type: application/json

{
  "name": "petstore",
  "source": "https://petstore3.swagger.io/api/v3/openapi.json",
  "basePath": "/petstore"
}

- 从 OpenAPI 方案创建 LLM 提示

POST /api/openapi/specs
Content-Type: application/json

{
  "name": "my-api",
  "source": "./specs/my-api.yaml",
  "basePath": "/api/v1"
}

OpenApicon Text 管理器

POST /api/openapi/specs
Content-Type: application/json

{
  "name": "inline-api",
  "source": "data:application/json;base64,eyJvcGVuYXBpIjoiMy...",
  "basePath": "/api"
}

- 保持各呼叫之间的一致性(可选择)

装入指定

public async Task<SpecLoadResult> LoadSpecAsync(
    string name,
    string source,
    string? basePath = null,
    string? contextName = null)
{
    // 1. Use scoped service factory for OpenApiSpecLoader
    using var scope = _scopeFactory.CreateScope();
    var specLoader = scope.ServiceProvider
        .GetRequiredService<OpenApiSpecLoader>();

    // 2. Load the OpenAPI document
    var document = await specLoader.LoadSpecAsync(source);

    // 3. Determine base path from spec or parameter
    var effectiveBasePath = basePath
        ?? document.Servers?.FirstOrDefault()?.Url
        ?? "/api";

    // 4. Store spec with configuration
    var config = new OpenApiSpecConfig
    {
        Name = name,
        Source = source,
        Document = document,
        BasePath = effectiveBasePath,
        ContextName = contextName,
        LoadedAt = DateTimeOffset.UtcNow
    };

    _specs.AddOrUpdate(name, config, (_, __) => config);

    // 5. Notify listeners via SignalR
    await NotifySpecLoaded(name, effectiveBasePath);

    return new SpecLoadResult
    {
        Name = name,
        BasePath = effectiveBasePath,
        EndpointCount = CountEndpoints(document),
        Success = true
    };
}

颜色可以从三个来源装入 :

  1. 目标 1. 目标
public OpenApiEndpointMatch? FindMatchingEndpoint(string path, string method)
{
    // Try each loaded spec
    foreach (var spec in _specs.Values)
    {
        // Remove base path prefix
        var relativePath = path;
        if (path.StartsWith(spec.BasePath))
        {
            relativePath = path.Substring(spec.BasePath.Length);
        }

        // Find matching path in OpenAPI document
        var (pathTemplate, operation) = FindOperation(
            spec.Document,
            relativePath,
            method);

        if (operation != null)
        {
            return new OpenApiEndpointMatch
            {
                Spec = spec,
                PathTemplate = pathTemplate,
                Operation = operation,
                Method = ParseMethod(method)
            };
        }
    }

    return null;
}

远程 URL

  1. 目标
public async Task<string> HandleRequestAsync(
    HttpContext context,
    OpenApiDocument document,
    string path,
    OperationType method,
    OpenApiOperation operation,
    string? contextName = null,
    CancellationToken cancellationToken = default)
{
    // 1. Extract request body
    var requestBody = await ReadRequestBodyAsync(context.Request);

    // 2. Get success response schema
    var shape = ExtractResponseSchema(operation);

    // 3. Get context history if using contexts
    var contextHistory = !string.IsNullOrWhiteSpace(contextName)
        ? _contextManager.GetContextForPrompt(contextName)
        : null;

    // 4. Build prompt from OpenAPI metadata
    var description = operation.Summary ?? operation.Description;
    var prompt = _promptBuilder.BuildPrompt(
        method.ToString(),
        path,
        requestBody,
        new ShapeInfo { Shape = shape },
        streaming: false,
        description: description,
        contextHistory: contextHistory);

    // 5. Get response from LLM
    var rawResponse = await _llmClient.GetCompletionAsync(
        prompt,
        cancellationToken);

    // 6. Extract clean JSON
    var jsonResponse = JsonExtractor.ExtractJson(rawResponse);

    // 7. Store in context if configured
    if (!string.IsNullOrWhiteSpace(contextName))
    {
        _contextManager.AddToContext(
            contextName,
            method.ToString(),
            path,
            requestBody,
            jsonResponse);
    }

    return jsonResponse;
}

本地文件

3 个

private string? ExtractResponseSchema(OpenApiOperation operation)
{
    // Look for successful response (2xx)
    var successResponse = operation.Responses
        .FirstOrDefault(r => r.Key.StartsWith("2"))
        .Value;

    if (successResponse == null)
        return null;

    // Get JSON content
    var jsonContent = successResponse.Content
        .FirstOrDefault(c => c.Key.Contains("json"))
        .Value;

    if (jsonContent?.Schema == null)
        return null;

    // Convert OpenAPI schema to JSON Schema
    return ConvertToJsonSchema(jsonContent.Schema);
}

private string ConvertToJsonSchema(OpenApiSchema schema)
{
    // Recursively build JSON Schema representation
    var builder = new StringBuilder();
    builder.Append("{");

    if (schema.Type != null)
    {
        builder.Append($"\"type\":\"{schema.Type}\"");
    }

    if (schema.Properties?.Count > 0)
    {
        builder.Append(",\"properties\":{");
        var props = schema.Properties
            .Select(p => $"\"{p.Key}\":{ConvertToJsonSchema(p.Value)}");
        builder.Append(string.Join(",", props));
        builder.Append("}");
    }

    if (schema.Items != null)
    {
        builder.Append(",\"items\":");
        builder.Append(ConvertToJsonSchema(schema.Items));
    }

    builder.Append("}");
    return builder.ToString();
}

数据 URL (Base64 编码)

标注加载进程

下面是当你装载一个规格时发生的情况:

动态线路匹配

POST /api/openapi/specs
Content-Type: application/json

{
  "name": "petstore",
  "source": "https://petstore3.swagger.io/api/v3/openapi.json",
  "basePath": "/petstore"
}

当请求抵达时,系统与所有已装入的规格匹配:

{
  "name": "petstore",
  "basePath": "/petstore",
  "endpointCount": 19,
  "endpoints": [
    {"path": "/petstore/pet", "method": "POST"},
    {"path": "/petstore/pet/{petId}", "method": "GET"},
    {"path": "/petstore/pet/findByStatus", "method": "GET"},
    ...
  ],
  "success": true
}

请求处理

一旦找到匹配的终点, 处理器会生成响应 :

### Get a pet by ID
GET /petstore/pet/123

### Response (auto-generated):
{
  "id": 123,
  "name": "Max",
  "category": {
    "id": 1,
    "name": "Dogs"
  },
  "photoUrls": [
    "https://example.com/max1.jpg"
  ],
  "tags": [
    {"id": 1, "name": "friendly"},
    {"id": 2, "name": "trained"}
  ],
  "status": "available"
}
### Find pets by status
GET /petstore/pet/findByStatus?status=available

### Response (auto-generated array):
[
  {
    "id": 42,
    "name": "Buddy",
    "status": "available",
    ...
  },
  {
    "id": 43,
    "name": "Luna",
    "status": "available",
    ...
  }
]

Schema 采掘

GET /api/openapi/specs/petstore

### Shows full details:
### - All endpoints
### - Load time
### - Context configuration
### - Base path

系统从 OpenAPI 定义中提取响应图:

POST /api/openapi/specs/petstore/reload

真实世界使用量

DELETE /api/openapi/specs/petstore

实例:

让我们嘲笑经典的宠物商店API:

### Load Petstore at /petstore
POST /api/openapi/specs
{"name": "petstore", "source": "...", "basePath": "/petstore"}

### Load GitHub API at /github
POST /api/openapi/specs
{"name": "github", "source": "...", "basePath": "/github"}

### Load Stripe API at /stripe
POST /api/openapi/specs
{"name": "stripe", "source": "...", "basePath": "/stripe"}

### All three APIs now available simultaneously:
GET /petstore/pet/123
GET /github/users/octocat
GET /stripe/customers/cus_123

第1步:装入标准

答复:

POST /api/openapi/specs
Content-Type: application/json

{
  "name": "petstore",
  "source": "https://petstore3.swagger.io/api/v3/openapi.json",
  "basePath": "/petstore",
  "contextName": "petstore-session"
}

第2步:使用模拟末端点

### Create a pet
POST /petstore/pet
{"name": "Max", "status": "available"}

### Response: {"id": 42, "name": "Max", "status": "available"}

### Get the pet (will reference same ID and name)
GET /petstore/pet/42

### Response: {"id": 42, "name": "Max", "status": "available"}
### Notice: Consistent ID and name from context

现在所有19个终点都可用:

步骤3:检查特征

POST /api/openapi/test
Content-Type: application/json

{
  "specName": "petstore",
  "path": "/pet/123",
  "method": "GET"
}

### Returns mock response without affecting routes

步骤4:如果参数变化重新装入

  • 第5步:删除完成时删除
  • 多重分层同时
  • 您可以同时装入多个图解, 每个图解都有自己的基准路径 :

带有上下文的特征

更现实的是,给一个特征设定一个上下文:http://localhost:5116/OpenApi:

graph TD
    A[OpenAPI Manager UI] --> B[Load Spec Section]
    A --> C[Spec List]
    A --> D[Context Viewer]

    B --> E[URL Input]
    B --> F[JSON Input]
    B --> G[Context Configuration]

    C --> H[Spec Card]
    H --> I[Reload Button]
    H --> J[Delete Button]
    H --> K[View Endpoints]

    D --> L[Active Contexts]
    L --> M[Context Details]
    L --> N[Clear Context]

现在所有宠物商店的终点都有着相同的上下文:

  • 测试终点测试端点允许您尝试端点而不提出真正的请求 :
  • **这有助于:**整合前预览响应
  • 单独测试特定终点调试计划问题
  • 管理统一UI视觉管理,访问
  • **特点:**拖放拖放
  • spec 文件上传活端点发现

- 立即看到所有终点

单击一拳的测试

  • 用按钮测试任何端点
# OpenAPI Spec
/pet/{petId}:
  get:
    parameters:
      - name: petId
        in: path
        schema:
          type: integer
GET /petstore/pet/123
### LLM receives: "Generate data for Pet with petId=123"
### Response: {"id": 123, ...}

实时通知

  • 参数装载时更新信号R
/pet/findByStatus:
  get:
    parameters:
      - name: status
        in: query
        schema:
          type: string
          enum: [available, pending, sold]
GET /petstore/pet/findByStatus?status=available
### LLM receives: "Generate array of Pets with status=available"
### Response: [{"status": "available", ...}, ...]

语法突出语法

  • 美丽的JSON应答显示
/pet:
  post:
    requestBody:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Pet'
POST /petstore/pet
Content-Type: application/json

{"name": "Max", "status": "available"}

### LLM receives: "Generate response for creating Pet with name=Max, status=available"
### Response: {"id": 42, "name": "Max", "status": "available"}

背景管理

  • 观点和清晰的背景
/pet/{petId}:
  get:
    summary: Find pet by ID
    description: Returns a single pet based on the ID provided

高级特征

路径图参数

自动提取路径参数 :

responses:
  '200':
    description: Successful operation
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Pet'
  '404':
    description: Pet not found

查询参数

查询参数影响响应 :

请求机构

public async Task NotifySpecLoaded(string name, string basePath)
{
    await _hubContext.Clients.All.SendAsync("SpecLoaded", new
    {
        name,
        basePath,
        timestamp = DateTimeOffset.UtcNow
    });
}

public async Task NotifySpecDeleted(string name)
{
    await _hubContext.Clients.All.SendAsync("SpecDeleted", new
    {
        name,
        timestamp = DateTimeOffset.UtcNow
    });
}

POST/PUT机构迅速列入:

const connection = new signalR.HubConnectionBuilder()
    .withUrl('/hubs/openapi')
    .build();

connection.on('SpecLoaded', (data) => {
    showNotification(`Spec "${data.name}" loaded at ${data.basePath}`, 'success');
    refreshSpecList();
});

connection.on('SpecDeleted', (data) => {
    showNotification(`Spec "${data.name}" deleted`, 'info');
    refreshSpecList();
});

说明和摘要

OpenAPI说明指导了LLM:

  • 及时将这些内容纳入其中,帮助专卖局长了解终点的目的。
  • 反应状态法
  • 该系统使用第一个成功(2xx)响应:
  • 只有200个模型模型用于模拟发电(目前没有模拟404个)。
  • 信号信号R 实时更新

在装入/删除规格时,UI通过信号R接收实时通知:

JavaScript 用户界面代码 :

格式支持

 Bad:  {"name": "spec1", ...}
 Good: {"name": "github-v3", ...}

该系统支持:

OpenAPI 3.0.x

### Good separation
/petstore/...
/github/...
/stripe/...

### Bad (conflicts!)
/api/... (multiple specs)

OpenAPI 3.1.x

斯瓦格 2. 0

POST /api/openapi/specs/my-api/reload

JSON 格式格式

POST /api/openapi/specs
{
  "name": "petstore",
  "source": "...",
  "contextName": "test-session"
}

### Now all petstore calls maintain consistency

YAML 格式格式

JSON和YAML的规格都自动检测和解析。

DELETE /api/openapi/specs/old-spec

最佳做法最佳做法

  1. 1. 目标 1. 目标使用描述性插件名称
  2. 2. 目标设置适当的基础路径
  3. **使用独特的基准路径避免冲突:**3 个
  4. 设置改变时重新装入如果您的 OpenAPI 规格已更新, 请重新装入 :
  5. **4. 4个。**关联调用使用背景

5 个

测试后清理/api/mock删除您不再使用的参数 :

### OpenAPI-based (from spec)
GET /petstore/pet/123
### Uses Pet schema from OpenAPI spec

### Regular mock (shape-based)
GET /api/mock/custom?shape={"id":0,"name":"string"}
### Uses explicit shape parameter

限制

反应状态法

- 只有成功的(2xx)答复被嘲笑

验证

private readonly ConcurrentDictionary<string, OpenApiSpecConfig> _specs = new();

- 接受认证信头,但未经验证

DynamicOpenApiManager审定

- 不执行针对计划要求的验证;

状态状态状态状态状态状态

### Send these simultaneously
POST /api/openapi/specs {"name": "spec1", ...}
POST /api/openapi/specs {"name": "spec2", ...}
POST /api/openapi/specs {"name": "spec3", ...}
  • 没有实际数据库;数据每次更新(除非使用上下文)

业绩 业绩业绩 业绩业绩

- LLM 代LLM增加延长(每请求100-500米)

与常规模拟末端点整合OpenAPI 特征与常规平行工作

终点 :

  • 两者使用相同的基本LLM,但在如何提供方案方面有所不同。
  • 业绩优化
  • 缓缓
  • 加载的参数在内存中缓存 :

使用寿命

**是一个单吨,因此应用程序寿命期间的参数仍会装入。**平行镜表加载

多个特性可以平行装入 :

  • 这三个人将平行装载,而不是相继装载。/petstore + /pet/123 = /petstore/pet/123
  • 排除故障
  • 闪光不会装入

问题:

显示装入失败解决办法:

检查 URL 可访问

  • 校验文件已存在( 用于本地路径)
  • 确保JSON/YAML有效
  • 查找 CORS 问题( 远程 URL)

未找到结束点

问题:

关于预期终点的404

  • **解决办法:**校验基准路径 :
  • 检查 pec 实际定义此路径确保 HTTP 方法匹配( GET 相对于 POST)
  • 反应与 Schema 不匹配问题:
  • 生成的数据与预期计划不匹配解决办法:
  • 检查规格中的图案是否正确校验您正在查看正确的响应( 200 vs 201) 。

记住:LLM一代是概率性的,不是决定性的。

结论 结论 结论 结论 结论

Finding related posts...
logo

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