vercel.cjs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.wrapAISDKModel = void 0;
  4. const traceable_js_1 = require("../traceable.cjs");
  5. const generic_js_1 = require("./generic.cjs");
  6. /**
  7. * Wrap a Vercel AI SDK model, enabling automatic LangSmith tracing.
  8. * After wrapping a model, you can use it with the Vercel AI SDK Core
  9. * methods as normal.
  10. *
  11. * @example
  12. * ```ts
  13. * import { anthropic } from "@ai-sdk/anthropic";
  14. * import { streamText } from "ai";
  15. * import { wrapAISDKModel } from "langsmith/wrappers/vercel";
  16. *
  17. * const anthropicModel = anthropic("claude-3-haiku-20240307");
  18. *
  19. * const modelWithTracing = wrapAISDKModel(anthropicModel);
  20. *
  21. * const { textStream } = await streamText({
  22. * model: modelWithTracing,
  23. * prompt: "Write a vegetarian lasagna recipe for 4 people.",
  24. * });
  25. *
  26. * for await (const chunk of textStream) {
  27. * console.log(chunk);
  28. * }
  29. * ```
  30. * @param model An AI SDK model instance.
  31. * @param options LangSmith options.
  32. * @returns
  33. */
  34. const wrapAISDKModel = (model, options) => {
  35. if (!("doStream" in model) ||
  36. typeof model.doStream !== "function" ||
  37. !("doGenerate" in model) ||
  38. typeof model.doGenerate !== "function") {
  39. throw new Error(`Received invalid input. This version of wrapAISDKModel only supports Vercel LanguageModelV1 instances.`);
  40. }
  41. const runName = options?.name ?? model.constructor?.name;
  42. return new Proxy(model, {
  43. get(target, propKey, receiver) {
  44. const originalValue = target[propKey];
  45. if (typeof originalValue === "function") {
  46. let __finalTracedIteratorKey;
  47. let aggregator;
  48. if (propKey === "doStream") {
  49. __finalTracedIteratorKey = "stream";
  50. aggregator = (chunks) => {
  51. return chunks.reduce((aggregated, chunk) => {
  52. if (chunk.type === "text-delta") {
  53. return {
  54. ...aggregated,
  55. text: aggregated.text + chunk.textDelta,
  56. };
  57. }
  58. else if (chunk.type === "tool-call") {
  59. return {
  60. ...aggregated,
  61. ...chunk,
  62. };
  63. }
  64. else if (chunk.type === "finish") {
  65. return {
  66. ...aggregated,
  67. usage: chunk.usage,
  68. finishReason: chunk.finishReason,
  69. };
  70. }
  71. else {
  72. return aggregated;
  73. }
  74. }, {
  75. text: "",
  76. });
  77. };
  78. }
  79. return (0, traceable_js_1.traceable)(originalValue.bind(target), {
  80. run_type: "llm",
  81. name: runName,
  82. ...options,
  83. __finalTracedIteratorKey,
  84. aggregator,
  85. });
  86. }
  87. else if (originalValue != null &&
  88. !Array.isArray(originalValue) &&
  89. // eslint-disable-next-line no-instanceof/no-instanceof
  90. !(originalValue instanceof Date) &&
  91. typeof originalValue === "object") {
  92. return (0, generic_js_1._wrapClient)(originalValue, [runName, propKey.toString()].join("."), options);
  93. }
  94. else {
  95. return Reflect.get(target, propKey, receiver);
  96. }
  97. },
  98. });
  99. };
  100. exports.wrapAISDKModel = wrapAISDKModel;