All files / src/core/services AIService.ts

33.33% Statements 3/9
0% Branches 0/1
0% Functions 0/4
33.33% Lines 3/9

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 8328x                         28x                                   28x                                                                                                      
import { AIBinding } from '@/core/bindings/AIBinding'
 
import type { InferenceEngine } from '@bayudwiyansatria/core'
import type { CloudflareEnv } from '@/types/CloudflareEnv'
 
/**
 * Workers AI binding.
 *
 * Every setting it needs — binding name, model, gateway — arrives resolved
 * from the configuration layer, so nothing about them is decided here. The
 * binding itself is read from `env` per call, which is what makes one
 * module-scope instance safe to share.
 */
const ai = new AIBinding()
 
/**
 * Inference capability, backed by Workers AI.
 *
 * @remarks
 * Which model answers a prompt is configuration, not business logic: callers
 * ask for text and get text. Override `ai.model` in
 * `config/AIConfig.ts` to change it everywhere at
 * once, or name a model per call when one task genuinely needs a different
 * one.
 *
 * @class
 *
 * @author Bayu Dwiyan Satria
 * @version 1.0.0
 * @since 1.0.0
 */
export class AIService<E extends CloudflareEnv = CloudflareEnv> implements InferenceEngine<E> {
  /**
   * Answers a prompt with the configured model.
   *
   * @param env The Worker environment.
   * @param prompt The prompt to send.
   * @param model Model to run. Falls back to the configured model.
   * @returns The generated text.
   */
  public async ask(env: E, prompt: string, model?: string): Promise<string> {
    const result = await ai.run<{ response: string }>(env, { prompt }, model)
 
    return result.response
  }
 
  /**
   * Embeds text as a vector.
   *
   * @param env The Worker environment.
   * @param text The text to embed.
   * @param model Embedding model to run.
   * @returns The embedding.
   */
  public async embed(env: E, text: string, model = '@cf/baai/bge-base-en-v1.5'): Promise<number[]> {
    const result = await ai.run<{ data: number[][] }>(env, { text: [text] }, model)
 
    return result.data[0]
  }
 
  /**
   * Returns the AI Gateway log id of the most recent call.
   *
   * Useful for correlating a response with its gateway log entry.
   *
   * @param env The Worker environment.
   * @returns The log id, or `null` when the call was not routed through a gateway.
   */
  public logId(env: E): string | null {
    return ai.logId(env)
  }
 
  /**
   * Reports whether Workers AI is bound to this Worker.
   *
   * @param env The Worker environment.
   * @returns `true` when the binding is present.
   */
  public isAvailable(env: E): boolean {
    return ai.isBound(env)
  }
}