Class: Langfuse::ApiClient
- Inherits:
-
Object
- Object
- Langfuse::ApiClient
- Includes:
- PromptCacheEvents
- 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.
Defined Under Namespace
Classes: PromptFetchOptions
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).
-
#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(dataset_name:, page: nil, limit: nil, source_trace_id: nil, source_observation_id: nil) ⇒ 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.
Methods included from PromptCacheEvents
#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
65 66 67 68 69 70 71 72 73 74 |
# File 'lib/langfuse/api_client.rb', line 65 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 @cache_backend_name = compute_cache_backend_name setup_prompt_cache_events(cache_observer: cache_observer) end |
Instance Attribute Details
#base_url ⇒ String (readonly)
Returns Base URL for Langfuse API.
43 44 45 |
# File 'lib/langfuse/api_client.rb', line 43 def base_url @base_url end |
#cache ⇒ PromptCache, ... (readonly)
Returns Optional cache for prompt responses.
52 53 54 |
# File 'lib/langfuse/api_client.rb', line 52 def cache @cache end |
#logger ⇒ Logger (readonly)
Returns Logger instance for debugging.
49 50 51 |
# File 'lib/langfuse/api_client.rb', line 49 def logger @logger end |
#public_key ⇒ String (readonly)
Returns Langfuse public API key.
37 38 39 |
# File 'lib/langfuse/api_client.rb', line 37 def public_key @public_key end |
#secret_key ⇒ String (readonly)
Returns Langfuse secret API key.
40 41 42 |
# File 'lib/langfuse/api_client.rb', line 40 def secret_key @secret_key end |
#timeout ⇒ Integer (readonly)
Returns HTTP request timeout in seconds.
46 47 48 |
# File 'lib/langfuse/api_client.rb', line 46 def timeout @timeout end |
Instance Method Details
#clear_prompt_cache ⇒ Integer?
Logically clear the whole Langfuse prompt cache namespace.
236 237 238 239 240 |
# File 'lib/langfuse/api_client.rb', line 236 def clear_prompt_cache generation = cache&.clear_logically emit_prompt_cache_event(:clear, backend: cache_backend_name, generation: generation) generation end |
#connection(timeout: nil) ⇒ Faraday::Connection
Get a Faraday connection
81 82 83 84 85 86 87 88 89 |
# File 'lib/langfuse/api_client.rb', line 81 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
597 598 599 600 601 602 603 604 |
# File 'lib/langfuse/api_client.rb', line 597 def create_dataset(name:, description: nil, metadata: nil) with_faraday_error_handling do payload = { name: name, description: description, metadata: }.compact response = connection.post("/api/public/v2/datasets", payload) handle_response(response) end 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
627 628 629 630 631 632 633 634 635 636 637 638 639 640 |
# File 'lib/langfuse/api_client.rb', line 627 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) with_faraday_error_handling do payload = build_dataset_item_payload( dataset_name: dataset_name, input: input, expected_output: expected_output, metadata: , id: id, source_trace_id: source_trace_id, source_observation_id: source_observation_id, status: status ) response = connection.post("/api/public/dataset-items", payload) handle_response(response) end 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)
375 376 377 378 379 380 381 382 383 384 385 386 387 |
# File 'lib/langfuse/api_client.rb', line 375 def create_dataset_run_item(dataset_item_id:, run_name:, trace_id: nil, observation_id: nil, metadata: nil, run_description: nil) with_faraday_error_handling do payload = { datasetItemId: dataset_item_id, runName: run_name } payload[:traceId] = trace_id if trace_id payload[:observationId] = observation_id if observation_id payload[:metadata] = if payload[:runDescription] = run_description if run_description response = connection.post("/api/public/dataset-run-items", payload) handle_response(response) end 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
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/langfuse/api_client.rb', line 273 def create_prompt(name:, prompt:, type:, config: {}, labels: [], tags: [], commit_message: nil) with_faraday_error_handling do path = "/api/public/v2/prompts" payload = { name: name, prompt: prompt, type: type, config: config, labels: labels, tags: } payload[:commitMessage] = if response = connection.post(path, payload) handle_response(response).tap { invalidate_prompt_cache_after_mutation(name) } end end |
#delete_dataset_item(id) ⇒ Hash
404 responses are treated as success to keep DELETE idempotent across retries
Delete a dataset item by ID
710 711 712 713 714 715 716 717 718 719 720 |
# File 'lib/langfuse/api_client.rb', line 710 def delete_dataset_item(id) encoded_id = URI.encode_uri_component(id) response = connection.delete("/api/public/dataset-items/#{encoded_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
437 438 439 440 441 442 |
# File 'lib/langfuse/api_client.rb', line 437 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
578 579 580 581 582 583 584 |
# File 'lib/langfuse/api_client.rb', line 578 def get_dataset(name) with_faraday_error_handling do encoded_name = URI.encode_uri_component(name) response = connection.get("/api/public/v2/datasets/#{encoded_name}") handle_response(response) end end |
#get_dataset_item(id) ⇒ Hash
Fetch a dataset item by ID
653 654 655 656 657 658 659 |
# File 'lib/langfuse/api_client.rb', line 653 def get_dataset_item(id) with_faraday_error_handling do encoded_id = URI.encode_uri_component(id) response = connection.get("/api/public/dataset-items/#{encoded_id}") handle_response(response) end end |
#get_dataset_run(dataset_name:, run_name:) ⇒ Hash
Fetch a dataset run by dataset and run name
397 398 399 400 401 402 |
# File 'lib/langfuse/api_client.rb', line 397 def get_dataset_run(dataset_name:, run_name:) with_faraday_error_handling do response = connection.get(dataset_run_path(dataset_name: dataset_name, run_name: run_name)) handle_response(response) end end |
#get_projects ⇒ Hash
Fetch projects accessible with the current API keys
453 454 455 456 457 458 |
# File 'lib/langfuse/api_client.rb', line 453 def get_projects # rubocop:disable Naming/AccessorMethodName with_faraday_error_handling do response = connection.get("/api/public/projects") handle_response(response) end 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.
134 135 136 |
# File 'lib/langfuse/api_client.rb', line 134 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.
150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/langfuse/api_client.rb', line 150 def get_prompt_result(name, version: nil, label: nil, cache_ttl: nil) (version, label, cache_ttl) = PromptFetchOptions.new( key: prompt_cache_key(name, version: version, label: label), cache_ttl: cache_ttl ) return fetch_uncached_prompt_result(, CacheStatus::DISABLED) if cache.nil? return fetch_uncached_prompt_result(, CacheStatus::BYPASS) if cache_ttl&.zero? fetch_cached_prompt_result() end |
#get_trace(id) ⇒ Hash
Fetch a trace by ID
540 541 542 543 544 545 546 |
# File 'lib/langfuse/api_client.rb', line 540 def get_trace(id) with_faraday_error_handling do encoded_id = URI.encode_uri_component(id) response = connection.get("/api/public/traces/#{encoded_id}") handle_response(response) end end |
#invalidate_prompt_cache(name, version: nil, label: nil) ⇒ PromptCacheKey
Invalidate one exact logical prompt cache key.
212 213 214 215 216 217 218 219 220 |
# File 'lib/langfuse/api_client.rb', line 212 def invalidate_prompt_cache(name, version: nil, label: nil) key = prompt_cache_key(name, version: version, label: label) deleted = cache&.delete(key.storage_key) || false emit_prompt_cache_event(:delete) { event_payload(key, CacheStatus::MISS, CacheSource::CACHE, deleted: deleted) } emit_prompt_cache_event(:invalidate) do event_payload(key, CacheStatus::MISS, CacheSource::CACHE, scope: :exact) end key end |
#invalidate_prompt_cache_by_name(name) ⇒ Integer?
Invalidate all cached variants for one prompt name.
226 227 228 229 230 231 |
# File 'lib/langfuse/api_client.rb', line 226 def invalidate_prompt_cache_by_name(name) generation = cache&.invalidate_name(name) payload = { name: name, backend: cache_backend_name, generation: generation, scope: :name } emit_prompt_cache_event(:invalidate, payload) generation end |
#list_dataset_items(dataset_name:, page: nil, limit: nil, source_trace_id: nil, source_observation_id: nil) ⇒ Array<Hash>
List items in a dataset with optional filters
674 675 676 677 678 679 680 681 |
# File 'lib/langfuse/api_client.rb', line 674 def list_dataset_items(dataset_name:, page: nil, limit: nil, source_trace_id: nil, source_observation_id: nil) result = list_dataset_items_paginated( dataset_name: dataset_name, page: page, limit: limit, source_trace_id: source_trace_id, source_observation_id: source_observation_id ) result["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
687 688 689 690 691 692 693 694 695 696 697 698 |
# File 'lib/langfuse/api_client.rb', line 687 def list_dataset_items_paginated(dataset_name:, page: nil, limit: nil, source_trace_id: nil, source_observation_id: nil) with_faraday_error_handling do params = build_dataset_items_params( dataset_name: dataset_name, page: page, limit: limit, source_trace_id: source_trace_id, source_observation_id: source_observation_id ) response = connection.get("/api/public/dataset-items", params) handle_response(response) end end |
#list_dataset_runs(dataset_name:, page: nil, limit: nil) ⇒ Array<Hash>
List dataset runs in a dataset
412 413 414 415 |
# File 'lib/langfuse/api_client.rb', line 412 def list_dataset_runs(dataset_name:, page: nil, limit: nil) result = list_dataset_runs_paginated(dataset_name: dataset_name, page: page, limit: limit) result["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
421 422 423 424 425 426 |
# File 'lib/langfuse/api_client.rb', line 421 def list_dataset_runs_paginated(dataset_name:, page: nil, limit: nil) with_faraday_error_handling do response = connection.get(dataset_runs_path(dataset_name), build_dataset_runs_params(page: page, limit: limit)) handle_response(response) end end |
#list_datasets(page: nil, limit: nil) ⇒ Array<Hash>
List all datasets in the project
558 559 560 561 562 563 564 565 566 |
# File 'lib/langfuse/api_client.rb', line 558 def list_datasets(page: nil, limit: nil) with_faraday_error_handling do params = { page: page, limit: limit }.compact response = connection.get("/api/public/v2/datasets", params) result = handle_response(response) result["data"] || [] end 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.
107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/langfuse/api_client.rb', line 107 def list_prompts(page: nil, limit: nil) with_faraday_error_handling do params = { page: page, limit: limit }.compact response = connection.get("/api/public/v2/prompts", params) result = handle_response(response) # API returns { data: [...], meta: {...} } result["data"] || [] end 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
492 493 494 495 496 497 498 499 500 501 502 503 504 |
# File 'lib/langfuse/api_client.rb', line 492 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) result = 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 ) result["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
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 |
# File 'lib/langfuse/api_client.rb', line 512 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) with_faraday_error_handling do 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 ) response = connection.get("/api/public/traces", params) handle_response(response) end end |
#prompt_cache_key(name, version: nil, label: nil) ⇒ PromptCacheKey
Inspect the logical and generated cache keys for a prompt.
193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/langfuse/api_client.rb', line 193 def prompt_cache_key(name, version: nil, label: nil) raise ArgumentError, "Cannot specify both version and label" if version && label logical_key = PromptCache.build_key(name, version: version, label: label) storage_key = if generated_storage_key_cache? cache.storage_key(logical_key, name: name) else logical_key end PromptCacheKey.new(name: name, version: version, label: label, logical_key: logical_key, storage_key: storage_key) end |
#prompt_cache_stats ⇒ Hash
Return prompt cache statistics.
245 246 247 248 249 |
# File 'lib/langfuse/api_client.rb', line 245 def prompt_cache_stats return disabled_prompt_cache_stats unless cache 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.
175 176 177 178 179 180 181 182 183 184 |
# File 'lib/langfuse/api_client.rb', line 175 def refresh_prompt(name, version: nil, label: nil, cache_ttl: nil) (version, label, cache_ttl) refresh_prompt_result( PromptFetchOptions.new( key: prompt_cache_key(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.
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
# File 'lib/langfuse/api_client.rb', line 343 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? path = "/api/public/ingestion" payload = { batch: events } response = connection.post(path, payload) handle_batch_response(response) rescue Faraday::RetriableResponse => e # Retry middleware exhausted all retries - handle the final response 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 ApiError, "Batch send failed: #{e.}" end |
#shutdown ⇒ void
This method returns an undefined value.
Shut down the API client and release resources
Shuts down the cache if it supports shutdown (e.g., SWR thread pool).
465 466 467 |
# File 'lib/langfuse/api_client.rb', line 465 def shutdown cache.shutdown if cache.respond_to?(:shutdown) end |
#update_prompt(name:, version:, labels:) ⇒ Hash
Update labels for an existing prompt version
309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/langfuse/api_client.rb', line 309 def update_prompt(name:, version:, labels:) raise ArgumentError, "labels must be an array" unless labels.is_a?(Array) with_faraday_error_handling do path = "/api/public/v2/prompts/#{URI.encode_uri_component(name)}/versions/#{version}" payload = { newLabels: labels } response = connection.patch(path, payload) handle_response(response).tap { invalidate_prompt_cache_after_mutation(name) } end end |