@librechat/agents 2.4.62 → 2.4.64
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/common/enum.cjs +6 -0
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/main.cjs +4 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/run.cjs +5 -3
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/tools/search/firecrawl.cjs +54 -8
- package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +4 -3
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/utils/title.cjs +32 -1
- package/dist/cjs/utils/title.cjs.map +1 -1
- package/dist/esm/common/enum.mjs +7 -1
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/main.mjs +1 -1
- package/dist/esm/run.mjs +7 -5
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/tools/search/firecrawl.mjs +54 -8
- package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +4 -3
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/utils/title.mjs +32 -2
- package/dist/esm/utils/title.mjs.map +1 -1
- package/dist/types/common/enum.d.ts +5 -0
- package/dist/types/run.d.ts +3 -3
- package/dist/types/tools/search/firecrawl.d.ts +15 -0
- package/dist/types/tools/search/types.d.ts +20 -9
- package/dist/types/types/run.d.ts +2 -0
- package/dist/types/utils/title.d.ts +2 -1
- package/package.json +3 -3
- package/src/common/enum.ts +6 -0
- package/src/run.ts +14 -6
- package/src/scripts/simple.ts +1 -1
- package/src/specs/anthropic.simple.test.ts +58 -1
- package/src/specs/openai.simple.test.ts +57 -1
- package/src/tools/search/firecrawl.ts +68 -19
- package/src/tools/search/tool.ts +4 -3
- package/src/tools/search/types.ts +20 -10
- package/src/types/run.ts +2 -0
- package/src/utils/title.ts +47 -2
package/src/run.ts
CHANGED
|
@@ -10,10 +10,13 @@ import type {
|
|
|
10
10
|
import type { ClientCallbacks, SystemCallbacks } from '@/graphs/Graph';
|
|
11
11
|
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
12
12
|
import type * as t from '@/types';
|
|
13
|
-
import { GraphEvents, Providers, Callback } from '@/common';
|
|
13
|
+
import { GraphEvents, Providers, Callback, TitleMethod } from '@/common';
|
|
14
14
|
import { manualToolStreamProviders } from '@/llm/providers';
|
|
15
15
|
import { shiftIndexTokenCountMap } from '@/messages/format';
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
createTitleRunnable,
|
|
18
|
+
createCompletionTitleRunnable,
|
|
19
|
+
} from '@/utils/title';
|
|
17
20
|
import { createTokenCounter } from '@/utils/tokens';
|
|
18
21
|
import { StandardGraph } from '@/graphs/Graph';
|
|
19
22
|
import { HandlerRegistry } from '@/events';
|
|
@@ -259,9 +262,11 @@ export class Run<T extends t.BaseGraphState> {
|
|
|
259
262
|
chainOptions,
|
|
260
263
|
skipLanguage,
|
|
261
264
|
omitOptions = defaultOmitOptions,
|
|
262
|
-
|
|
265
|
+
titleMethod = TitleMethod.COMPLETION,
|
|
266
|
+
convoPromptTemplate,
|
|
267
|
+
}: t.RunTitleOptions): Promise<{ language?: string; title?: string }> {
|
|
263
268
|
const convoTemplate = PromptTemplate.fromTemplate(
|
|
264
|
-
'User: {input}\nAI: {output}'
|
|
269
|
+
convoPromptTemplate ?? 'User: {input}\nAI: {output}'
|
|
265
270
|
);
|
|
266
271
|
const response = contentParts
|
|
267
272
|
.map((part) => {
|
|
@@ -297,10 +302,13 @@ export class Run<T extends t.BaseGraphState> {
|
|
|
297
302
|
model.n = (clientOptions as t.OpenAIClientOptions | undefined)
|
|
298
303
|
?.n as number;
|
|
299
304
|
}
|
|
300
|
-
const chain =
|
|
305
|
+
const chain =
|
|
306
|
+
titleMethod === TitleMethod.COMPLETION
|
|
307
|
+
? await createCompletionTitleRunnable(model, titlePrompt)
|
|
308
|
+
: await createTitleRunnable(model, titlePrompt);
|
|
301
309
|
return (await chain.invoke(
|
|
302
310
|
{ convo, inputText, skipLanguage },
|
|
303
311
|
chainOptions
|
|
304
|
-
)) as { language
|
|
312
|
+
)) as { language?: string; title?: string };
|
|
305
313
|
}
|
|
306
314
|
}
|
package/src/scripts/simple.ts
CHANGED
|
@@ -14,9 +14,9 @@ import {
|
|
|
14
14
|
ModelEndHandler,
|
|
15
15
|
createMetadataAggregator,
|
|
16
16
|
} from '@/events';
|
|
17
|
+
import { GraphEvents, Providers, TitleMethod } from '@/common';
|
|
17
18
|
import { getLLMConfig } from '@/utils/llmConfig';
|
|
18
19
|
import { getArgs } from '@/scripts/args';
|
|
19
|
-
import { GraphEvents, Providers } from '@/common';
|
|
20
20
|
import { Run } from '@/run';
|
|
21
21
|
|
|
22
22
|
const conversationHistory: BaseMessage[] = [];
|
|
@@ -16,8 +16,8 @@ import {
|
|
|
16
16
|
ModelEndHandler,
|
|
17
17
|
createMetadataAggregator,
|
|
18
18
|
} from '@/events';
|
|
19
|
+
import { ContentTypes, GraphEvents, Providers, TitleMethod } from '@/common';
|
|
19
20
|
import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
|
|
20
|
-
import { ContentTypes, GraphEvents, Providers } from '@/common';
|
|
21
21
|
import { capitalizeFirstLetter } from './spec.utils';
|
|
22
22
|
import { getLLMConfig } from '@/utils/llmConfig';
|
|
23
23
|
import { getArgs } from '@/scripts/args';
|
|
@@ -175,6 +175,7 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
|
|
|
175
175
|
const titleResult = await run.generateTitle({
|
|
176
176
|
provider,
|
|
177
177
|
inputText: userMessage,
|
|
178
|
+
titleMethod: TitleMethod.STRUCTURED,
|
|
178
179
|
contentParts,
|
|
179
180
|
chainOptions: {
|
|
180
181
|
callbacks: [
|
|
@@ -191,6 +192,62 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
|
|
|
191
192
|
expect(collected).toBeDefined();
|
|
192
193
|
});
|
|
193
194
|
|
|
195
|
+
test(`${capitalizeFirstLetter(provider)}: should generate title using completion method`, async () => {
|
|
196
|
+
const { userName, location } = await getArgs();
|
|
197
|
+
const llmConfig = getLLMConfig(provider);
|
|
198
|
+
const customHandlers = setupCustomHandlers();
|
|
199
|
+
|
|
200
|
+
run = await Run.create<t.IState>({
|
|
201
|
+
runId: 'test-run-id-completion',
|
|
202
|
+
graphConfig: {
|
|
203
|
+
type: 'standard',
|
|
204
|
+
llmConfig,
|
|
205
|
+
tools: [new Calculator()],
|
|
206
|
+
instructions:
|
|
207
|
+
'You are a friendly AI assistant. Always address the user by their name.',
|
|
208
|
+
additional_instructions: `The user's name is ${userName} and they are located in ${location}.`,
|
|
209
|
+
},
|
|
210
|
+
returnContent: true,
|
|
211
|
+
customHandlers,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
const userMessage =
|
|
215
|
+
'Can you help me calculate the area of a circle with radius 5?';
|
|
216
|
+
conversationHistory = [];
|
|
217
|
+
conversationHistory.push(new HumanMessage(userMessage));
|
|
218
|
+
|
|
219
|
+
const inputs = {
|
|
220
|
+
messages: conversationHistory,
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const finalContentParts = await run.processStream(inputs, config);
|
|
224
|
+
expect(finalContentParts).toBeDefined();
|
|
225
|
+
|
|
226
|
+
const { handleLLMEnd, collected } = createMetadataAggregator();
|
|
227
|
+
const titleResult = await run.generateTitle({
|
|
228
|
+
provider,
|
|
229
|
+
inputText: userMessage,
|
|
230
|
+
titleMethod: TitleMethod.COMPLETION, // Using completion method
|
|
231
|
+
contentParts,
|
|
232
|
+
chainOptions: {
|
|
233
|
+
callbacks: [
|
|
234
|
+
{
|
|
235
|
+
handleLLMEnd,
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
expect(titleResult).toBeDefined();
|
|
242
|
+
expect(titleResult.title).toBeDefined();
|
|
243
|
+
expect(titleResult.title).not.toBe('');
|
|
244
|
+
expect(titleResult.title).not.toBe('Untitled Conversation');
|
|
245
|
+
// Completion method doesn't return language
|
|
246
|
+
expect(titleResult.language).toBeUndefined();
|
|
247
|
+
expect(collected).toBeDefined();
|
|
248
|
+
console.log(`Completion method generated title: "${titleResult.title}"`);
|
|
249
|
+
});
|
|
250
|
+
|
|
194
251
|
test(`${capitalizeFirstLetter(provider)}: should follow-up`, async () => {
|
|
195
252
|
console.log('Previous conversation length:', runningHistory.length);
|
|
196
253
|
console.log(
|
|
@@ -16,8 +16,8 @@ import {
|
|
|
16
16
|
ModelEndHandler,
|
|
17
17
|
createMetadataAggregator,
|
|
18
18
|
} from '@/events';
|
|
19
|
+
import { ContentTypes, GraphEvents, Providers, TitleMethod } from '@/common';
|
|
19
20
|
import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
|
|
20
|
-
import { ContentTypes, GraphEvents, Providers } from '@/common';
|
|
21
21
|
import { capitalizeFirstLetter } from './spec.utils';
|
|
22
22
|
import { getLLMConfig } from '@/utils/llmConfig';
|
|
23
23
|
import { getArgs } from '@/scripts/args';
|
|
@@ -175,6 +175,7 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
|
|
|
175
175
|
const titleResult = await run.generateTitle({
|
|
176
176
|
provider,
|
|
177
177
|
inputText: userMessage,
|
|
178
|
+
titleMethod: TitleMethod.STRUCTURED,
|
|
178
179
|
contentParts,
|
|
179
180
|
chainOptions: {
|
|
180
181
|
callbacks: [
|
|
@@ -191,6 +192,61 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
|
|
|
191
192
|
expect(collected).toBeDefined();
|
|
192
193
|
});
|
|
193
194
|
|
|
195
|
+
test(`${capitalizeFirstLetter(provider)}: should generate title using completion method`, async () => {
|
|
196
|
+
const { userName, location } = await getArgs();
|
|
197
|
+
const llmConfig = getLLMConfig(provider);
|
|
198
|
+
const customHandlers = setupCustomHandlers();
|
|
199
|
+
|
|
200
|
+
run = await Run.create<t.IState>({
|
|
201
|
+
runId: 'test-run-id-completion',
|
|
202
|
+
graphConfig: {
|
|
203
|
+
type: 'standard',
|
|
204
|
+
llmConfig,
|
|
205
|
+
tools: [new Calculator()],
|
|
206
|
+
instructions:
|
|
207
|
+
'You are a friendly AI assistant. Always address the user by their name.',
|
|
208
|
+
additional_instructions: `The user's name is ${userName} and they are located in ${location}.`,
|
|
209
|
+
},
|
|
210
|
+
returnContent: true,
|
|
211
|
+
customHandlers,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
const userMessage = 'What is the weather like today?';
|
|
215
|
+
conversationHistory = [];
|
|
216
|
+
conversationHistory.push(new HumanMessage(userMessage));
|
|
217
|
+
|
|
218
|
+
const inputs = {
|
|
219
|
+
messages: conversationHistory,
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const finalContentParts = await run.processStream(inputs, config);
|
|
223
|
+
expect(finalContentParts).toBeDefined();
|
|
224
|
+
|
|
225
|
+
const { handleLLMEnd, collected } = createMetadataAggregator();
|
|
226
|
+
const titleResult = await run.generateTitle({
|
|
227
|
+
provider,
|
|
228
|
+
inputText: userMessage,
|
|
229
|
+
titleMethod: TitleMethod.COMPLETION, // Using completion method
|
|
230
|
+
contentParts,
|
|
231
|
+
chainOptions: {
|
|
232
|
+
callbacks: [
|
|
233
|
+
{
|
|
234
|
+
handleLLMEnd,
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
expect(titleResult).toBeDefined();
|
|
241
|
+
expect(titleResult.title).toBeDefined();
|
|
242
|
+
expect(titleResult.title).not.toBe('');
|
|
243
|
+
expect(titleResult.title).not.toBe('Untitled Conversation');
|
|
244
|
+
// Completion method doesn't return language
|
|
245
|
+
expect(titleResult.language).toBeUndefined();
|
|
246
|
+
expect(collected).toBeDefined();
|
|
247
|
+
console.log(`Completion method generated title: "${titleResult.title}"`);
|
|
248
|
+
});
|
|
249
|
+
|
|
194
250
|
test(`${capitalizeFirstLetter(provider)}: should follow-up`, async () => {
|
|
195
251
|
console.log('Previous conversation length:', runningHistory.length);
|
|
196
252
|
console.log(
|
|
@@ -13,6 +13,21 @@ export class FirecrawlScraper {
|
|
|
13
13
|
private defaultFormats: string[];
|
|
14
14
|
private timeout: number;
|
|
15
15
|
private logger: t.Logger;
|
|
16
|
+
private includeTags?: string[];
|
|
17
|
+
private excludeTags?: string[];
|
|
18
|
+
private waitFor?: number;
|
|
19
|
+
private maxAge?: number;
|
|
20
|
+
private mobile?: boolean;
|
|
21
|
+
private skipTlsVerification?: boolean;
|
|
22
|
+
private blockAds?: boolean;
|
|
23
|
+
private removeBase64Images?: boolean;
|
|
24
|
+
private parsePDF?: boolean;
|
|
25
|
+
private storeInCache?: boolean;
|
|
26
|
+
private zeroDataRetention?: boolean;
|
|
27
|
+
private headers?: Record<string, string>;
|
|
28
|
+
private location?: { country?: string; languages?: string[] };
|
|
29
|
+
private onlyMainContent?: boolean;
|
|
30
|
+
private changeTrackingOptions?: object;
|
|
16
31
|
|
|
17
32
|
constructor(config: t.FirecrawlScraperConfig = {}) {
|
|
18
33
|
this.apiKey = config.apiKey ?? process.env.FIRECRAWL_API_KEY ?? '';
|
|
@@ -23,11 +38,27 @@ export class FirecrawlScraper {
|
|
|
23
38
|
'https://api.firecrawl.dev';
|
|
24
39
|
this.apiUrl = `${baseUrl.replace(/\/+$/, '')}/v1/scrape`;
|
|
25
40
|
|
|
26
|
-
this.defaultFormats = config.formats ?? ['markdown', '
|
|
41
|
+
this.defaultFormats = config.formats ?? ['markdown', 'rawHtml'];
|
|
27
42
|
this.timeout = config.timeout ?? 7500;
|
|
28
43
|
|
|
29
44
|
this.logger = config.logger || createDefaultLogger();
|
|
30
45
|
|
|
46
|
+
this.includeTags = config.includeTags;
|
|
47
|
+
this.excludeTags = config.excludeTags;
|
|
48
|
+
this.waitFor = config.waitFor;
|
|
49
|
+
this.maxAge = config.maxAge;
|
|
50
|
+
this.mobile = config.mobile;
|
|
51
|
+
this.skipTlsVerification = config.skipTlsVerification;
|
|
52
|
+
this.blockAds = config.blockAds;
|
|
53
|
+
this.removeBase64Images = config.removeBase64Images;
|
|
54
|
+
this.parsePDF = config.parsePDF;
|
|
55
|
+
this.storeInCache = config.storeInCache;
|
|
56
|
+
this.zeroDataRetention = config.zeroDataRetention;
|
|
57
|
+
this.headers = config.headers;
|
|
58
|
+
this.location = config.location;
|
|
59
|
+
this.onlyMainContent = config.onlyMainContent;
|
|
60
|
+
this.changeTrackingOptions = config.changeTrackingOptions;
|
|
61
|
+
|
|
31
62
|
if (!this.apiKey) {
|
|
32
63
|
this.logger.warn('FIRECRAWL_API_KEY is not set. Scraping will not work.');
|
|
33
64
|
}
|
|
@@ -58,25 +89,36 @@ export class FirecrawlScraper {
|
|
|
58
89
|
}
|
|
59
90
|
|
|
60
91
|
try {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
92
|
+
const payload = omitUndefined({
|
|
93
|
+
url,
|
|
94
|
+
formats: options.formats ?? this.defaultFormats,
|
|
95
|
+
includeTags: options.includeTags ?? this.includeTags,
|
|
96
|
+
excludeTags: options.excludeTags ?? this.excludeTags,
|
|
97
|
+
headers: options.headers ?? this.headers,
|
|
98
|
+
waitFor: options.waitFor ?? this.waitFor,
|
|
99
|
+
timeout: options.timeout ?? this.timeout,
|
|
100
|
+
onlyMainContent: options.onlyMainContent ?? this.onlyMainContent,
|
|
101
|
+
maxAge: options.maxAge ?? this.maxAge,
|
|
102
|
+
mobile: options.mobile ?? this.mobile,
|
|
103
|
+
skipTlsVerification:
|
|
104
|
+
options.skipTlsVerification ?? this.skipTlsVerification,
|
|
105
|
+
parsePDF: options.parsePDF ?? this.parsePDF,
|
|
106
|
+
location: options.location ?? this.location,
|
|
107
|
+
removeBase64Images:
|
|
108
|
+
options.removeBase64Images ?? this.removeBase64Images,
|
|
109
|
+
blockAds: options.blockAds ?? this.blockAds,
|
|
110
|
+
storeInCache: options.storeInCache ?? this.storeInCache,
|
|
111
|
+
zeroDataRetention: options.zeroDataRetention ?? this.zeroDataRetention,
|
|
112
|
+
changeTrackingOptions:
|
|
113
|
+
options.changeTrackingOptions ?? this.changeTrackingOptions,
|
|
114
|
+
});
|
|
115
|
+
const response = await axios.post(this.apiUrl, payload, {
|
|
116
|
+
headers: {
|
|
117
|
+
'Content-Type': 'application/json',
|
|
118
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
71
119
|
},
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
'Content-Type': 'application/json',
|
|
75
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
76
|
-
},
|
|
77
|
-
timeout: this.timeout,
|
|
78
|
-
}
|
|
79
|
-
);
|
|
120
|
+
timeout: this.timeout,
|
|
121
|
+
});
|
|
80
122
|
|
|
81
123
|
return [url, response.data];
|
|
82
124
|
} catch (error) {
|
|
@@ -156,3 +198,10 @@ export const createFirecrawlScraper = (
|
|
|
156
198
|
): FirecrawlScraper => {
|
|
157
199
|
return new FirecrawlScraper(config);
|
|
158
200
|
};
|
|
201
|
+
|
|
202
|
+
// Helper function to clean up payload for firecrawl
|
|
203
|
+
function omitUndefined<T extends object>(obj: T): Partial<T> {
|
|
204
|
+
return Object.fromEntries(
|
|
205
|
+
Object.entries(obj).filter(([, v]) => v !== undefined)
|
|
206
|
+
) as Partial<T>;
|
|
207
|
+
}
|
package/src/tools/search/tool.ts
CHANGED
|
@@ -346,7 +346,7 @@ export const createSearchTool = (
|
|
|
346
346
|
safeSearch = 1,
|
|
347
347
|
firecrawlApiKey,
|
|
348
348
|
firecrawlApiUrl,
|
|
349
|
-
|
|
349
|
+
firecrawlOptions,
|
|
350
350
|
scraperTimeout,
|
|
351
351
|
jinaApiKey,
|
|
352
352
|
cohereApiKey,
|
|
@@ -385,10 +385,11 @@ export const createSearchTool = (
|
|
|
385
385
|
});
|
|
386
386
|
|
|
387
387
|
const firecrawlScraper = createFirecrawlScraper({
|
|
388
|
+
...firecrawlOptions,
|
|
388
389
|
apiKey: firecrawlApiKey ?? process.env.FIRECRAWL_API_KEY,
|
|
389
390
|
apiUrl: firecrawlApiUrl,
|
|
390
|
-
timeout: scraperTimeout,
|
|
391
|
-
formats:
|
|
391
|
+
timeout: scraperTimeout ?? firecrawlOptions?.timeout,
|
|
392
|
+
formats: firecrawlOptions?.formats ?? ['markdown', 'rawHtml'],
|
|
392
393
|
});
|
|
393
394
|
|
|
394
395
|
const selectedReranker = createReranker({
|
|
@@ -94,7 +94,7 @@ export interface ProcessSourcesConfig {
|
|
|
94
94
|
export interface FirecrawlConfig {
|
|
95
95
|
firecrawlApiKey?: string;
|
|
96
96
|
firecrawlApiUrl?: string;
|
|
97
|
-
|
|
97
|
+
firecrawlOptions?: FirecrawlScraperConfig;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
export interface ScraperContentResult {
|
|
@@ -170,15 +170,10 @@ export type UsedReferences = {
|
|
|
170
170
|
}[];
|
|
171
171
|
|
|
172
172
|
/** Firecrawl */
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
excludeTags?: string[];
|
|
178
|
-
headers?: Record<string, string>;
|
|
179
|
-
waitFor?: number;
|
|
180
|
-
timeout?: number;
|
|
181
|
-
}
|
|
173
|
+
export type FirecrawlScrapeOptions = Omit<
|
|
174
|
+
FirecrawlScraperConfig,
|
|
175
|
+
'apiKey' | 'apiUrl' | 'logger'
|
|
176
|
+
>;
|
|
182
177
|
|
|
183
178
|
export interface ScrapeMetadata {
|
|
184
179
|
// Core source information
|
|
@@ -261,6 +256,21 @@ export interface FirecrawlScraperConfig {
|
|
|
261
256
|
formats?: string[];
|
|
262
257
|
timeout?: number;
|
|
263
258
|
logger?: Logger;
|
|
259
|
+
includeTags?: string[];
|
|
260
|
+
excludeTags?: string[];
|
|
261
|
+
waitFor?: number;
|
|
262
|
+
maxAge?: number;
|
|
263
|
+
mobile?: boolean;
|
|
264
|
+
skipTlsVerification?: boolean;
|
|
265
|
+
blockAds?: boolean;
|
|
266
|
+
removeBase64Images?: boolean;
|
|
267
|
+
parsePDF?: boolean;
|
|
268
|
+
storeInCache?: boolean;
|
|
269
|
+
zeroDataRetention?: boolean;
|
|
270
|
+
headers?: Record<string, string>;
|
|
271
|
+
location?: { country?: string; languages?: string[] };
|
|
272
|
+
onlyMainContent?: boolean;
|
|
273
|
+
changeTrackingOptions?: object;
|
|
264
274
|
}
|
|
265
275
|
|
|
266
276
|
export type GetSourcesParams = {
|
package/src/types/run.ts
CHANGED
|
@@ -33,6 +33,8 @@ export type RunTitleOptions = {
|
|
|
33
33
|
clientOptions?: l.ClientOptions;
|
|
34
34
|
chainOptions?: Partial<RunnableConfig> | undefined;
|
|
35
35
|
omitOptions?: Set<string>;
|
|
36
|
+
titleMethod?: e.TitleMethod;
|
|
37
|
+
convoPromptTemplate?: string;
|
|
36
38
|
};
|
|
37
39
|
|
|
38
40
|
export interface AgentStateChannels {
|
package/src/utils/title.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { ChatPromptTemplate } from '@langchain/core/prompts';
|
|
3
2
|
import { RunnableLambda } from '@langchain/core/runnables';
|
|
3
|
+
import { ChatPromptTemplate } from '@langchain/core/prompts';
|
|
4
4
|
import type { Runnable } from '@langchain/core/runnables';
|
|
5
|
-
import * as t from '@/types';
|
|
5
|
+
import type * as t from '@/types';
|
|
6
|
+
import { ContentTypes } from '@/common';
|
|
6
7
|
|
|
7
8
|
const defaultTitlePrompt = `Analyze this conversation and provide:
|
|
8
9
|
1. The detected language of the conversation
|
|
@@ -66,3 +67,47 @@ export const createTitleRunnable = async (
|
|
|
66
67
|
},
|
|
67
68
|
});
|
|
68
69
|
};
|
|
70
|
+
|
|
71
|
+
const defaultCompletionPrompt = `Provide a concise, 5-word-or-less title for the conversation, using its same language, with no punctuation. Apply title case conventions appropriate for the language. Never directly mention the language name or the word "title" and only return the title itself.
|
|
72
|
+
|
|
73
|
+
Conversation:
|
|
74
|
+
{convo}`;
|
|
75
|
+
|
|
76
|
+
export const createCompletionTitleRunnable = async (
|
|
77
|
+
model: t.ChatModelInstance,
|
|
78
|
+
titlePrompt?: string
|
|
79
|
+
): Promise<Runnable> => {
|
|
80
|
+
const completionPrompt = ChatPromptTemplate.fromTemplate(
|
|
81
|
+
titlePrompt ?? defaultCompletionPrompt
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
return new RunnableLambda({
|
|
85
|
+
func: async (input: {
|
|
86
|
+
convo: string;
|
|
87
|
+
inputText: string;
|
|
88
|
+
skipLanguage: boolean;
|
|
89
|
+
}): Promise<{ title: string }> => {
|
|
90
|
+
const promptOutput = await completionPrompt.invoke({
|
|
91
|
+
convo: input.convo,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const response = await model.invoke(promptOutput);
|
|
95
|
+
let content = '';
|
|
96
|
+
if (typeof response.content === 'string') {
|
|
97
|
+
content = response.content;
|
|
98
|
+
} else if (Array.isArray(response.content)) {
|
|
99
|
+
content = response.content
|
|
100
|
+
.filter(
|
|
101
|
+
(part): part is { type: ContentTypes.TEXT; text: string } =>
|
|
102
|
+
part.type === ContentTypes.TEXT
|
|
103
|
+
)
|
|
104
|
+
.map((part) => part.text)
|
|
105
|
+
.join('');
|
|
106
|
+
}
|
|
107
|
+
const title = content.trim();
|
|
108
|
+
return {
|
|
109
|
+
title: title || 'Untitled Conversation',
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
};
|