Class: Langfuse::ApiClient
- Inherits:
-
Object
- Object
- Langfuse::ApiClient
- Includes:
- PromptCacheEvents, ReadApi
- Defined in:
- lib/langfuse/api_client.rb
Overview
HTTP client for Langfuse API
Handles authentication, connection management, and HTTP requests to the Langfuse REST API.
Constant Summary
Constants included from PromptCacheEvents
PromptCacheEvents::PROMPT_CACHE_NOTIFICATION
Instance Attribute Summary collapse
-
#base_url ⇒ String
readonly
Base URL for Langfuse API.
-
#cache ⇒ PromptCache, ...
readonly
Optional cache for prompt responses.
-
#logger ⇒ Logger
readonly
Logger instance for debugging.
-
#public_key ⇒ String
readonly
Langfuse public API key.
-
#secret_key ⇒ String
readonly
Langfuse secret API key.
-
#timeout ⇒ Integer
readonly
HTTP request timeout in seconds.
Instance Method Summary collapse
-
#clear_prompt_cache ⇒ Integer?
Logically clear the whole Langfuse prompt cache namespace.
-
#connection(timeout: nil) ⇒ Faraday::Connection
Get a Faraday connection.
-
#create_dataset(name:, description: nil, metadata: nil) ⇒ Hash
Create a new dataset.
-
#create_dataset_item(dataset_name:, input: nil, expected_output: nil, metadata: nil, id: nil, source_trace_id: nil, source_observation_id: nil, status: nil) ⇒ Hash
Create a new dataset item (or upsert if id is provided).
-
#create_dataset_run_item(dataset_item_id:, run_name:, trace_id: nil, observation_id: nil, metadata: nil, run_description: nil) ⇒ Hash
Create a dataset run item (link a trace to a dataset item within a run).
-
#create_prompt(name:, prompt:, type:, config: {}, labels: [], tags: [], commit_message: nil) ⇒ Hash
Create a new prompt (or new version if prompt with same name exists).
-
#create_score(payload:) ⇒ String
Create a score through the synchronous Scores API.
-
#delete_dataset_item(id) ⇒ Hash
Delete a dataset item by ID.
-
#delete_dataset_run(dataset_name:, run_name:) ⇒ Hash?
Delete a dataset run by name.
-
#get_dataset(name) ⇒ Hash
Fetch a dataset by name.
-
#get_dataset_item(id) ⇒ Hash
Fetch a dataset item by ID.
-
#get_dataset_run(dataset_name:, run_name:) ⇒ Hash
Fetch a dataset run by dataset and run name.
-
#get_projects ⇒ Hash
Fetch projects accessible with the current API keys.
-
#get_prompt(name, version: nil, label: nil, cache_ttl: nil) ⇒ Hash
Fetch a prompt from the Langfuse API.
-
#get_prompt_result(name, version: nil, label: nil, cache_ttl: nil) ⇒ PromptFetchResult
Fetch a prompt and include cache metadata.
-
#get_trace(id) ⇒ Hash
Fetch a trace by ID.
-
#initialize(public_key:, secret_key:, base_url:, timeout: 5, logger: nil, cache: nil, cache_observer: nil) ⇒ ApiClient
constructor
Initialize a new API client.
-
#invalidate_prompt_cache(name, version: nil, label: nil) ⇒ PromptCacheKey
Invalidate one exact logical prompt cache key.
-
#invalidate_prompt_cache_by_name(name) ⇒ Integer?
Invalidate all cached variants for one prompt name.
-
#list_dataset_items ⇒ Array<Hash>
List items in a dataset with optional filters.
-
#list_dataset_items_paginated(dataset_name:, page: nil, limit: nil, source_trace_id: nil, source_observation_id: nil) ⇒ Hash
private
Full paginated response including "meta" for internal pagination use.
-
#list_dataset_runs(dataset_name:, page: nil, limit: nil) ⇒ Array<Hash>
List dataset runs in a dataset.
-
#list_dataset_runs_paginated(dataset_name:, page: nil, limit: nil) ⇒ Hash
private
Full paginated response including "meta" for internal pagination use.
-
#list_datasets(page: nil, limit: nil) ⇒ Array<Hash>
List all datasets in the project.
-
#list_prompts(page: nil, limit: nil) ⇒ Array<Hash>
List all prompts in the Langfuse project.
-
#list_traces(page: nil, limit: nil, user_id: nil, name: nil, session_id: nil, from_timestamp: nil, to_timestamp: nil, order_by: nil, tags: nil, version: nil, release: nil, environment: nil, fields: nil, filter: nil) ⇒ Array<Hash>
List traces in the project.
-
#list_traces_paginated(page: nil, limit: nil, user_id: nil, name: nil, session_id: nil, from_timestamp: nil, to_timestamp: nil, order_by: nil, tags: nil, version: nil, release: nil, environment: nil, fields: nil, filter: nil) ⇒ Hash
private
Full paginated response including "meta" for internal pagination use.
-
#prompt_cache_key(name, version: nil, label: nil) ⇒ PromptCacheKey
Inspect the logical and generated cache keys for a prompt.
-
#prompt_cache_stats ⇒ Hash
Return prompt cache statistics.
-
#refresh_prompt(name, version: nil, label: nil, cache_ttl: nil) ⇒ PromptFetchResult
Refresh a prompt from the API, optionally writing through to cache.
-
#send_batch(events) ⇒ void
Send a batch of events to the Langfuse ingestion API.
-
#shutdown ⇒ void
Shut down the API client and release resources.
-
#update_prompt(name:, version:, labels:) ⇒ Hash
Update labels for an existing prompt version.
-
#validate_prompt_cache_backend! ⇒ Boolean
Validate the configured prompt cache backend.
Methods included from ReadApi
#list_observations, #list_scores, #query_metrics
Methods included from PromptCacheEvents
build_payload, #emit_prompt_cache_event, #emit_prompt_fallback_event, #setup_prompt_cache_events
Constructor Details
#initialize(public_key:, secret_key:, base_url:, timeout: 5, logger: nil, cache: nil, cache_observer: nil) ⇒ ApiClient
Initialize a new API client
rubocop:disable Metrics/ParameterLists
60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/langfuse/api_client.rb', line 60 def initialize(public_key:, secret_key:, base_url:, timeout: 5, logger: nil, cache: nil, cache_observer: nil) @public_key = public_key @secret_key = secret_key @base_url = base_url @timeout = timeout @logger = logger || Logger.new($stdout, level: Logger::WARN) @cache = cache setup_prompt_cache_events(cache_observer: cache_observer) @prompt_cache_coordinator = PromptCacheCoordinator.new( cache: cache, event_emitter: self, fetch_prompt: ->(name, version:, label:) { fetch_prompt_from_api(name, version: version, label: label) } ) end |
Instance Attribute Details
#base_url ⇒ String (readonly)
Returns Base URL for Langfuse API.
38 39 40 |
# File 'lib/langfuse/api_client.rb', line 38 def base_url @base_url end |
#cache ⇒ PromptCache, ... (readonly)
Returns Optional cache for prompt responses.
47 48 49 |
# File 'lib/langfuse/api_client.rb', line 47 def cache @cache end |
#logger ⇒ Logger (readonly)
Returns Logger instance for debugging.
44 45 46 |
# File 'lib/langfuse/api_client.rb', line 44 def logger @logger end |
#public_key ⇒ String (readonly)
Returns Langfuse public API key.
32 33 34 |
# File 'lib/langfuse/api_client.rb', line 32 def public_key @public_key end |
#secret_key ⇒ String (readonly)
Returns Langfuse secret API key.
35 36 37 |
# File 'lib/langfuse/api_client.rb', line 35 def secret_key @secret_key end |
#timeout ⇒ Integer (readonly)
Returns HTTP request timeout in seconds.
41 42 43 |
# File 'lib/langfuse/api_client.rb', line 41 def timeout @timeout end |
Instance Method Details
#clear_prompt_cache ⇒ Integer?
Logically clear the whole Langfuse prompt cache namespace.
194 195 196 |
# File 'lib/langfuse/api_client.rb', line 194 def clear_prompt_cache @prompt_cache_coordinator.clear_prompt_cache end |
#connection(timeout: nil) ⇒ Faraday::Connection
Get a Faraday connection
80 81 82 83 84 85 86 87 88 |
# File 'lib/langfuse/api_client.rb', line 80 def connection(timeout: nil) if timeout # Create dedicated connection for custom timeout # to avoid mutating shared connection build_connection(timeout: timeout) else @connection ||= build_connection end end |
#create_dataset(name:, description: nil, metadata: nil) ⇒ Hash
Create a new dataset
527 528 529 530 |
# File 'lib/langfuse/api_client.rb', line 527 def create_dataset(name:, description: nil, metadata: nil) request(:post, "/api/public/v2/datasets", body: { name: name, description: description, metadata: }.compact) end |
#create_dataset_item(dataset_name:, input: nil, expected_output: nil, metadata: nil, id: nil, source_trace_id: nil, source_observation_id: nil, status: nil) ⇒ Hash
Create a new dataset item (or upsert if id is provided)
rubocop:disable Metrics/ParameterLists
553 554 555 556 557 558 559 560 561 562 563 |
# File 'lib/langfuse/api_client.rb', line 553 def create_dataset_item(dataset_name:, input: nil, expected_output: nil, metadata: nil, id: nil, source_trace_id: nil, source_observation_id: nil, status: nil) payload = { datasetName: dataset_name, id: id, input: input, expectedOutput: expected_output, metadata: , sourceTraceId: source_trace_id, sourceObservationId: source_observation_id, status: status&.to_s&.upcase }.compact request(:post, "/api/public/dataset-items", body: payload) end |
#create_dataset_run_item(dataset_item_id:, run_name:, trace_id: nil, observation_id: nil, metadata: nil, run_description: nil) ⇒ Hash
Create a dataset run item (link a trace to a dataset item within a run)
337 338 339 340 341 342 343 344 345 |
# File 'lib/langfuse/api_client.rb', line 337 def create_dataset_run_item(dataset_item_id:, run_name:, trace_id: nil, observation_id: nil, metadata: nil, run_description: nil) payload = { datasetItemId: dataset_item_id, runName: run_name, traceId: trace_id, observationId: observation_id, metadata: , runDescription: run_description }.compact request(:post, "/api/public/dataset-run-items", body: payload) end |
#create_prompt(name:, prompt:, type:, config: {}, labels: [], tags: [], commit_message: nil) ⇒ Hash
Create a new prompt (or new version if prompt with same name exists)
rubocop:disable Metrics/ParameterLists
238 239 240 241 242 243 244 245 |
# File 'lib/langfuse/api_client.rb', line 238 def create_prompt(name:, prompt:, type:, config: {}, labels: [], tags: [], commit_message: nil) payload = { name: name, prompt: prompt, type: type, config: config, labels: labels, tags: , commitMessage: }.compact request(:post, "/api/public/v2/prompts", body: payload) .tap { @prompt_cache_coordinator.invalidate_after_mutation(name) } end |
#create_score(payload:) ⇒ String
Create a score through the synchronous Scores API.
315 316 317 318 319 320 321 |
# File 'lib/langfuse/api_client.rb', line 315 def create_score(payload:) response = request(:post, "/api/public/scores", body: payload) score_id = response["id"] return score_id if score_id.is_a?(String) && !score_id.empty? raise ApiError, "Score creation response did not include an id" end |
#delete_dataset_item(id) ⇒ Hash
404 responses are treated as success to keep DELETE idempotent across retries
Delete a dataset item by ID
620 621 622 623 624 625 626 627 628 629 |
# File 'lib/langfuse/api_client.rb', line 620 def delete_dataset_item(id) response = connection.delete("/api/public/dataset-items/#{URI.encode_uri_component(id)}") handle_delete_dataset_item_response(response, id) rescue Faraday::RetriableResponse => e logger.error("Faraday error: Retries exhausted - #{e.response.status}") handle_delete_dataset_item_response(e.response, id) rescue Faraday::Error => e logger.error("Faraday error: #{e.}") raise ApiError, "HTTP request failed: #{e.}" end |
#delete_dataset_run(dataset_name:, run_name:) ⇒ Hash?
404 responses raise NotFoundError to preserve strict delete semantics
Delete a dataset run by name
388 389 390 391 392 393 |
# File 'lib/langfuse/api_client.rb', line 388 def delete_dataset_run(dataset_name:, run_name:) with_faraday_error_handling do response = connection.delete(dataset_run_path(dataset_name: dataset_name, run_name: run_name)) response.status == 204 ? nil : handle_response(response) end end |
#get_dataset(name) ⇒ Hash
Fetch a dataset by name
512 513 514 |
# File 'lib/langfuse/api_client.rb', line 512 def get_dataset(name) request(:get, "/api/public/v2/datasets/#{URI.encode_uri_component(name)}") end |
#get_dataset_item(id) ⇒ Hash
Fetch a dataset item by ID
576 577 578 |
# File 'lib/langfuse/api_client.rb', line 576 def get_dataset_item(id) request(:get, "/api/public/dataset-items/#{URI.encode_uri_component(id)}") end |
#get_dataset_run(dataset_name:, run_name:) ⇒ Hash
Fetch a dataset run by dataset and run name
355 356 357 |
# File 'lib/langfuse/api_client.rb', line 355 def get_dataset_run(dataset_name:, run_name:) request(:get, dataset_run_path(dataset_name: dataset_name, run_name: run_name)) end |
#get_projects ⇒ Hash
Fetch projects accessible with the current API keys
404 405 406 |
# File 'lib/langfuse/api_client.rb', line 404 def get_projects # rubocop:disable Naming/AccessorMethodName request(:get, "/api/public/projects") end |
#get_prompt(name, version: nil, label: nil, cache_ttl: nil) ⇒ Hash
Fetch a prompt from the Langfuse API
Checks cache first if caching is enabled. On cache miss, fetches from API and stores in cache. When using Rails.cache backend, uses distributed lock to prevent cache stampedes.
125 126 127 |
# File 'lib/langfuse/api_client.rb', line 125 def get_prompt(name, version: nil, label: nil, cache_ttl: nil) get_prompt_result(name, version: version, label: label, cache_ttl: cache_ttl).prompt end |
#get_prompt_result(name, version: nil, label: nil, cache_ttl: nil) ⇒ PromptFetchResult
Fetch a prompt and include cache metadata.
141 142 143 |
# File 'lib/langfuse/api_client.rb', line 141 def get_prompt_result(name, version: nil, label: nil, cache_ttl: nil) @prompt_cache_coordinator.get_prompt_result(name, version: version, label: label, cache_ttl: cache_ttl) end |
#get_trace(id) ⇒ Hash
Fetch a trace by ID
484 485 486 |
# File 'lib/langfuse/api_client.rb', line 484 def get_trace(id) request(:get, "/api/public/traces/#{URI.encode_uri_component(id)}") end |
#invalidate_prompt_cache(name, version: nil, label: nil) ⇒ PromptCacheKey
Invalidate one exact logical prompt cache key.
179 180 181 |
# File 'lib/langfuse/api_client.rb', line 179 def invalidate_prompt_cache(name, version: nil, label: nil) @prompt_cache_coordinator.invalidate_prompt_cache(name, version: version, label: label) end |
#invalidate_prompt_cache_by_name(name) ⇒ Integer?
Invalidate all cached variants for one prompt name.
187 188 189 |
# File 'lib/langfuse/api_client.rb', line 187 def invalidate_prompt_cache_by_name(name) @prompt_cache_coordinator.invalidate_prompt_cache_by_name(name) end |
#list_dataset_items ⇒ Array<Hash>
List items in a dataset with optional filters
593 594 595 |
# File 'lib/langfuse/api_client.rb', line 593 def list_dataset_items(**) list_dataset_items_paginated(**)["data"] || [] end |
#list_dataset_items_paginated(dataset_name:, page: nil, limit: nil, source_trace_id: nil, source_observation_id: nil) ⇒ Hash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Full paginated response including "meta" for internal pagination use
601 602 603 604 605 606 607 608 |
# File 'lib/langfuse/api_client.rb', line 601 def list_dataset_items_paginated(dataset_name:, page: nil, limit: nil, source_trace_id: nil, source_observation_id: nil) params = { datasetName: dataset_name, page: page, limit: limit, sourceTraceId: source_trace_id, sourceObservationId: source_observation_id }.compact request(:get, "/api/public/dataset-items", params: params) end |
#list_dataset_runs(dataset_name:, page: nil, limit: nil) ⇒ Array<Hash>
List dataset runs in a dataset
367 368 369 |
# File 'lib/langfuse/api_client.rb', line 367 def list_dataset_runs(dataset_name:, page: nil, limit: nil) list_dataset_runs_paginated(dataset_name: dataset_name, page: page, limit: limit)["data"] || [] end |
#list_dataset_runs_paginated(dataset_name:, page: nil, limit: nil) ⇒ Hash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Full paginated response including "meta" for internal pagination use
375 376 377 |
# File 'lib/langfuse/api_client.rb', line 375 def list_dataset_runs_paginated(dataset_name:, page: nil, limit: nil) request(:get, dataset_runs_path(dataset_name), params: { page: page, limit: limit }.compact) end |
#list_datasets(page: nil, limit: nil) ⇒ Array<Hash>
List all datasets in the project
498 499 500 |
# File 'lib/langfuse/api_client.rb', line 498 def list_datasets(page: nil, limit: nil) request(:get, "/api/public/v2/datasets", params: { page: page, limit: limit }.compact)["data"] || [] end |
#list_prompts(page: nil, limit: nil) ⇒ Array<Hash>
List all prompts in the Langfuse project
Fetches a list of all prompt names available in your project. Note: This returns metadata only, not full prompt content.
106 107 108 |
# File 'lib/langfuse/api_client.rb', line 106 def list_prompts(page: nil, limit: nil) request(:get, "/api/public/v2/prompts", params: { page: page, limit: limit }.compact)["data"] || [] end |
#list_traces(page: nil, limit: nil, user_id: nil, name: nil, session_id: nil, from_timestamp: nil, to_timestamp: nil, order_by: nil, tags: nil, version: nil, release: nil, environment: nil, fields: nil, filter: nil) ⇒ Array<Hash>
List traces in the project
rubocop:disable Metrics/ParameterLists
440 441 442 443 444 445 446 447 448 449 450 451 |
# File 'lib/langfuse/api_client.rb', line 440 def list_traces(page: nil, limit: nil, user_id: nil, name: nil, session_id: nil, from_timestamp: nil, to_timestamp: nil, order_by: nil, tags: nil, version: nil, release: nil, environment: nil, fields: nil, filter: nil) list_traces_paginated( page: page, limit: limit, user_id: user_id, name: name, session_id: session_id, from_timestamp: , to_timestamp: , order_by: order_by, tags: , version: version, release: release, environment: environment, fields: fields, filter: filter )["data"] || [] end |
#list_traces_paginated(page: nil, limit: nil, user_id: nil, name: nil, session_id: nil, from_timestamp: nil, to_timestamp: nil, order_by: nil, tags: nil, version: nil, release: nil, environment: nil, fields: nil, filter: nil) ⇒ Hash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Full paginated response including "meta" for internal pagination use
rubocop:disable Metrics/ParameterLists
459 460 461 462 463 464 465 466 467 468 469 470 471 |
# File 'lib/langfuse/api_client.rb', line 459 def list_traces_paginated(page: nil, limit: nil, user_id: nil, name: nil, session_id: nil, from_timestamp: nil, to_timestamp: nil, order_by: nil, tags: nil, version: nil, release: nil, environment: nil, fields: nil, filter: nil) params = build_traces_params( page: page, limit: limit, user_id: user_id, name: name, session_id: session_id, from_timestamp: , to_timestamp: , order_by: order_by, tags: , version: version, release: release, environment: environment, fields: fields, filter: filter ) request(:get, "/api/public/traces", params: params) end |
#prompt_cache_key(name, version: nil, label: nil) ⇒ PromptCacheKey
Inspect the logical and generated cache keys for a prompt.
168 169 170 |
# File 'lib/langfuse/api_client.rb', line 168 def prompt_cache_key(name, version: nil, label: nil) @prompt_cache_coordinator.prompt_cache_key(name, version: version, label: label) end |
#prompt_cache_stats ⇒ Hash
Return prompt cache statistics.
201 202 203 |
# File 'lib/langfuse/api_client.rb', line 201 def prompt_cache_stats @prompt_cache_coordinator.prompt_cache_stats end |
#refresh_prompt(name, version: nil, label: nil, cache_ttl: nil) ⇒ PromptFetchResult
Refresh a prompt from the API, optionally writing through to cache.
157 158 159 |
# File 'lib/langfuse/api_client.rb', line 157 def refresh_prompt(name, version: nil, label: nil, cache_ttl: nil) @prompt_cache_coordinator.refresh_prompt(name, version: version, label: label, cache_ttl: cache_ttl) end |
#send_batch(events) ⇒ void
This method returns an undefined value.
Send a batch of events to the Langfuse ingestion API
Sends events (scores, traces, observations) to the ingestion endpoint. Retries transient errors (429, 503, 504, network errors) with exponential backoff. Batch operations are idempotent (events have unique IDs), so retries are safe.
295 296 297 298 299 300 301 302 303 304 305 306 307 |
# File 'lib/langfuse/api_client.rb', line 295 def send_batch(events) raise ArgumentError, "events must be an array" unless events.is_a?(Array) raise ArgumentError, "events array cannot be empty" if events.empty? response = connection.post("/api/public/ingestion", { batch: events }) handle_batch_response(response) rescue Faraday::RetriableResponse => e logger.error("Langfuse batch send failed: Retries exhausted - #{e.response.status}") handle_batch_response(e.response) rescue Faraday::Error => e logger.error("Langfuse batch send failed: #{e.}") raise BatchDeliveryError.new("Batch send failed: #{e.}", retryable: true) end |
#shutdown ⇒ void
This method returns an undefined value.
Shut down the API client and release resources
Shuts down the cache backend's SWR thread pool when present.
413 414 415 |
# File 'lib/langfuse/api_client.rb', line 413 def shutdown @cache&.shutdown end |
#update_prompt(name:, version:, labels:) ⇒ Hash
Update labels for an existing prompt version
265 266 267 268 269 270 271 |
# File 'lib/langfuse/api_client.rb', line 265 def update_prompt(name:, version:, labels:) raise ArgumentError, "labels must be an array" unless labels.is_a?(Array) path = "/api/public/v2/prompts/#{URI.encode_uri_component(name)}/versions/#{version}" request(:patch, path, body: { newLabels: labels }) .tap { @prompt_cache_coordinator.invalidate_after_mutation(name) } end |
#validate_prompt_cache_backend! ⇒ Boolean
Validate the configured prompt cache backend.
rubocop:disable Naming/PredicateMethod
210 211 212 213 |
# File 'lib/langfuse/api_client.rb', line 210 def validate_prompt_cache_backend! @cache&.validate! true end |