Class: Raif::Task

Direct Known Subclasses

Evals::LlmJudge

Constant Summary

Constants included from Concerns::LlmResponseParsing

Concerns::LlmResponseParsing::ASCII_CONTROL_CHARS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Concerns::RunWith

deserialize_run_with_value, gid_string?, locate_gid, serialize_run_with_value

Methods included from Concerns::JsonSchemaDefinition

#schema_for_instance

Methods included from Concerns::LlmResponseParsing

#parse_html_response, #parse_json_response, #parsed_response

Methods included from Concerns::HasRuntimeDuration

#runtime_duration, #runtime_duration_seconds, #runtime_ended_at

Methods included from Concerns::HasAvailableModelTools

#available_model_tools_map

Methods included from Concerns::HasRequestedLanguage

#requested_language_name, #system_prompt_language_preference

Methods included from Concerns::HasLlm

#default_llm_model_key, #llm

Instance Attribute Details

#filesObject

Returns the value of attribute files.



76
77
78
# File 'app/models/raif/task.rb', line 76

def files
  @files
end

#imagesObject

Returns the value of attribute images.



76
77
78
# File 'app/models/raif/task.rb', line 76

def images
  @images
end

Class Method Details

.build_for_batch(batch:, batch_custom_id: nil, creator: nil, available_model_tools: [], llm_model_key: nil, images: [], files: [], **args) ⇒ Raif::Task

Builds a Raif::Task and a pending Raif::ModelCompletion attached to the given Raif::ModelCompletionBatch, without performing the LLM request. The provider's batch-submission code reads the pending completion's request fields when constructing its per-entry batch payload.

The task is persisted with started_at: nil (state :pending). The pending ModelCompletion has raif_model_completion_batch_id pointing at the batch and batch_custom_id set to the value used as the provider's custom_id in the batch payload.

Parameters:

  • batch (Raif::ModelCompletionBatch)
  • batch_custom_id (String, nil) (defaults to: nil)

    the provider custom_id; defaults to "raif_task_<task.id>"

Returns:



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'app/models/raif/task.rb', line 204

def self.build_for_batch(batch:, batch_custom_id: nil, creator: nil, available_model_tools: [],
  llm_model_key: nil, images: [], files: [], **args)
  task = build_task_instance(
    creator: creator,
    available_model_tools: available_model_tools,
    llm_model_key: llm_model_key,
    images: images,
    files: files,
    **args
  )

  task.save!
  task.prepare_for_batch!(batch: batch, batch_custom_id: batch_custom_id)
  task
end

.json_response_schema(&block) ⇒ Object



301
302
303
304
305
306
307
# File 'app/models/raif/task.rb', line 301

def self.json_response_schema(&block)
  if block_given?
    json_schema_definition(:json_response, &block)
  elsif schema_defined?(:json_response)
    schema_for(:json_response)
  end
end

.prompt(creator: nil, **args) ⇒ String

Returns the LLM prompt for the task.

Parameters:

  • creator (Object, nil) (defaults to: nil)

    The creator of the task (polymorphic association), optional

  • args (Hash)

    Additional arguments to pass to the instance of the task that is created.

Returns:

  • (String)

    The LLM prompt for the task.



288
289
290
# File 'app/models/raif/task.rb', line 288

def self.prompt(creator: nil, **args)
  new(creator:, **args).build_prompt
end

.run(creator: nil, available_model_tools: [], llm_model_key: nil, images: [], files: [], **args, &block) ⇒ Raif::Task?

The primary interface for running a task. It will hit the LLM with the task's prompt and system prompt and return a Raif::Task object. It will also create a new Raif::ModelCompletion record.

Parameters:

  • creator (Object, nil) (defaults to: nil)

    The creator of the task (polymorphic association), optional

  • available_model_tools (Array<Class>) (defaults to: [])

    Optional array of model tool classes that will be provided to the LLM for it to invoke.

  • llm_model_key (Symbol, String) (defaults to: nil)

    Optional key for the LLM model to use. If blank, Raif.config.default_llm_model_key will be used.

  • images (Array) (defaults to: [])

    Optional array of Raif::ModelImageInput objects to include with the prompt.

  • files (Array) (defaults to: [])

    Optional array of Raif::ModelFileInput objects to include with the prompt.

  • args (Hash)

    Additional arguments to pass to the instance of the task that is created.

Returns:

  • (Raif::Task, nil)

    The task instance that was created and run.



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'app/models/raif/task.rb', line 103

def self.run(creator: nil, available_model_tools: [], llm_model_key: nil, images: [], files: [], **args, &block)
  task = build_task_instance(
    creator: creator,
    available_model_tools: available_model_tools,
    llm_model_key: llm_model_key,
    images: images,
    files: files,
    started_at: Time.current,
    **args
  )

  task.save!
  task.run(&block)
  task
rescue StandardError => e
  task&.failed!

  logger.error e.message
  logger.error e.backtrace.join("\n")

  if defined?(Airbrake)
    notice = Airbrake.build_notice(e)
    notice[:context][:component] = "raif_task"
    notice[:context][:action] = name

    Airbrake.notify(notice)
  end

  task
end

.system_prompt(creator: nil, **args) ⇒ String

Returns the LLM system prompt for the task.

Parameters:

  • creator (Object, nil) (defaults to: nil)

    The creator of the task (polymorphic association), optional

  • args (Hash)

    Additional arguments to pass to the instance of the task that is created.

Returns:

  • (String)

    The LLM system prompt for the task.



297
298
299
# File 'app/models/raif/task.rb', line 297

def self.system_prompt(creator: nil, **args)
  new(creator:, **args).build_system_prompt
end

Instance Method Details

#build_promptObject

Raises:

  • (NotImplementedError)


325
326
327
# File 'app/models/raif/task.rb', line 325

def build_prompt
  raise NotImplementedError, "Raif::Task subclasses must implement #build_prompt"
end

#build_system_promptObject



329
330
331
332
333
334
# File 'app/models/raif/task.rb', line 329

def build_system_prompt
  sp = Raif.config.task_system_prompt_intro
  sp = sp.call(self) if sp.respond_to?(:call)
  sp += system_prompt_language_preference if requested_language_key.present?
  sp
end

#json_response_schemaObject

Instance method to get the JSON response schema For instance-dependent schemas, builds the schema with this instance as context For class-level schemas, returns the class-level schema



312
313
314
# File 'app/models/raif/task.rb', line 312

def json_response_schema
  schema_for_instance(:json_response)
end

#messagesObject



279
280
281
# File 'app/models/raif/task.rb', line 279

def messages
  [{ "role" => "user", "content" => message_content }]
end

#prepare_for_batch!(batch:, batch_custom_id: nil, skip_prompt_population: false) ⇒ Raif::ModelCompletion

Populates this task's prompts and creates the pending Raif::ModelCompletion that will be sent through the batch. Mirrors Raif::Task#run's default behavior: prompts are rebuilt every call unless skip_prompt_population: true is passed (e.g. for re-prepare flows where the caller has hand-set prompts and wants them preserved).

The default batch_custom_id is "raif_task_<task.id>" — a task-specific identifier. Other producers (non-task) should pass an explicit batch_custom_id when building their own pending completions via Raif::Llm#build_pending_model_completion; the only requirement is uniqueness within the batch.

Parameters:

  • batch (Raif::ModelCompletionBatch)
  • batch_custom_id (String, nil) (defaults to: nil)
  • skip_prompt_population (Boolean) (defaults to: false)

    preserve any pre-set prompts on this task instead of rebuilding via #build_prompt / #build_system_prompt

Returns:



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'app/models/raif/task.rb', line 256

def prepare_for_batch!(batch:, batch_custom_id: nil, skip_prompt_population: false)
  populate_prompts unless skip_prompt_population
  save! if changed?

  effective_batch_custom_id = batch_custom_id.presence || "raif_task_#{id}"

  mc = llm.build_pending_model_completion(
    messages: messages,
    source: self,
    system_prompt: system_prompt,
    response_format: response_format.to_sym,
    available_model_tools: available_model_tools,
    temperature: self.class.temperature,
    anthropic_prompt_caching_enabled: self.class.anthropic_prompt_caching_enabled,
    bedrock_prompt_caching_enabled: self.class.bedrock_prompt_caching_enabled,
    raif_model_completion_batch: batch,
    batch_custom_id: effective_batch_custom_id
  )

  self.raif_model_completion = mc
  mc
end

#process_completion!(model_completion) ⇒ self

Wires a (possibly batch-resolved) Raif::ModelCompletion back into this task: links it as the task's raif_model_completion, mirrors raw_response onto the task, processes any tool calls the model made, and transitions the task to completed (or failed, if the underlying completion failed). Called by both the synchronous #run path and the batch completion handler after the provider's per-entry result has been applied.

Parameters:

Returns:

  • (self)


175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'app/models/raif/task.rb', line 175

def process_completion!(model_completion)
  self.raif_model_completion = model_completion.becomes(Raif::ModelCompletion)

  update(raw_response: raif_model_completion.raw_response)

  if raif_model_completion.failed?
    # Failure detail (failure_error / failure_reason) lives on the model
    # completion; the task's `failed_at` is just a state marker.
    failed!
  else
    process_model_tool_invocations
    completed!
  end
  self
end

#prompt_studio_task_attributesHash

Returns additional attributes to assign when creating tasks in Prompt Studio (reruns, batch runs, and judge tasks). Override in your ApplicationTask or task subclass to include app-specific attributes.

Returns:

  • (Hash)

    additional attributes to assign to the new task



321
322
323
# File 'app/models/raif/task.rb', line 321

def prompt_studio_task_attributes
  {}
end

#re_run(&block) ⇒ Object



161
162
163
164
# File 'app/models/raif/task.rb', line 161

def re_run(&block)
  update_columns(started_at: Time.current)
  run(skip_prompt_population: true, &block)
end

#run(skip_prompt_population: false, &block) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'app/models/raif/task.rb', line 134

def run(skip_prompt_population: false, &block)
  update_columns(started_at: Time.current) if started_at.nil?

  populate_prompts unless skip_prompt_population

  streaming_block = if block_given?
    proc do |model_completion, delta, sse_event|
      update_columns(raw_response: model_completion.raw_response, updated_at: Time.current)
      block.call(model_completion, delta, sse_event)
    end
  end

  mc = llm.chat(
    messages: messages,
    source: self,
    system_prompt: system_prompt,
    response_format: response_format.to_sym,
    available_model_tools: available_model_tools,
    temperature: self.class.temperature,
    anthropic_prompt_caching_enabled: self.class.anthropic_prompt_caching_enabled,
    bedrock_prompt_caching_enabled: self.class.bedrock_prompt_caching_enabled,
    &streaming_block
  )

  process_completion!(mc)
end

#statusObject



81
82
83
84
85
86
87
88
89
90
91
# File 'app/models/raif/task.rb', line 81

def status
  if completed_at?
    :completed
  elsif failed_at?
    :failed
  elsif started_at?
    :in_progress
  else
    :pending
  end
end