@librechat/agents 2.4.88 → 2.4.90
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/cjs/instrumentation.cjs +7 -1
- package/dist/cjs/instrumentation.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +0 -4
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/run.cjs +32 -3
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/utils/title.cjs +54 -25
- package/dist/cjs/utils/title.cjs.map +1 -1
- package/dist/esm/instrumentation.mjs +7 -1
- package/dist/esm/instrumentation.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +0 -4
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/run.mjs +32 -3
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/utils/title.mjs +54 -25
- package/dist/esm/utils/title.mjs.map +1 -1
- package/dist/types/run.d.ts +2 -2
- package/package.json +2 -2
- package/src/instrumentation.ts +8 -1
- package/src/llm/openai/index.ts +0 -5
- package/src/run.ts +51 -7
- package/src/scripts/simple.ts +9 -1
- package/src/utils/title.ts +80 -40
package/src/run.ts
CHANGED
|
@@ -4,13 +4,15 @@ import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
|
4
4
|
import { CallbackHandler } from '@langfuse/langchain';
|
|
5
5
|
import { PromptTemplate } from '@langchain/core/prompts';
|
|
6
6
|
import { SystemMessage } from '@langchain/core/messages';
|
|
7
|
+
import { RunnableLambda } from '@langchain/core/runnables';
|
|
7
8
|
import { AzureChatOpenAI, ChatOpenAI } from '@langchain/openai';
|
|
8
9
|
import type {
|
|
9
|
-
BaseMessage,
|
|
10
10
|
MessageContentComplex,
|
|
11
|
+
BaseMessage,
|
|
11
12
|
} from '@langchain/core/messages';
|
|
12
|
-
import type {
|
|
13
|
+
import type { StringPromptValue } from '@langchain/core/prompt_values';
|
|
13
14
|
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
15
|
+
import type { ClientCallbacks, SystemCallbacks } from '@/graphs/Graph';
|
|
14
16
|
import type * as t from '@/types';
|
|
15
17
|
import { GraphEvents, Providers, Callback, TitleMethod } from '@/common';
|
|
16
18
|
import { manualToolStreamProviders } from '@/llm/providers';
|
|
@@ -291,18 +293,38 @@ export class Run<T extends t.BaseGraphState> {
|
|
|
291
293
|
titleMethod = TitleMethod.COMPLETION,
|
|
292
294
|
titlePromptTemplate,
|
|
293
295
|
}: t.RunTitleOptions): Promise<{ language?: string; title?: string }> {
|
|
296
|
+
if (
|
|
297
|
+
chainOptions != null &&
|
|
298
|
+
isPresent(process.env.LANGFUSE_SECRET_KEY) &&
|
|
299
|
+
isPresent(process.env.LANGFUSE_PUBLIC_KEY) &&
|
|
300
|
+
isPresent(process.env.LANGFUSE_BASE_URL)
|
|
301
|
+
) {
|
|
302
|
+
const userId = chainOptions.configurable?.user_id;
|
|
303
|
+
const sessionId = chainOptions.configurable?.thread_id;
|
|
304
|
+
const traceMetadata = {
|
|
305
|
+
messageId: 'title-' + this.id,
|
|
306
|
+
};
|
|
307
|
+
const handler = new CallbackHandler({
|
|
308
|
+
userId,
|
|
309
|
+
sessionId,
|
|
310
|
+
traceMetadata,
|
|
311
|
+
});
|
|
312
|
+
chainOptions.callbacks = (
|
|
313
|
+
(chainOptions.callbacks as t.ProvidedCallbacks) ?? []
|
|
314
|
+
).concat([handler]);
|
|
315
|
+
}
|
|
316
|
+
|
|
294
317
|
const convoTemplate = PromptTemplate.fromTemplate(
|
|
295
318
|
titlePromptTemplate ?? 'User: {input}\nAI: {output}'
|
|
296
319
|
);
|
|
320
|
+
|
|
297
321
|
const response = contentParts
|
|
298
322
|
.map((part) => {
|
|
299
323
|
if (part?.type === 'text') return part.text;
|
|
300
324
|
return '';
|
|
301
325
|
})
|
|
302
326
|
.join('\n');
|
|
303
|
-
|
|
304
|
-
await convoTemplate.invoke({ input: inputText, output: response })
|
|
305
|
-
).value;
|
|
327
|
+
|
|
306
328
|
const model = this.Graph?.getNewModel({
|
|
307
329
|
provider,
|
|
308
330
|
omitOptions,
|
|
@@ -328,10 +350,32 @@ export class Run<T extends t.BaseGraphState> {
|
|
|
328
350
|
model.n = (clientOptions as t.OpenAIClientOptions | undefined)
|
|
329
351
|
?.n as number;
|
|
330
352
|
}
|
|
331
|
-
|
|
353
|
+
|
|
354
|
+
const convoToTitleInput = new RunnableLambda({
|
|
355
|
+
func: (
|
|
356
|
+
promptValue: StringPromptValue
|
|
357
|
+
): { convo: string; inputText: string; skipLanguage?: boolean } => ({
|
|
358
|
+
convo: promptValue.value,
|
|
359
|
+
inputText,
|
|
360
|
+
skipLanguage,
|
|
361
|
+
}),
|
|
362
|
+
}).withConfig({ runName: 'ConvoTransform' });
|
|
363
|
+
|
|
364
|
+
const titleChain =
|
|
332
365
|
titleMethod === TitleMethod.COMPLETION
|
|
333
366
|
? await createCompletionTitleRunnable(model, titlePrompt)
|
|
334
367
|
: await createTitleRunnable(model, titlePrompt);
|
|
335
|
-
|
|
368
|
+
|
|
369
|
+
/** Pipes `convoTemplate` -> `transformer` -> `titleChain` */
|
|
370
|
+
const fullChain = convoTemplate
|
|
371
|
+
.withConfig({ runName: 'ConvoTemplate' })
|
|
372
|
+
.pipe(convoToTitleInput)
|
|
373
|
+
.pipe(titleChain)
|
|
374
|
+
.withConfig({ runName: 'TitleChain' });
|
|
375
|
+
|
|
376
|
+
return await fullChain.invoke(
|
|
377
|
+
{ input: inputText, output: response },
|
|
378
|
+
chainOptions
|
|
379
|
+
);
|
|
336
380
|
}
|
|
337
381
|
}
|
package/src/scripts/simple.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
import { GraphEvents, Providers, TitleMethod } from '@/common';
|
|
18
18
|
import { getLLMConfig } from '@/utils/llmConfig';
|
|
19
19
|
import { getArgs } from '@/scripts/args';
|
|
20
|
+
import { sleep } from '@/utils/run';
|
|
20
21
|
import { Run } from '@/run';
|
|
21
22
|
|
|
22
23
|
const conversationHistory: BaseMessage[] = [];
|
|
@@ -129,7 +130,7 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
129
130
|
}
|
|
130
131
|
|
|
131
132
|
const run = await Run.create<t.IState>({
|
|
132
|
-
runId: 'test-
|
|
133
|
+
runId: 'test-simple-script',
|
|
133
134
|
graphConfig: {
|
|
134
135
|
type: 'standard',
|
|
135
136
|
llmConfig,
|
|
@@ -144,7 +145,9 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
144
145
|
});
|
|
145
146
|
|
|
146
147
|
const config = {
|
|
148
|
+
runId: 'test-simple-script',
|
|
147
149
|
configurable: {
|
|
150
|
+
user_id: 'user-123',
|
|
148
151
|
thread_id: 'conversation-num-1',
|
|
149
152
|
},
|
|
150
153
|
streamMode: 'values',
|
|
@@ -176,6 +179,10 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
176
179
|
contentParts,
|
|
177
180
|
// titleMethod: TitleMethod.STRUCTURED,
|
|
178
181
|
chainOptions: {
|
|
182
|
+
configurable: {
|
|
183
|
+
user_id: 'user-123',
|
|
184
|
+
thread_id: 'conversation-num-1',
|
|
185
|
+
},
|
|
179
186
|
callbacks: [
|
|
180
187
|
{
|
|
181
188
|
handleLLMEnd,
|
|
@@ -192,6 +199,7 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
192
199
|
console.log('Collected usage metadata:', collectedUsage);
|
|
193
200
|
console.log('Generated Title:', titleResult);
|
|
194
201
|
console.log('Collected title usage metadata:', collected);
|
|
202
|
+
await sleep(5000);
|
|
195
203
|
}
|
|
196
204
|
|
|
197
205
|
process.on('unhandledRejection', (reason, promise) => {
|
package/src/utils/title.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { RunnableLambda } from '@langchain/core/runnables';
|
|
3
2
|
import { ChatPromptTemplate } from '@langchain/core/prompts';
|
|
3
|
+
import { RunnableLambda, RunnableSequence } from '@langchain/core/runnables';
|
|
4
4
|
import type { Runnable, RunnableConfig } from '@langchain/core/runnables';
|
|
5
|
+
import type { AIMessage } from '@langchain/core/messages';
|
|
5
6
|
import type * as t from '@/types';
|
|
6
7
|
import { ContentTypes } from '@/common';
|
|
7
8
|
|
|
@@ -42,7 +43,55 @@ export const createTitleRunnable = async (
|
|
|
42
43
|
|
|
43
44
|
const titlePrompt = ChatPromptTemplate.fromTemplate(
|
|
44
45
|
_titlePrompt ?? defaultTitlePrompt
|
|
45
|
-
);
|
|
46
|
+
).withConfig({ runName: 'TitlePrompt' });
|
|
47
|
+
|
|
48
|
+
const titleOnlyInnerChain = RunnableSequence.from([titlePrompt, titleLLM]);
|
|
49
|
+
const combinedInnerChain = RunnableSequence.from([titlePrompt, combinedLLM]);
|
|
50
|
+
|
|
51
|
+
/** Wrap titleOnlyChain in RunnableLambda to create parent span */
|
|
52
|
+
const titleOnlyChain = new RunnableLambda({
|
|
53
|
+
func: async (
|
|
54
|
+
input: { convo: string },
|
|
55
|
+
config?: Partial<RunnableConfig>
|
|
56
|
+
): Promise<{ title: string }> => {
|
|
57
|
+
return await titleOnlyInnerChain.invoke(input, config);
|
|
58
|
+
},
|
|
59
|
+
}).withConfig({ runName: 'TitleOnlyChain' });
|
|
60
|
+
|
|
61
|
+
/** Wrap combinedChain in RunnableLambda to create parent span */
|
|
62
|
+
const combinedChain = new RunnableLambda({
|
|
63
|
+
func: async (
|
|
64
|
+
input: { convo: string },
|
|
65
|
+
config?: Partial<RunnableConfig>
|
|
66
|
+
): Promise<{ language: string; title: string }> => {
|
|
67
|
+
return await combinedInnerChain.invoke(input, config);
|
|
68
|
+
},
|
|
69
|
+
}).withConfig({ runName: 'TitleLanguageChain' });
|
|
70
|
+
|
|
71
|
+
/** Runnable to add default values if needed */
|
|
72
|
+
const addDefaults = new RunnableLambda({
|
|
73
|
+
func: (
|
|
74
|
+
result: { language: string; title: string } | undefined
|
|
75
|
+
): { language: string; title: string } => ({
|
|
76
|
+
language: result?.language ?? 'English',
|
|
77
|
+
title: result?.title ?? '',
|
|
78
|
+
}),
|
|
79
|
+
}).withConfig({ runName: 'AddDefaults' });
|
|
80
|
+
|
|
81
|
+
const combinedChainInner = RunnableSequence.from([
|
|
82
|
+
combinedChain,
|
|
83
|
+
addDefaults,
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
/** Wrap combinedChainWithDefaults in RunnableLambda to create parent span */
|
|
87
|
+
const combinedChainWithDefaults = new RunnableLambda({
|
|
88
|
+
func: async (
|
|
89
|
+
input: { convo: string },
|
|
90
|
+
config?: Partial<RunnableConfig>
|
|
91
|
+
): Promise<{ language: string; title: string }> => {
|
|
92
|
+
return await combinedChainInner.invoke(input, config);
|
|
93
|
+
},
|
|
94
|
+
}).withConfig({ runName: 'CombinedChainWithDefaults' });
|
|
46
95
|
|
|
47
96
|
return new RunnableLambda({
|
|
48
97
|
func: async (
|
|
@@ -53,28 +102,17 @@ export const createTitleRunnable = async (
|
|
|
53
102
|
},
|
|
54
103
|
config?: Partial<RunnableConfig>
|
|
55
104
|
): Promise<{ language: string; title: string } | { title: string }> => {
|
|
105
|
+
const invokeInput = { convo: input.convo };
|
|
106
|
+
|
|
56
107
|
if (input.skipLanguage) {
|
|
57
|
-
return (await
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
},
|
|
61
|
-
config
|
|
62
|
-
)) as { title: string };
|
|
108
|
+
return (await titleOnlyChain.invoke(invokeInput, config)) as {
|
|
109
|
+
title: string;
|
|
110
|
+
};
|
|
63
111
|
}
|
|
64
112
|
|
|
65
|
-
|
|
66
|
-
{
|
|
67
|
-
convo: input.convo,
|
|
68
|
-
},
|
|
69
|
-
config
|
|
70
|
-
)) as { language: string; title: string } | undefined;
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
language: result?.language ?? 'English',
|
|
74
|
-
title: result?.title ?? '',
|
|
75
|
-
};
|
|
113
|
+
return await combinedChainWithDefaults.invoke(invokeInput, config);
|
|
76
114
|
},
|
|
77
|
-
});
|
|
115
|
+
}).withConfig({ runName: 'TitleGenerator' });
|
|
78
116
|
};
|
|
79
117
|
|
|
80
118
|
const defaultCompletionPrompt = `Provide a concise, 5-word-or-less title for the conversation, using title case conventions. Only return the title itself.
|
|
@@ -88,22 +126,11 @@ export const createCompletionTitleRunnable = async (
|
|
|
88
126
|
): Promise<Runnable> => {
|
|
89
127
|
const completionPrompt = ChatPromptTemplate.fromTemplate(
|
|
90
128
|
titlePrompt ?? defaultCompletionPrompt
|
|
91
|
-
);
|
|
129
|
+
).withConfig({ runName: 'CompletionTitlePrompt' });
|
|
92
130
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
convo: string;
|
|
97
|
-
inputText: string;
|
|
98
|
-
skipLanguage: boolean;
|
|
99
|
-
},
|
|
100
|
-
config?: Partial<RunnableConfig>
|
|
101
|
-
): Promise<{ title: string }> => {
|
|
102
|
-
const promptOutput = await completionPrompt.invoke({
|
|
103
|
-
convo: input.convo,
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const response = await model.invoke(promptOutput, config);
|
|
131
|
+
/** Runnable to extract content from model response */
|
|
132
|
+
const extractContent = new RunnableLambda({
|
|
133
|
+
func: (response: AIMessage): { title: string } => {
|
|
107
134
|
let content = '';
|
|
108
135
|
if (typeof response.content === 'string') {
|
|
109
136
|
content = response.content;
|
|
@@ -116,10 +143,23 @@ export const createCompletionTitleRunnable = async (
|
|
|
116
143
|
.map((part) => part.text)
|
|
117
144
|
.join('');
|
|
118
145
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
146
|
+
return { title: content.trim() };
|
|
147
|
+
},
|
|
148
|
+
}).withConfig({ runName: 'ExtractTitle' });
|
|
149
|
+
|
|
150
|
+
const innerChain = RunnableSequence.from([
|
|
151
|
+
completionPrompt,
|
|
152
|
+
model,
|
|
153
|
+
extractContent,
|
|
154
|
+
]);
|
|
155
|
+
|
|
156
|
+
/** Wrap in RunnableLambda to create a parent span for LangFuse */
|
|
157
|
+
return new RunnableLambda({
|
|
158
|
+
func: async (
|
|
159
|
+
input: { convo: string },
|
|
160
|
+
config?: Partial<RunnableConfig>
|
|
161
|
+
): Promise<{ title: string }> => {
|
|
162
|
+
return await innerChain.invoke(input, config);
|
|
123
163
|
},
|
|
124
|
-
});
|
|
164
|
+
}).withConfig({ runName: 'CompletionTitleChain' });
|
|
125
165
|
};
|