PhoenixKitAI.TaskSpec (PhoenixKitAI v0.26.1)

Copy Markdown View Source

The declaration of an AI task: a named use of AI that a module's code makes, returned by the module's ai_tasks/0 callback and found by PhoenixKitAI.Tasks.

def ai_tasks do
  [
    %PhoenixKitAI.TaskSpec{
      key: "warehouse.inventory_photo",
      label: gettext_noop("Inventory by photo"),
      gettext_backend: MyModule.Gettext,
      purpose: gettext_noop("Count the stock items visible in shelf photos."),
      needs: [:vision, :json_schema],
      endpoints: {MyModule.Settings, :inventory_endpoint_uuids, []}
    }
  ]
end

The key is a string prefixed with the module's key. needs says what the model has to be able to do: :vision (images in), :file_input (documents such as PDF in), :image_output (it generates images), :tools, :json_schema (a strict JSON schema) — hard requirements a call is refused for — and :json (any JSON; soft, only noted). endpoints is an {module, function, args} returning the endpoints the task uses now (uuids or %PhoenixKitAI.Endpoint{}s, a single one, {:ok, uuid} or nil).

default_limits are the task's limits when an admin has set none (%{task: %{unit => %{period => amount}}, user: …}, units :money in dollars — a Decimal or a dollar string like "20.00", never an integer, which the released versions read as millionths and which now refuses the task's calls —, :requests, :tokens, periods :day, :month — see PhoenixKitAI.TaskLimits). watchers is an {module, function, args} called with the user uuid (or nil) appended, returning the uuids of more people to tell about the task's limits (PhoenixKitAI.GuardEvents); the user is never told as a watcher.

user_limits (default true) says whether the guard limits each user in the task. false is for a task whose module keeps its own limits per user: PhoenixKitAI.TaskLimits then has only the task's limits for it, ignores the user part of default_limits and the user values an admin stored (they stay in the database), refuses to set user limits ({:error, :user_limits_off}), and «AI → Tasks» shows no user limits for it. Only false turns them off: PhoenixKitAI.Tasks reads any other value (nil included) as true.

self_flag says the consumer has its model flag off-purpose requests (the default of the task's guard mode, PhoenixKitAI.Guard.self_flag?/1). private hides the reasons of the task's flags and blocks from all but the holders of ai.manage. block_group names the group a block of the task lands on (nil: the task's own key; "free_text" for tasks that take free text). sources (the source values a call may come from; a module name allows its functions), max_calls_per_hour (per person) and max_tokens_per_call are norms whose breach is signalled, never blocked (PhoenixKitAI.Guard.check_anomalies/1). auto_block_threshold and content are kept for a later part of the guard (a classifier); nothing reads them yet. typical_tokens ({input, output} of a typical call) is read by PhoenixKitAI.Recommendations to estimate the price of a call.

module and enabled are filled in by PhoenixKitAI.Tasks: the module that declared the task, and whether that module is switched on.

Summary

Functions

The requirements a call is refused for when the model lacks them.

The task's label in the current locale, through its own gettext backend when it names one; the key when it has no label.

Every requirement a task or a call can have.

The task's purpose for display, translated through the declaring module's gettext_backend when one is set (declare it with gettext_noop/1). The untranslated text is what prompts and classifiers get, so their wording stays the same in every locale.

Types

mfa_ref()

@type mfa_ref() :: {module(), atom(), list()}

need()

@type need() :: :vision | :file_input | :image_output | :tools | :json_schema | :json

t()

@type t() :: %PhoenixKitAI.TaskSpec{
  auto_block_threshold: pos_integer() | nil,
  block_group: String.t() | nil,
  content: mfa_ref() | nil,
  default_limits: map(),
  enabled: boolean(),
  endpoints: mfa_ref() | nil,
  gettext_backend: module() | nil,
  key: String.t(),
  label: String.t() | nil,
  max_calls_per_hour: pos_integer() | nil,
  max_tokens_per_call: pos_integer() | nil,
  module: module() | nil,
  needs: [need()],
  private: boolean(),
  purpose: String.t() | nil,
  self_flag: boolean(),
  sources: [String.t()] | nil,
  typical_tokens: {non_neg_integer(), non_neg_integer()} | nil,
  user_limits: boolean(),
  watchers: mfa_ref() | nil
}

Functions

hard_needs()

@spec hard_needs() :: [need()]

The requirements a call is refused for when the model lacks them.

label(task_spec)

@spec label(t()) :: String.t()

The task's label in the current locale, through its own gettext backend when it names one; the key when it has no label.

needs()

@spec needs() :: [need()]

Every requirement a task or a call can have.

purpose(task_spec)

@spec purpose(t()) :: String.t() | nil

The task's purpose for display, translated through the declaring module's gettext_backend when one is set (declare it with gettext_noop/1). The untranslated text is what prompts and classifiers get, so their wording stays the same in every locale.