Team Ai
Apppublic

WaveCut/Bonsai-Chat-WebGPU

sourceHugging Faceupdated 3mo agoView on Hugging Face
5likes
protocol.ts413 linesDownload Raw Back to engine
1import type { ModelManifestV2, ModelTierId } from './manifest';2import type { BackendReport } from './native-log';3 4export type RuntimeBackend = 'webgpu' | 'wasm';5export type RequestedBackend = 'auto' | RuntimeBackend;6 7export interface StorageEstimate {8  usageBytes: number | null;9  quotaBytes: number | null;10  persisted: boolean;11}12 13export interface WebGpuAdapterSnapshot {14  available: boolean;15  name: string | null;16  vendor: string | null;17  architecture: string | null;18  device: string | null;19  description: string | null;20  limits: Record<string, number>;21  features: string[];22}23 24export interface EngineCapabilities {25  crossOriginIsolated: boolean;26  sharedArrayBuffer: boolean;27  hardwareConcurrency: number;28  webgpu: WebGpuAdapterSnapshot;29  storage: StorageEstimate;30  browser: {31    userAgent: string;32    platform: string;33    language: string;34  };35  runtime: {36    implementation: 'bonsai-wllama';37    wllamaRevision: string;38    llamaCppRevision: string;39    patchSetSha256: string;40    moduleSha256: string;41    wasmFlavor: 'jspi' | 'compat';42    wasmSha256: string;43    compatWorkerSha256: string | null;44    tokenEmbeddingOnWebGPU: true;45    tensorPlacementOverrides: false;46  };47}48 49export interface GateDecision {50  allowed: boolean;51  requestedBackend: RequestedBackend;52  selectedBackend: RuntimeBackend | null;53  reasons: string[];54  warnings: string[];55  requiredBytes: number;56  availableStorageBytes: number | null;57}58 59export interface FutureTensorPlacement {60  engine: 'future-custom-build';61  overrides: Array<{62    tensor: string;63    backend: RuntimeBackend;64  }>;65}66 67export type BenchmarkFlashMode = 'off' | 'auto';68export type BenchmarkKvCacheType = 'f16' | 'q8_0' | 'q4_0';69export type BenchmarkWasmFlavor = 'auto' | 'jspi' | 'compat';70 71export interface BenchmarkLoadTuning {72  nBatch?: number;73  nUbatch?: number;74  flashMode: BenchmarkFlashMode;75  kvCacheType: BenchmarkKvCacheType;76  wasmFlavor: BenchmarkWasmFlavor;77}78 79export interface EngineChatToolCall {80  id: string;81  type: 'function';82  function: {83    name: string;84    arguments: string;85  };86}87 88export type EngineChatMessage =89  | { role: 'system' | 'user'; content: string; name?: string }90  | { role: 'assistant'; content?: string | null; name?: string; tool_calls?: EngineChatToolCall[] }91  | { role: 'tool'; content: string; tool_call_id: string };92 93export interface EngineChatTool {94  type: 'function';95  function: {96    name: string;97    description?: string;98    parameters: {99      type: 'object';100      properties: Record<string, {101        type: string;102        description?: string;103        enum?: string[];104        [key: string]: unknown;105      }>;106      required?: string[];107      additionalProperties?: boolean;108    };109  };110}111 112type ManifestSource =113  | { manifestUrl: string; manifest?: never }114  | { manifest: ModelManifestV2; manifestUrl?: never };115 116export type LoadModelParams = ManifestSource & {117  modelId: ModelTierId;118  backend: RequestedBackend;119  contextSize?: number;120  warmupSystemPrompt?: string;121  threads?: number;122  benchmarkTuning?: BenchmarkLoadTuning;123  tensorPlacement?: FutureTensorPlacement;124};125 126export interface GenerateParams {127  messages: EngineChatMessage[];128  maxTokens?: number;129  temperature?: number;130  topP?: number;131  topK?: number;132  minP?: number;133  seed?: number;134  tools?: EngineChatTool[];135  toolChoice?: 'none' | 'auto' | 'required';136  cachePrompt?: boolean;137  returnTokenIds?: boolean;138}139 140export interface LoadModelResult {141  modelId: ModelTierId;142  backend: RuntimeBackend;143  gate: GateDecision;144  shardUrls: string[];145  context: {146    size: number;147    trainingSize: number;148    layerCount: number;149    vocabularySize: number;150    batchSize: number;151    microBatchSize: number;152  };153  tuning: {154    scope: 'release-defaults' | 'benchmark';155    requested: {156      nBatch: number | null;157      nUbatch: number | null;158      flashMode: BenchmarkFlashMode;159      cacheTypeK: BenchmarkKvCacheType;160      cacheTypeV: BenchmarkKvCacheType;161      wasmFlavor: BenchmarkWasmFlavor;162    };163    observed: {164      nBatch: number;165      nUbatch: number;166      flashAttention: boolean | null;167      cacheTypeK: string | null;168      cacheTypeV: string | null;169      kvBufferBytes: number | null;170      wasmFlavor: 'jspi' | 'compat';171      wasmSha256: string;172      compatWorkerSha256: string | null;173    };174    applied: boolean;175  };176  chatTemplate: {177    bytes: number;178    hasThinkMarker: boolean;179    hasToolCallMarker: boolean;180    hasToolResponseMarker: boolean;181  };182  backendReport: BackendReport;183}184 185export interface EngineTokenLogprob {186  id: number;187  logprob: number;188}189 190export interface EngineSampledTokenTraceEntry {191  selected: EngineTokenLogprob;192  topCandidates: EngineTokenLogprob[];193}194 195export interface GenerateResult {196  text: string;197  reasoningText: string;198  toolCallError?: string;199  tokenIds: number[] | null;200  tokenTrace: EngineSampledTokenTraceEntry[] | null;201  tokenTraceAccounting?: {202    usageCompletionTokens: number | null;203    tracedTokens: number;204    delta: number | null;205  } | null;206  finishReason: 'stop' | 'length' | 'tool_calls' | 'content_filter' | null;207  toolCalls: EngineChatToolCall[];208  usage: {209    promptTokens: number;210    completionTokens: number;211    totalTokens: number;212  } | null;213  timings: {214    promptTokensPerSecond: number;215    predictedTokensPerSecond: number;216  } | null;217}218 219export interface ScoreSequenceParams {220  promptTokenIds: number[];221  referenceTokenIds: number[];222  topK: 5;223}224 225export interface EngineTeacherForcedScoreEntry {226  index: number;227  selectedReference: EngineTokenLogprob;228  naturalTop1: EngineTokenLogprob;229  topCandidates: EngineTokenLogprob[];230  referenceRankInTopCandidatesZeroBased: number | null;231  top1Top2Margin: number;232}233 234export interface ScoreSequenceResult {235  method: {236    promptMode: 'raw-token-id-prefix';237    maxTokensPerStep: 1;238    temperature: 0;239    topK: 1;240    reportedTopLogprobs: 5;241    logitBias: 1_000;242    cachePromptFirst: false;243    cachePromptSubsequent: true;244  };245  entries: EngineTeacherForcedScoreEntry[];246  summary: {247    tokenCount: 1_024;248    meanNll: number;249    perplexity: number;250  };251}252 253export interface EmptyParams {254  readonly _empty?: never;255}256 257export interface EngineRequestMap {258  capabilities: EmptyParams;259  loadModel: LoadModelParams;260  generate: GenerateParams;261  scoreSequence: ScoreSequenceParams;262  abort: { targetRequestId: string };263  unload: EmptyParams;264  backendReport: EmptyParams;265  storageEstimate: EmptyParams;266  storagePersist: EmptyParams;267  storageClear: EmptyParams;268}269 270export interface EngineResponseMap {271  capabilities: EngineCapabilities;272  loadModel: LoadModelResult;273  generate: GenerateResult;274  scoreSequence: ScoreSequenceResult;275  abort: { targetRequestId: string; aborted: boolean };276  unload: { unloaded: true };277  backendReport: BackendReport;278  storageEstimate: StorageEstimate;279  storagePersist: StorageEstimate & { granted: boolean };280  storageClear: StorageEstimate & { cleared: true };281}282 283export type EngineMethod = keyof EngineRequestMap;284 285export type EngineRequest = {286  [Method in EngineMethod]: {287    type: 'request';288    requestId: string;289    method: Method;290    params: EngineRequestMap[Method];291  };292}[EngineMethod];293 294export interface EngineErrorPayload {295  code: string;296  message: string;297  details?: unknown;298}299 300export type ShardDownloadFailureKind = 'network' | 'abort' | 'verification';301 302export interface ShardDownloadFailureDetails {303  kind: 'shard-download-failure';304  failure: ShardDownloadFailureKind;305  causeCode: string;306  shardIndex: number;307  shardCount: number;308  shardPath: string;309  retryFromByteZero: true;310  partialDeleted: boolean;311}312 313export function isShardDownloadFailureDetails(314  value: unknown,315): value is ShardDownloadFailureDetails {316  if (typeof value !== 'object' || value === null) return false;317  const details = value as Partial<ShardDownloadFailureDetails>;318  return details.kind === 'shard-download-failure'319    && (details.failure === 'network' || details.failure === 'abort' || details.failure === 'verification')320    && typeof details.causeCode === 'string'321    && Number.isSafeInteger(details.shardIndex)322    && (details.shardIndex ?? -1) >= 0323    && Number.isSafeInteger(details.shardCount)324    && (details.shardCount ?? 0) > 0325    && (details.shardIndex ?? 0) < (details.shardCount ?? 0)326    && typeof details.shardPath === 'string'327    && details.shardPath.length > 0328    && details.retryFromByteZero === true329    && typeof details.partialDeleted === 'boolean';330}331 332export type EngineResponse = {333  [Method in EngineMethod]:334    | {335      type: 'response';336      requestId: string;337      method: Method;338      ok: true;339      result: EngineResponseMap[Method];340    }341    | {342      type: 'response';343      requestId: string;344      method: Method;345      ok: false;346      error: EngineErrorPayload;347    };348}[EngineMethod];349 350export type EngineShardProgressState =351  | 'queued'352  | 'cached'353  | 'downloading'354  | 'complete'355  | 'error';356 357export interface EngineShardProgress {358  index: number;359  path: string;360  loadedBytes: number;361  totalBytes: number;362  state: EngineShardProgressState;363}364 365export type EngineEvent =366  | {367    type: 'event';368    requestId: string;369    event: 'progress';370    phase: 'manifest' | 'cache' | 'download' | 'load' | 'warmup';371    loadedBytes: number;372    totalBytes: number;373    shardIndex: number | null;374    shardCount: number;375    shardPath: string | null;376    stageProgress: number | null;377    nativeStage: string | null;378    residentBytes: number | null;379    shards: EngineShardProgress[];380  }381  | {382    type: 'event';383    requestId: string;384    event: 'token';385    text: string;386    reasoningDelta?: string;387  }388  | {389    type: 'event';390    requestId: string;391    event: 'tool-call';392    index: number;393    id: string;394    name: string;395    argumentCharacters: number;396    argumentDelta: string;397  }398  | {399    type: 'event';400    requestId: string;401    event: 'generation';402    phase: 'preparing' | 'prefill' | 'decode';403    promptProcessed: number;404    promptTotal: number;405    promptCached: number;406    completionTokens: number;407    elapsedMs: number;408    promptTokensPerSecond: number;409    decodeTokensPerSecond: number;410  };411 412export type EngineWorkerMessage = EngineResponse | EngineEvent;413