langsmith 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.cjs CHANGED
@@ -46,6 +46,7 @@ const _uuid_js_1 = require("./utils/_uuid.cjs");
46
46
  const warn_js_1 = require("./utils/warn.cjs");
47
47
  const prompts_js_1 = require("./utils/prompts.cjs");
48
48
  const error_js_1 = require("./utils/error.cjs");
49
+ const prompts_cache_js_1 = require("./utils/prompts_cache.cjs");
49
50
  const fetch_js_1 = require("./singletons/fetch.cjs");
50
51
  const index_js_2 = require("./utils/fast-safe-stringify/index.cjs");
51
52
  function mergeRuntimeEnvIntoRun(run, cachedEnvVars, omitTracedRuntimeInfo) {
@@ -410,6 +411,12 @@ class Client {
410
411
  writable: true,
411
412
  value: void 0
412
413
  });
414
+ Object.defineProperty(this, "_promptCache", {
415
+ enumerable: true,
416
+ configurable: true,
417
+ writable: true,
418
+ value: void 0
419
+ });
413
420
  Object.defineProperty(this, "multipartStreamingDisabled", {
414
421
  enumerable: true,
415
422
  configurable: true,
@@ -481,6 +488,27 @@ class Client {
481
488
  }
482
489
  // Cache metadata env vars once during construction to avoid repeatedly scanning process.env
483
490
  this.cachedLSEnvVarsForMetadata = (0, env_js_1.getLangSmithEnvVarsMetadata)();
491
+ // Initialize prompt cache
492
+ const cacheEnabled = config.promptCacheEnabled ??
493
+ (0, env_js_1.getLangSmithEnvironmentVariable)("PROMPT_CACHE_ENABLED") === "true";
494
+ if (cacheEnabled) {
495
+ this._promptCache = new prompts_cache_js_1.PromptCache({
496
+ maxSize: config.promptCacheMaxSize ??
497
+ parseInt((0, env_js_1.getLangSmithEnvironmentVariable)("PROMPT_CACHE_MAX_SIZE") ?? "100", 10),
498
+ ttlSeconds: config.promptCacheTtlSeconds ??
499
+ parseFloat((0, env_js_1.getLangSmithEnvironmentVariable)("PROMPT_CACHE_TTL_SECONDS") ??
500
+ "3600"),
501
+ refreshIntervalSeconds: config.promptCacheRefreshIntervalSeconds ??
502
+ parseFloat((0, env_js_1.getLangSmithEnvironmentVariable)("PROMPT_CACHE_REFRESH_INTERVAL_SECONDS") ?? "60"),
503
+ fetchFunc: this._makeFetchPromptFunc(),
504
+ });
505
+ // Load from file if path provided
506
+ const cachePath = config.promptCachePath ??
507
+ (0, env_js_1.getLangSmithEnvironmentVariable)("PROMPT_CACHE_PATH");
508
+ if (cachePath) {
509
+ this._promptCache.load(cachePath);
510
+ }
511
+ }
484
512
  }
485
513
  static getDefaultClientConfig() {
486
514
  const apiKey = (0, env_js_1.getLangSmithEnvironmentVariable)("API_KEY");
@@ -3784,7 +3812,29 @@ class Client {
3784
3812
  });
3785
3813
  return response.json();
3786
3814
  }
3787
- async pullPromptCommit(promptIdentifier, options) {
3815
+ /**
3816
+ * Generate a cache key for a prompt.
3817
+ * Format: "{identifier}" or "{identifier}:with_model"
3818
+ */
3819
+ _getPromptCacheKey(promptIdentifier, includeModel) {
3820
+ const suffix = includeModel ? ":with_model" : "";
3821
+ return `${promptIdentifier}${suffix}`;
3822
+ }
3823
+ /**
3824
+ * Create a fetch function for the prompt cache to use for background refresh.
3825
+ */
3826
+ _makeFetchPromptFunc() {
3827
+ return async (key) => {
3828
+ // Parse the cache key back to identifier and options
3829
+ const includeModel = key.endsWith(":with_model");
3830
+ const identifier = includeModel ? key.slice(0, -11) : key; // Remove ":with_model"
3831
+ return this._fetchPromptFromApi(identifier, { includeModel });
3832
+ };
3833
+ }
3834
+ /**
3835
+ * Fetch a prompt commit directly from the API (bypassing cache).
3836
+ */
3837
+ async _fetchPromptFromApi(promptIdentifier, options) {
3788
3838
  const [owner, promptName, commitHash] = (0, prompts_js_1.parsePromptIdentifier)(promptIdentifier);
3789
3839
  const response = await this.caller.call(async () => {
3790
3840
  const res = await this._fetch(`${this.apiUrl}/commits/${owner}/${promptName}/${commitHash}${options?.includeModel ? "?include_model=true" : ""}`, {
@@ -3805,6 +3855,22 @@ class Client {
3805
3855
  examples: result.examples,
3806
3856
  };
3807
3857
  }
3858
+ async pullPromptCommit(promptIdentifier, options) {
3859
+ // Check cache first if not skipped
3860
+ if (!options?.skipCache && this._promptCache) {
3861
+ const cacheKey = this._getPromptCacheKey(promptIdentifier, options?.includeModel);
3862
+ const cached = this._promptCache.get(cacheKey);
3863
+ if (cached) {
3864
+ return cached;
3865
+ }
3866
+ // Cache miss - fetch from API and cache it
3867
+ const result = await this._fetchPromptFromApi(promptIdentifier, options);
3868
+ this._promptCache.set(cacheKey, result);
3869
+ return result;
3870
+ }
3871
+ // No cache or skip cache - fetch directly
3872
+ return this._fetchPromptFromApi(promptIdentifier, options);
3873
+ }
3808
3874
  /**
3809
3875
  * This method should not be used directly, use `import { pull } from "langchain/hub"` instead.
3810
3876
  * Using this method directly returns the JSON string of the prompt rather than a LangChain object.
@@ -3813,6 +3879,7 @@ class Client {
3813
3879
  async _pullPrompt(promptIdentifier, options) {
3814
3880
  const promptObject = await this.pullPromptCommit(promptIdentifier, {
3815
3881
  includeModel: options?.includeModel,
3882
+ skipCache: options?.skipCache,
3816
3883
  });
3817
3884
  const prompt = JSON.stringify(promptObject.manifest);
3818
3885
  return prompt;
@@ -3927,6 +3994,22 @@ class Client {
3927
3994
  throw new Error(`Invalid public ${kind} URL or token: ${urlOrToken}`);
3928
3995
  }
3929
3996
  }
3997
+ /**
3998
+ * Get the prompt cache instance, if caching is enabled.
3999
+ * Useful for accessing cache metrics or manually managing the cache.
4000
+ */
4001
+ get promptCache() {
4002
+ return this._promptCache;
4003
+ }
4004
+ /**
4005
+ * Cleanup resources held by the client.
4006
+ * Stops the prompt cache's background refresh timer.
4007
+ */
4008
+ cleanup() {
4009
+ if (this._promptCache) {
4010
+ this._promptCache.stop();
4011
+ }
4012
+ }
3930
4013
  /**
3931
4014
  * Awaits all pending trace batches. Useful for environments where
3932
4015
  * you need to be sure that all tracing requests finish before execution ends,
package/dist/client.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { OTELContext } from "./experimental/otel/types.js";
2
2
  import { AsyncCallerParams } from "./utils/async_caller.js";
3
3
  import { ComparativeExperiment, DataType, Dataset, DatasetDiffInfo, DatasetShareSchema, Example, ExampleCreate, ExampleUpdate, ExampleUpdateWithoutId, Feedback, FeedbackConfig, FeedbackIngestToken, KVMap, LangChainBaseMessage, LangSmithSettings, LikePromptResponse, Prompt, PromptCommit, PromptSortField, Run, RunCreate, RunUpdate, ScoreType, ExampleSearch, TimeDelta, TracerSession, TracerSessionResult, ValueType, AnnotationQueue, RunWithAnnotationQueueInfo, Attachments, UploadExamplesResponse, UpdateExamplesResponse, DatasetVersion, AnnotationQueueWithDetails } from "./schemas.js";
4
4
  import { EvaluationResult, EvaluationResults } from "./evaluation/evaluator.js";
5
+ import { PromptCache } from "./utils/prompts_cache.js";
5
6
  export interface ClientConfig {
6
7
  apiUrl?: string;
7
8
  apiKey?: string;
@@ -49,6 +50,29 @@ export interface ClientConfig {
49
50
  * Custom fetch implementation. Useful for testing.
50
51
  */
51
52
  fetchImplementation?: typeof fetch;
53
+ /**
54
+ * Whether to enable prompt caching. Defaults to false.
55
+ */
56
+ promptCacheEnabled?: boolean;
57
+ /**
58
+ * Maximum number of prompts to cache. Defaults to 100.
59
+ */
60
+ promptCacheMaxSize?: number;
61
+ /**
62
+ * Time-to-live for cached prompts in seconds. After this time, cached prompts
63
+ * are considered stale and will be refreshed in the background.
64
+ * Set to null for infinite TTL (offline mode). Defaults to 3600 (1 hour).
65
+ */
66
+ promptCacheTtlSeconds?: number | null;
67
+ /**
68
+ * How often to check for stale cache entries in seconds. Defaults to 60.
69
+ */
70
+ promptCacheRefreshIntervalSeconds?: number;
71
+ /**
72
+ * Path to a JSON file to load cached prompts from on initialization.
73
+ * Useful for offline mode.
74
+ */
75
+ promptCachePath?: string;
52
76
  }
53
77
  /**
54
78
  * Represents the parameters for listing runs (spans) from the Langsmith server.
@@ -351,6 +375,7 @@ export declare class Client implements LangSmithTracingClientInterface {
351
375
  private langSmithToOTELTranslator?;
352
376
  private fetchImplementation?;
353
377
  private cachedLSEnvVarsForMetadata?;
378
+ private _promptCache?;
354
379
  private get _fetch();
355
380
  private multipartStreamingDisabled;
356
381
  private _multipartDisabled;
@@ -995,8 +1020,22 @@ export declare class Client implements LangSmithTracingClientInterface {
995
1020
  isArchived?: boolean;
996
1021
  }): Promise<Record<string, any>>;
997
1022
  deletePrompt(promptIdentifier: string): Promise<void>;
1023
+ /**
1024
+ * Generate a cache key for a prompt.
1025
+ * Format: "{identifier}" or "{identifier}:with_model"
1026
+ */
1027
+ private _getPromptCacheKey;
1028
+ /**
1029
+ * Create a fetch function for the prompt cache to use for background refresh.
1030
+ */
1031
+ private _makeFetchPromptFunc;
1032
+ /**
1033
+ * Fetch a prompt commit directly from the API (bypassing cache).
1034
+ */
1035
+ private _fetchPromptFromApi;
998
1036
  pullPromptCommit(promptIdentifier: string, options?: {
999
1037
  includeModel?: boolean;
1038
+ skipCache?: boolean;
1000
1039
  }): Promise<PromptCommit>;
1001
1040
  /**
1002
1041
  * This method should not be used directly, use `import { pull } from "langchain/hub"` instead.
@@ -1005,6 +1044,7 @@ export declare class Client implements LangSmithTracingClientInterface {
1005
1044
  */
1006
1045
  _pullPrompt(promptIdentifier: string, options?: {
1007
1046
  includeModel?: boolean;
1047
+ skipCache?: boolean;
1008
1048
  }): Promise<any>;
1009
1049
  pushPrompt(promptIdentifier: string, options?: {
1010
1050
  object?: any;
@@ -1030,6 +1070,16 @@ export declare class Client implements LangSmithTracingClientInterface {
1030
1070
  datasetName?: string;
1031
1071
  }): Promise<void>;
1032
1072
  private parseTokenOrUrl;
1073
+ /**
1074
+ * Get the prompt cache instance, if caching is enabled.
1075
+ * Useful for accessing cache metrics or manually managing the cache.
1076
+ */
1077
+ get promptCache(): PromptCache | undefined;
1078
+ /**
1079
+ * Cleanup resources held by the client.
1080
+ * Stops the prompt cache's background refresh timer.
1081
+ */
1082
+ cleanup(): void;
1033
1083
  /**
1034
1084
  * Awaits all pending trace batches. Useful for environments where
1035
1085
  * you need to be sure that all tracing requests finish before execution ends,
package/dist/client.js CHANGED
@@ -9,6 +9,7 @@ import { assertUuid } from "./utils/_uuid.js";
9
9
  import { warnOnce } from "./utils/warn.js";
10
10
  import { parsePromptIdentifier } from "./utils/prompts.js";
11
11
  import { raiseForStatus, isLangSmithNotFoundError } from "./utils/error.js";
12
+ import { PromptCache } from "./utils/prompts_cache.js";
12
13
  import { _globalFetchImplementationIsNodeFetch, _getFetchImplementation, } from "./singletons/fetch.js";
13
14
  import { serialize as serializePayloadForTracing } from "./utils/fast-safe-stringify/index.js";
14
15
  export function mergeRuntimeEnvIntoRun(run, cachedEnvVars, omitTracedRuntimeInfo) {
@@ -372,6 +373,12 @@ export class Client {
372
373
  writable: true,
373
374
  value: void 0
374
375
  });
376
+ Object.defineProperty(this, "_promptCache", {
377
+ enumerable: true,
378
+ configurable: true,
379
+ writable: true,
380
+ value: void 0
381
+ });
375
382
  Object.defineProperty(this, "multipartStreamingDisabled", {
376
383
  enumerable: true,
377
384
  configurable: true,
@@ -443,6 +450,27 @@ export class Client {
443
450
  }
444
451
  // Cache metadata env vars once during construction to avoid repeatedly scanning process.env
445
452
  this.cachedLSEnvVarsForMetadata = getLangSmithEnvVarsMetadata();
453
+ // Initialize prompt cache
454
+ const cacheEnabled = config.promptCacheEnabled ??
455
+ getLangSmithEnvironmentVariable("PROMPT_CACHE_ENABLED") === "true";
456
+ if (cacheEnabled) {
457
+ this._promptCache = new PromptCache({
458
+ maxSize: config.promptCacheMaxSize ??
459
+ parseInt(getLangSmithEnvironmentVariable("PROMPT_CACHE_MAX_SIZE") ?? "100", 10),
460
+ ttlSeconds: config.promptCacheTtlSeconds ??
461
+ parseFloat(getLangSmithEnvironmentVariable("PROMPT_CACHE_TTL_SECONDS") ??
462
+ "3600"),
463
+ refreshIntervalSeconds: config.promptCacheRefreshIntervalSeconds ??
464
+ parseFloat(getLangSmithEnvironmentVariable("PROMPT_CACHE_REFRESH_INTERVAL_SECONDS") ?? "60"),
465
+ fetchFunc: this._makeFetchPromptFunc(),
466
+ });
467
+ // Load from file if path provided
468
+ const cachePath = config.promptCachePath ??
469
+ getLangSmithEnvironmentVariable("PROMPT_CACHE_PATH");
470
+ if (cachePath) {
471
+ this._promptCache.load(cachePath);
472
+ }
473
+ }
446
474
  }
447
475
  static getDefaultClientConfig() {
448
476
  const apiKey = getLangSmithEnvironmentVariable("API_KEY");
@@ -3746,7 +3774,29 @@ export class Client {
3746
3774
  });
3747
3775
  return response.json();
3748
3776
  }
3749
- async pullPromptCommit(promptIdentifier, options) {
3777
+ /**
3778
+ * Generate a cache key for a prompt.
3779
+ * Format: "{identifier}" or "{identifier}:with_model"
3780
+ */
3781
+ _getPromptCacheKey(promptIdentifier, includeModel) {
3782
+ const suffix = includeModel ? ":with_model" : "";
3783
+ return `${promptIdentifier}${suffix}`;
3784
+ }
3785
+ /**
3786
+ * Create a fetch function for the prompt cache to use for background refresh.
3787
+ */
3788
+ _makeFetchPromptFunc() {
3789
+ return async (key) => {
3790
+ // Parse the cache key back to identifier and options
3791
+ const includeModel = key.endsWith(":with_model");
3792
+ const identifier = includeModel ? key.slice(0, -11) : key; // Remove ":with_model"
3793
+ return this._fetchPromptFromApi(identifier, { includeModel });
3794
+ };
3795
+ }
3796
+ /**
3797
+ * Fetch a prompt commit directly from the API (bypassing cache).
3798
+ */
3799
+ async _fetchPromptFromApi(promptIdentifier, options) {
3750
3800
  const [owner, promptName, commitHash] = parsePromptIdentifier(promptIdentifier);
3751
3801
  const response = await this.caller.call(async () => {
3752
3802
  const res = await this._fetch(`${this.apiUrl}/commits/${owner}/${promptName}/${commitHash}${options?.includeModel ? "?include_model=true" : ""}`, {
@@ -3767,6 +3817,22 @@ export class Client {
3767
3817
  examples: result.examples,
3768
3818
  };
3769
3819
  }
3820
+ async pullPromptCommit(promptIdentifier, options) {
3821
+ // Check cache first if not skipped
3822
+ if (!options?.skipCache && this._promptCache) {
3823
+ const cacheKey = this._getPromptCacheKey(promptIdentifier, options?.includeModel);
3824
+ const cached = this._promptCache.get(cacheKey);
3825
+ if (cached) {
3826
+ return cached;
3827
+ }
3828
+ // Cache miss - fetch from API and cache it
3829
+ const result = await this._fetchPromptFromApi(promptIdentifier, options);
3830
+ this._promptCache.set(cacheKey, result);
3831
+ return result;
3832
+ }
3833
+ // No cache or skip cache - fetch directly
3834
+ return this._fetchPromptFromApi(promptIdentifier, options);
3835
+ }
3770
3836
  /**
3771
3837
  * This method should not be used directly, use `import { pull } from "langchain/hub"` instead.
3772
3838
  * Using this method directly returns the JSON string of the prompt rather than a LangChain object.
@@ -3775,6 +3841,7 @@ export class Client {
3775
3841
  async _pullPrompt(promptIdentifier, options) {
3776
3842
  const promptObject = await this.pullPromptCommit(promptIdentifier, {
3777
3843
  includeModel: options?.includeModel,
3844
+ skipCache: options?.skipCache,
3778
3845
  });
3779
3846
  const prompt = JSON.stringify(promptObject.manifest);
3780
3847
  return prompt;
@@ -3889,6 +3956,22 @@ export class Client {
3889
3956
  throw new Error(`Invalid public ${kind} URL or token: ${urlOrToken}`);
3890
3957
  }
3891
3958
  }
3959
+ /**
3960
+ * Get the prompt cache instance, if caching is enabled.
3961
+ * Useful for accessing cache metrics or manually managing the cache.
3962
+ */
3963
+ get promptCache() {
3964
+ return this._promptCache;
3965
+ }
3966
+ /**
3967
+ * Cleanup resources held by the client.
3968
+ * Stops the prompt cache's background refresh timer.
3969
+ */
3970
+ cleanup() {
3971
+ if (this._promptCache) {
3972
+ this._promptCache.stop();
3973
+ }
3974
+ }
3892
3975
  /**
3893
3976
  * Awaits all pending trace batches. Useful for environments where
3894
3977
  * you need to be sure that all tracing requests finish before execution ends,