@posthog/ai 7.2.1 → 7.3.0
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/anthropic/index.cjs +13 -3
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.mjs +13 -3
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/gemini/index.cjs +69 -8
- package/dist/gemini/index.cjs.map +1 -1
- package/dist/gemini/index.d.ts +1 -0
- package/dist/gemini/index.mjs +69 -8
- package/dist/gemini/index.mjs.map +1 -1
- package/dist/index.cjs +253 -151
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.mjs +253 -151
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +13 -2
- package/dist/langchain/index.cjs.map +1 -1
- package/dist/langchain/index.mjs +13 -2
- package/dist/langchain/index.mjs.map +1 -1
- package/dist/openai/index.cjs +48 -14
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +48 -14
- package/dist/openai/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +141 -113
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.d.ts +7 -2
- package/dist/vercel/index.mjs +141 -113
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +17 -12
package/dist/vercel/index.cjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var ai = require('ai');
|
|
4
3
|
var uuid = require('uuid');
|
|
5
4
|
var buffer = require('buffer');
|
|
6
5
|
|
|
7
|
-
var version = "7.
|
|
6
|
+
var version = "7.3.0";
|
|
8
7
|
|
|
9
8
|
// Type guards for safer type checking
|
|
10
9
|
|
|
@@ -333,6 +332,15 @@ const sendEventToPosthog = async ({
|
|
|
333
332
|
|
|
334
333
|
const REDACTED_IMAGE_PLACEHOLDER = '[base64 image redacted]';
|
|
335
334
|
|
|
335
|
+
// ============================================
|
|
336
|
+
// Multimodal Feature Toggle
|
|
337
|
+
// ============================================
|
|
338
|
+
|
|
339
|
+
const isMultimodalEnabled = () => {
|
|
340
|
+
const val = process.env._INTERNAL_LLMA_MULTIMODAL || '';
|
|
341
|
+
return val.toLowerCase() === 'true' || val === '1' || val.toLowerCase() === 'yes';
|
|
342
|
+
};
|
|
343
|
+
|
|
336
344
|
// ============================================
|
|
337
345
|
// Base64 Detection Helpers
|
|
338
346
|
// ============================================
|
|
@@ -360,6 +368,7 @@ const isRawBase64 = str => {
|
|
|
360
368
|
return str.length > 20 && /^[A-Za-z0-9+/]+=*$/.test(str);
|
|
361
369
|
};
|
|
362
370
|
function redactBase64DataUrl(str) {
|
|
371
|
+
if (isMultimodalEnabled()) return str;
|
|
363
372
|
if (!isString(str)) return str;
|
|
364
373
|
|
|
365
374
|
// Check for data URL format
|
|
@@ -574,68 +583,126 @@ const extractProvider = model => {
|
|
|
574
583
|
const providerName = provider.split('.')[0];
|
|
575
584
|
return providerName;
|
|
576
585
|
};
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
586
|
+
|
|
587
|
+
// Extract web search count from provider metadata (works for both V2 and V3)
|
|
588
|
+
const extractWebSearchCount = (providerMetadata, usage) => {
|
|
589
|
+
// Try Anthropic-specific extraction
|
|
590
|
+
if (providerMetadata && typeof providerMetadata === 'object' && 'anthropic' in providerMetadata && providerMetadata.anthropic && typeof providerMetadata.anthropic === 'object' && 'server_tool_use' in providerMetadata.anthropic) {
|
|
591
|
+
const serverToolUse = providerMetadata.anthropic.server_tool_use;
|
|
592
|
+
if (serverToolUse && typeof serverToolUse === 'object' && 'web_search_requests' in serverToolUse && typeof serverToolUse.web_search_requests === 'number') {
|
|
593
|
+
return serverToolUse.web_search_requests;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// Fall back to generic calculation
|
|
598
|
+
return calculateWebSearchCount({
|
|
599
|
+
usage,
|
|
600
|
+
providerMetadata
|
|
601
|
+
});
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
// Extract additional token values from provider metadata
|
|
605
|
+
const extractAdditionalTokenValues = providerMetadata => {
|
|
606
|
+
if (providerMetadata && typeof providerMetadata === 'object' && 'anthropic' in providerMetadata && providerMetadata.anthropic && typeof providerMetadata.anthropic === 'object' && 'cacheCreationInputTokens' in providerMetadata.anthropic) {
|
|
607
|
+
return {
|
|
608
|
+
cacheCreationInputTokens: providerMetadata.anthropic.cacheCreationInputTokens
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
return {};
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
// Helper to extract numeric token value from V2 (number) or V3 (object with .total) usage formats
|
|
615
|
+
const extractTokenCount = value => {
|
|
616
|
+
if (typeof value === 'number') {
|
|
617
|
+
return value;
|
|
618
|
+
}
|
|
619
|
+
if (value && typeof value === 'object' && 'total' in value && typeof value.total === 'number') {
|
|
620
|
+
return value.total;
|
|
621
|
+
}
|
|
622
|
+
return undefined;
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
// Helper to extract reasoning tokens from V2 (usage.reasoningTokens) or V3 (usage.outputTokens.reasoning)
|
|
626
|
+
const extractReasoningTokens = usage => {
|
|
627
|
+
// V2 style: top-level reasoningTokens
|
|
628
|
+
if ('reasoningTokens' in usage) {
|
|
629
|
+
return usage.reasoningTokens;
|
|
630
|
+
}
|
|
631
|
+
// V3 style: nested in outputTokens.reasoning
|
|
632
|
+
if ('outputTokens' in usage && usage.outputTokens && typeof usage.outputTokens === 'object' && 'reasoning' in usage.outputTokens) {
|
|
633
|
+
return usage.outputTokens.reasoning;
|
|
634
|
+
}
|
|
635
|
+
return undefined;
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
// Helper to extract cached input tokens from V2 (usage.cachedInputTokens) or V3 (usage.inputTokens.cacheRead)
|
|
639
|
+
const extractCacheReadTokens = usage => {
|
|
640
|
+
// V2 style: top-level cachedInputTokens
|
|
641
|
+
if ('cachedInputTokens' in usage) {
|
|
642
|
+
return usage.cachedInputTokens;
|
|
643
|
+
}
|
|
644
|
+
// V3 style: nested in inputTokens.cacheRead
|
|
645
|
+
if ('inputTokens' in usage && usage.inputTokens && typeof usage.inputTokens === 'object' && 'cacheRead' in usage.inputTokens) {
|
|
646
|
+
return usage.inputTokens.cacheRead;
|
|
647
|
+
}
|
|
648
|
+
return undefined;
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Wraps a Vercel AI SDK language model (V2 or V3) with PostHog tracing.
|
|
653
|
+
* Automatically detects the model version and applies appropriate instrumentation.
|
|
654
|
+
*/
|
|
655
|
+
const wrapVercelLanguageModel = (model, phClient, options) => {
|
|
656
|
+
const traceId = options.posthogTraceId ?? uuid.v4();
|
|
657
|
+
const mergedOptions = {
|
|
658
|
+
...options,
|
|
659
|
+
posthogTraceId: traceId,
|
|
660
|
+
posthogDistinctId: options.posthogDistinctId,
|
|
661
|
+
posthogProperties: {
|
|
662
|
+
...options.posthogProperties,
|
|
663
|
+
$ai_framework: 'vercel',
|
|
664
|
+
$ai_framework_version: model.specificationVersion === 'v3' ? '6' : '5'
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
// Create wrapped model that preserves the original type
|
|
669
|
+
const wrappedModel = {
|
|
670
|
+
...model,
|
|
671
|
+
doGenerate: async params => {
|
|
583
672
|
const startTime = Date.now();
|
|
584
673
|
const mergedParams = {
|
|
585
|
-
...
|
|
586
|
-
...mapVercelParams(params)
|
|
587
|
-
posthogProperties: {
|
|
588
|
-
...options.posthogProperties,
|
|
589
|
-
$ai_framework: 'vercel'
|
|
590
|
-
}
|
|
674
|
+
...mergedOptions,
|
|
675
|
+
...mapVercelParams(params)
|
|
591
676
|
};
|
|
592
677
|
const availableTools = extractAvailableToolCalls('vercel', params);
|
|
593
678
|
try {
|
|
594
|
-
const result = await doGenerate();
|
|
595
|
-
const modelId =
|
|
596
|
-
const provider =
|
|
679
|
+
const result = await model.doGenerate(params);
|
|
680
|
+
const modelId = mergedOptions.posthogModelOverride ?? (result.response?.modelId ? result.response.modelId : model.modelId);
|
|
681
|
+
const provider = mergedOptions.posthogProviderOverride ?? extractProvider(model);
|
|
597
682
|
const baseURL = ''; // cannot currently get baseURL from vercel
|
|
598
683
|
const content = mapVercelOutput(result.content);
|
|
599
684
|
const latency = (Date.now() - startTime) / 1000;
|
|
600
685
|
const providerMetadata = result.providerMetadata;
|
|
601
|
-
const additionalTokenValues =
|
|
602
|
-
|
|
603
|
-
cacheCreationInputTokens: providerMetadata.anthropic.cacheCreationInputTokens
|
|
604
|
-
} : {})
|
|
605
|
-
};
|
|
686
|
+
const additionalTokenValues = extractAdditionalTokenValues(providerMetadata);
|
|
687
|
+
const webSearchCount = extractWebSearchCount(providerMetadata, result.usage);
|
|
606
688
|
|
|
607
|
-
//
|
|
608
|
-
|
|
609
|
-
if (providerMetadata?.anthropic && typeof providerMetadata.anthropic === 'object' && 'server_tool_use' in providerMetadata.anthropic) {
|
|
610
|
-
// Anthropic-specific extraction
|
|
611
|
-
const serverToolUse = providerMetadata.anthropic.server_tool_use;
|
|
612
|
-
if (serverToolUse && typeof serverToolUse === 'object' && 'web_search_requests' in serverToolUse && typeof serverToolUse.web_search_requests === 'number') {
|
|
613
|
-
webSearchCount = serverToolUse.web_search_requests;
|
|
614
|
-
}
|
|
615
|
-
} else {
|
|
616
|
-
// For other providers through Vercel, pass available metadata to helper
|
|
617
|
-
// Note: Vercel abstracts provider responses, so we may not have access to
|
|
618
|
-
// raw citations/annotations unless Vercel exposes them in usage/metadata
|
|
619
|
-
webSearchCount = calculateWebSearchCount({
|
|
620
|
-
usage: result.usage,
|
|
621
|
-
providerMetadata: providerMetadata
|
|
622
|
-
});
|
|
623
|
-
}
|
|
689
|
+
// V2 usage has simple numbers, V3 has objects with .total - normalize both
|
|
690
|
+
const usageObj = result.usage;
|
|
624
691
|
const usage = {
|
|
625
|
-
inputTokens: result.usage.inputTokens,
|
|
626
|
-
outputTokens: result.usage.outputTokens,
|
|
627
|
-
reasoningTokens:
|
|
628
|
-
cacheReadInputTokens:
|
|
692
|
+
inputTokens: extractTokenCount(result.usage.inputTokens),
|
|
693
|
+
outputTokens: extractTokenCount(result.usage.outputTokens),
|
|
694
|
+
reasoningTokens: extractReasoningTokens(usageObj),
|
|
695
|
+
cacheReadInputTokens: extractCacheReadTokens(usageObj),
|
|
629
696
|
webSearchCount,
|
|
630
697
|
...additionalTokenValues
|
|
631
698
|
};
|
|
632
699
|
await sendEventToPosthog({
|
|
633
700
|
client: phClient,
|
|
634
|
-
distinctId:
|
|
635
|
-
traceId:
|
|
701
|
+
distinctId: mergedOptions.posthogDistinctId,
|
|
702
|
+
traceId: mergedOptions.posthogTraceId ?? uuid.v4(),
|
|
636
703
|
model: modelId,
|
|
637
704
|
provider: provider,
|
|
638
|
-
input:
|
|
705
|
+
input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
639
706
|
output: content,
|
|
640
707
|
latency,
|
|
641
708
|
baseURL,
|
|
@@ -643,18 +710,18 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
643
710
|
httpStatus: 200,
|
|
644
711
|
usage,
|
|
645
712
|
tools: availableTools,
|
|
646
|
-
captureImmediate:
|
|
713
|
+
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
647
714
|
});
|
|
648
715
|
return result;
|
|
649
716
|
} catch (error) {
|
|
650
717
|
const modelId = model.modelId;
|
|
651
718
|
await sendEventToPosthog({
|
|
652
719
|
client: phClient,
|
|
653
|
-
distinctId:
|
|
654
|
-
traceId:
|
|
720
|
+
distinctId: mergedOptions.posthogDistinctId,
|
|
721
|
+
traceId: mergedOptions.posthogTraceId ?? uuid.v4(),
|
|
655
722
|
model: modelId,
|
|
656
723
|
provider: model.provider,
|
|
657
|
-
input:
|
|
724
|
+
input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
658
725
|
output: [],
|
|
659
726
|
latency: 0,
|
|
660
727
|
baseURL: '',
|
|
@@ -667,30 +734,23 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
667
734
|
isError: true,
|
|
668
735
|
error: truncate(JSON.stringify(error)),
|
|
669
736
|
tools: availableTools,
|
|
670
|
-
captureImmediate:
|
|
737
|
+
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
671
738
|
});
|
|
672
739
|
throw error;
|
|
673
740
|
}
|
|
674
741
|
},
|
|
675
|
-
|
|
676
|
-
doStream,
|
|
677
|
-
params
|
|
678
|
-
}) => {
|
|
742
|
+
doStream: async params => {
|
|
679
743
|
const startTime = Date.now();
|
|
680
744
|
let generatedText = '';
|
|
681
745
|
let reasoningText = '';
|
|
682
746
|
let usage = {};
|
|
683
747
|
let providerMetadata = undefined;
|
|
684
748
|
const mergedParams = {
|
|
685
|
-
...
|
|
686
|
-
...mapVercelParams(params)
|
|
687
|
-
posthogProperties: {
|
|
688
|
-
...options.posthogProperties,
|
|
689
|
-
$ai_framework: 'vercel'
|
|
690
|
-
}
|
|
749
|
+
...mergedOptions,
|
|
750
|
+
...mapVercelParams(params)
|
|
691
751
|
};
|
|
692
|
-
const modelId =
|
|
693
|
-
const provider =
|
|
752
|
+
const modelId = mergedOptions.posthogModelOverride ?? model.modelId;
|
|
753
|
+
const provider = mergedOptions.posthogProviderOverride ?? extractProvider(model);
|
|
694
754
|
const availableTools = extractAvailableToolCalls('vercel', params);
|
|
695
755
|
const baseURL = ''; // cannot currently get baseURL from vercel
|
|
696
756
|
|
|
@@ -700,15 +760,15 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
700
760
|
const {
|
|
701
761
|
stream,
|
|
702
762
|
...rest
|
|
703
|
-
} = await doStream();
|
|
763
|
+
} = await model.doStream(params);
|
|
704
764
|
const transformStream = new TransformStream({
|
|
705
765
|
transform(chunk, controller) {
|
|
706
|
-
// Handle
|
|
766
|
+
// Handle streaming patterns - compatible with both V2 and V3
|
|
707
767
|
if (chunk.type === 'text-delta') {
|
|
708
768
|
generatedText += chunk.delta;
|
|
709
769
|
}
|
|
710
770
|
if (chunk.type === 'reasoning-delta') {
|
|
711
|
-
reasoningText += chunk.delta;
|
|
771
|
+
reasoningText += chunk.delta;
|
|
712
772
|
}
|
|
713
773
|
|
|
714
774
|
// Handle tool call chunks
|
|
@@ -729,7 +789,6 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
729
789
|
}
|
|
730
790
|
if (chunk.type === 'tool-input-end') {
|
|
731
791
|
// Tool call is complete, keep it in the map for final processing
|
|
732
|
-
// Nothing specific to do here, the tool call is already complete
|
|
733
792
|
}
|
|
734
793
|
if (chunk.type === 'tool-call') {
|
|
735
794
|
// Direct tool call chunk (complete tool call)
|
|
@@ -741,14 +800,13 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
741
800
|
}
|
|
742
801
|
if (chunk.type === 'finish') {
|
|
743
802
|
providerMetadata = chunk.providerMetadata;
|
|
744
|
-
const additionalTokenValues = providerMetadata
|
|
745
|
-
|
|
746
|
-
} : {};
|
|
803
|
+
const additionalTokenValues = extractAdditionalTokenValues(providerMetadata);
|
|
804
|
+
const chunkUsage = chunk.usage || {};
|
|
747
805
|
usage = {
|
|
748
|
-
inputTokens: chunk.usage?.inputTokens,
|
|
749
|
-
outputTokens: chunk.usage?.outputTokens,
|
|
750
|
-
reasoningTokens:
|
|
751
|
-
cacheReadInputTokens:
|
|
806
|
+
inputTokens: extractTokenCount(chunk.usage?.inputTokens),
|
|
807
|
+
outputTokens: extractTokenCount(chunk.usage?.outputTokens),
|
|
808
|
+
reasoningTokens: extractReasoningTokens(chunkUsage),
|
|
809
|
+
cacheReadInputTokens: extractCacheReadTokens(chunkUsage),
|
|
752
810
|
...additionalTokenValues
|
|
753
811
|
};
|
|
754
812
|
}
|
|
@@ -790,24 +848,7 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
790
848
|
role: 'assistant',
|
|
791
849
|
content: content.length === 1 && content[0].type === 'text' ? content[0].text : content
|
|
792
850
|
}] : [];
|
|
793
|
-
|
|
794
|
-
// Calculate web search count based on provider
|
|
795
|
-
let webSearchCount = 0;
|
|
796
|
-
if (providerMetadata && typeof providerMetadata === 'object' && 'anthropic' in providerMetadata && providerMetadata.anthropic && typeof providerMetadata.anthropic === 'object' && 'server_tool_use' in providerMetadata.anthropic) {
|
|
797
|
-
// Anthropic-specific extraction
|
|
798
|
-
const serverToolUse = providerMetadata.anthropic.server_tool_use;
|
|
799
|
-
if (serverToolUse && typeof serverToolUse === 'object' && 'web_search_requests' in serverToolUse && typeof serverToolUse.web_search_requests === 'number') {
|
|
800
|
-
webSearchCount = serverToolUse.web_search_requests;
|
|
801
|
-
}
|
|
802
|
-
} else {
|
|
803
|
-
// For other providers through Vercel, pass available metadata to helper
|
|
804
|
-
// Note: Vercel abstracts provider responses, so we may not have access to
|
|
805
|
-
// raw citations/annotations unless Vercel exposes them in usage/metadata
|
|
806
|
-
webSearchCount = calculateWebSearchCount({
|
|
807
|
-
usage: usage,
|
|
808
|
-
providerMetadata: providerMetadata
|
|
809
|
-
});
|
|
810
|
-
}
|
|
851
|
+
const webSearchCount = extractWebSearchCount(providerMetadata, usage);
|
|
811
852
|
|
|
812
853
|
// Update usage with web search count
|
|
813
854
|
const finalUsage = {
|
|
@@ -816,11 +857,11 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
816
857
|
};
|
|
817
858
|
await sendEventToPosthog({
|
|
818
859
|
client: phClient,
|
|
819
|
-
distinctId:
|
|
820
|
-
traceId:
|
|
860
|
+
distinctId: mergedOptions.posthogDistinctId,
|
|
861
|
+
traceId: mergedOptions.posthogTraceId ?? uuid.v4(),
|
|
821
862
|
model: modelId,
|
|
822
863
|
provider: provider,
|
|
823
|
-
input:
|
|
864
|
+
input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
824
865
|
output: output,
|
|
825
866
|
latency,
|
|
826
867
|
baseURL,
|
|
@@ -828,7 +869,7 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
828
869
|
httpStatus: 200,
|
|
829
870
|
usage: finalUsage,
|
|
830
871
|
tools: availableTools,
|
|
831
|
-
captureImmediate:
|
|
872
|
+
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
832
873
|
});
|
|
833
874
|
}
|
|
834
875
|
});
|
|
@@ -839,11 +880,11 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
839
880
|
} catch (error) {
|
|
840
881
|
await sendEventToPosthog({
|
|
841
882
|
client: phClient,
|
|
842
|
-
distinctId:
|
|
843
|
-
traceId:
|
|
883
|
+
distinctId: mergedOptions.posthogDistinctId,
|
|
884
|
+
traceId: mergedOptions.posthogTraceId ?? uuid.v4(),
|
|
844
885
|
model: modelId,
|
|
845
886
|
provider: provider,
|
|
846
|
-
input:
|
|
887
|
+
input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
847
888
|
output: [],
|
|
848
889
|
latency: 0,
|
|
849
890
|
baseURL: '',
|
|
@@ -856,25 +897,12 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
856
897
|
isError: true,
|
|
857
898
|
error: truncate(JSON.stringify(error)),
|
|
858
899
|
tools: availableTools,
|
|
859
|
-
captureImmediate:
|
|
900
|
+
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
860
901
|
});
|
|
861
902
|
throw error;
|
|
862
903
|
}
|
|
863
904
|
}
|
|
864
905
|
};
|
|
865
|
-
return middleware;
|
|
866
|
-
};
|
|
867
|
-
const wrapVercelLanguageModel = (model, phClient, options) => {
|
|
868
|
-
const traceId = options.posthogTraceId ?? uuid.v4();
|
|
869
|
-
const middleware = createInstrumentationMiddleware(phClient, model, {
|
|
870
|
-
...options,
|
|
871
|
-
posthogTraceId: traceId,
|
|
872
|
-
posthogDistinctId: options.posthogDistinctId
|
|
873
|
-
});
|
|
874
|
-
const wrappedModel = ai.wrapLanguageModel({
|
|
875
|
-
model,
|
|
876
|
-
middleware
|
|
877
|
-
});
|
|
878
906
|
return wrappedModel;
|
|
879
907
|
};
|
|
880
908
|
|