File size: 1,920 Bytes
fa1140b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | """统一中间表示(IR)—— 2api 框架的核心数据契约。
上游适配器(``app/upstream/parser.py``)把目标网站的任意原生事件归一成 :class:`IREvent`,
三家 API adapter(``app/adapters/*``)各自消费同一份 IREvent 流,转成 OpenAI / Anthropic 格式。
换上游时**唯一必改**的是 parser(原生事件 → IREvent);IREvent 本身是稳定契约,勿轻改。
新增需求优先扩 :attr:`ToolEvent.detail`,而非加 IREvent 字段。
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Literal
IRKind = Literal["text", "thinking", "tool", "finish", "error"]
@dataclass
class ToolEvent:
"""工具调用 / 工具事件:agent 内置工具的展示,或 prompt 模式解析出的调用。"""
name: str
title: str = ""
detail: dict[str, Any] = field(default_factory=dict)
@dataclass
class Usage:
"""token 用量。优先用上游真实值(parser 填 ``usage_delta``);无则由 :mod:`app.tokens` 估算。"""
input_tokens: int = 0
output_tokens: int = 0
thinking_tokens: int = 0
cached_tokens: int = 0
cache_creation_tokens: int = 0
model: str | None = None
provider: str | None = None
def add(self, other: Usage) -> None:
self.input_tokens += other.input_tokens
self.output_tokens += other.output_tokens
self.thinking_tokens += other.thinking_tokens
self.cached_tokens += other.cached_tokens
self.cache_creation_tokens += other.cache_creation_tokens
@dataclass
class IREvent:
"""归一后的单个中间事件。adapter 把它转成各家流式格式。"""
kind: IRKind
text: str = ""
thinking: str = ""
tool: ToolEvent | None = None
usage_delta: Usage | None = None
finish_reason: str | None = None # "stop" / "length" / "tool_use" / ...
error: str | None = None
|