@lobehub/lobehub 2.0.0-next.360 → 2.0.0-next.362
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/CHANGELOG.md +50 -0
- package/Dockerfile +2 -1
- package/changelog/v1.json +14 -0
- package/locales/en-US/chat.json +3 -1
- package/locales/zh-CN/chat.json +2 -0
- package/package.json +1 -1
- package/packages/const/src/userMemory.ts +1 -0
- package/packages/context-engine/src/base/BaseEveryUserContentProvider.ts +204 -0
- package/packages/context-engine/src/base/BaseLastUserContentProvider.ts +1 -8
- package/packages/context-engine/src/base/__tests__/BaseEveryUserContentProvider.test.ts +354 -0
- package/packages/context-engine/src/base/constants.ts +20 -0
- package/packages/context-engine/src/engine/messages/MessagesEngine.ts +27 -23
- package/packages/context-engine/src/engine/messages/__tests__/MessagesEngine.test.ts +364 -0
- package/packages/context-engine/src/providers/PageEditorContextInjector.ts +17 -13
- package/packages/context-engine/src/providers/PageSelectionsInjector.ts +65 -0
- package/packages/context-engine/src/providers/__tests__/PageSelectionsInjector.test.ts +333 -0
- package/packages/context-engine/src/providers/index.ts +3 -1
- package/packages/database/src/models/userMemory/model.ts +178 -3
- package/packages/database/src/models/userMemory/sources/benchmarkLoCoMo.ts +1 -1
- package/packages/memory-user-memory/package.json +2 -1
- package/packages/memory-user-memory/promptfoo/evals/activity/basic/buildMessages.ts +40 -0
- package/packages/memory-user-memory/promptfoo/evals/activity/basic/eval.yaml +13 -0
- package/packages/memory-user-memory/promptfoo/evals/activity/basic/prompt.ts +5 -0
- package/packages/memory-user-memory/promptfoo/evals/activity/basic/tests/cases.ts +106 -0
- package/packages/memory-user-memory/promptfoo/evals/activity/locomo/buildMessages.ts +104 -0
- package/packages/memory-user-memory/promptfoo/evals/activity/locomo/eval.yaml +13 -0
- package/packages/memory-user-memory/promptfoo/evals/activity/locomo/prompt.ts +5 -0
- package/packages/memory-user-memory/promptfoo/evals/activity/locomo/tests/benchmark-locomo-payload-conv-26.json +149 -0
- package/packages/memory-user-memory/promptfoo/evals/activity/locomo/tests/cases.ts +72 -0
- package/packages/memory-user-memory/promptfoo/response-formats/activity.json +370 -0
- package/packages/memory-user-memory/promptfoo/response-formats/experience.json +14 -0
- package/packages/memory-user-memory/promptfoo/response-formats/identity.json +281 -255
- package/packages/memory-user-memory/promptfooconfig.yaml +1 -0
- package/packages/memory-user-memory/scripts/generate-response-formats.ts +26 -2
- package/packages/memory-user-memory/src/extractors/activity.ts +44 -0
- package/packages/memory-user-memory/src/extractors/gatekeeper.test.ts +2 -1
- package/packages/memory-user-memory/src/extractors/gatekeeper.ts +2 -1
- package/packages/memory-user-memory/src/extractors/index.ts +1 -0
- package/packages/memory-user-memory/src/prompts/gatekeeper.ts +3 -3
- package/packages/memory-user-memory/src/prompts/index.ts +7 -1
- package/packages/memory-user-memory/src/prompts/layers/activity.ts +90 -0
- package/packages/memory-user-memory/src/prompts/layers/index.ts +1 -0
- package/packages/memory-user-memory/src/providers/existingUserMemory.test.ts +25 -1
- package/packages/memory-user-memory/src/providers/existingUserMemory.ts +113 -0
- package/packages/memory-user-memory/src/schemas/activity.ts +315 -0
- package/packages/memory-user-memory/src/schemas/experience.ts +5 -5
- package/packages/memory-user-memory/src/schemas/gatekeeper.ts +1 -0
- package/packages/memory-user-memory/src/schemas/index.ts +1 -0
- package/packages/memory-user-memory/src/services/extractExecutor.ts +29 -0
- package/packages/memory-user-memory/src/types.ts +7 -0
- package/packages/prompts/src/agents/index.ts +1 -0
- package/packages/prompts/src/agents/pageSelectionContext.ts +28 -0
- package/packages/types/src/aiChat.ts +4 -0
- package/packages/types/src/message/common/index.ts +1 -0
- package/packages/types/src/message/common/metadata.ts +8 -0
- package/packages/types/src/message/common/pageSelection.ts +36 -0
- package/packages/types/src/message/ui/params.ts +16 -0
- package/packages/types/src/serverConfig.ts +1 -1
- package/packages/types/src/userMemory/layers.ts +52 -0
- package/packages/types/src/userMemory/list.ts +20 -2
- package/packages/types/src/userMemory/shared.ts +22 -1
- package/packages/types/src/userMemory/trace.ts +1 -0
- package/packages/types/src/util.ts +9 -1
- package/scripts/prebuild.mts +1 -0
- package/src/features/ChatInput/Desktop/ContextContainer/ContextList.tsx +1 -1
- package/src/features/Conversation/ChatInput/index.tsx +9 -1
- package/src/features/Conversation/Messages/User/components/MessageContent.tsx +7 -1
- package/src/features/Conversation/Messages/User/components/PageSelections.tsx +62 -0
- package/src/features/PageEditor/EditorCanvas/useAskCopilotItem.tsx +5 -1
- package/src/libs/next/proxy/define-config.ts +1 -0
- package/src/locales/default/chat.ts +3 -2
- package/src/server/globalConfig/parseMemoryExtractionConfig.ts +7 -1
- package/src/server/routers/lambda/aiChat.ts +7 -0
- package/src/server/services/memory/userMemory/__tests__/extract.runtime.test.ts +2 -0
- package/src/server/services/memory/userMemory/extract.ts +108 -7
- package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +5 -19
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { renderPlaceholderTemplate } from '@lobechat/context-engine';
|
|
2
|
+
|
|
3
|
+
import { activityPrompt } from '../../../../src/prompts';
|
|
4
|
+
import type { ExtractorTemplateProps } from '../../../../src/types';
|
|
5
|
+
|
|
6
|
+
export interface PromptVars extends ExtractorTemplateProps {
|
|
7
|
+
conversation: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const buildActivityMessages = (vars: PromptVars) => {
|
|
11
|
+
const retrievedContext =
|
|
12
|
+
Array.isArray(vars.retrievedContexts) && vars.retrievedContexts.length > 0
|
|
13
|
+
? vars.retrievedContexts.join('\n\n')
|
|
14
|
+
: typeof vars.retrievedContexts === 'string'
|
|
15
|
+
? vars.retrievedContexts
|
|
16
|
+
: 'No similar memories retrieved.';
|
|
17
|
+
|
|
18
|
+
const rendered = renderPlaceholderTemplate(activityPrompt, {
|
|
19
|
+
availableCategories: vars.availableCategories,
|
|
20
|
+
language: vars.language || 'English',
|
|
21
|
+
retrievedContext,
|
|
22
|
+
sessionDate: vars.sessionDate || new Date().toISOString(),
|
|
23
|
+
topK: vars.topK ?? 5,
|
|
24
|
+
username: vars.username || 'User',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const messages = [
|
|
28
|
+
{ content: rendered, role: 'system' as const },
|
|
29
|
+
{ content: rendered, role: 'user' as const },
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
if (vars.conversation) {
|
|
33
|
+
messages.push({
|
|
34
|
+
content: `Conversation:\n${vars.conversation}`,
|
|
35
|
+
role: 'user' as const,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return messages;
|
|
40
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
description: Regression benchmark for activity layer structured extraction
|
|
2
|
+
|
|
3
|
+
providers:
|
|
4
|
+
- id: openai:chat:gpt-5-mini
|
|
5
|
+
config:
|
|
6
|
+
response_format: file://../../../response-formats/activity.json
|
|
7
|
+
temperature: 0
|
|
8
|
+
|
|
9
|
+
prompts:
|
|
10
|
+
- file://./prompt.ts
|
|
11
|
+
|
|
12
|
+
tests:
|
|
13
|
+
- file://./tests/cases.ts
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
type PromptfooAssert =
|
|
2
|
+
| { type: 'javascript'; value: string }
|
|
3
|
+
| { provider?: string; type: 'llm-rubric'; value: string };
|
|
4
|
+
|
|
5
|
+
interface PromptfooTestCase {
|
|
6
|
+
assert: PromptfooAssert[];
|
|
7
|
+
description?: string;
|
|
8
|
+
vars: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const baseSchemaAssert: PromptfooAssert = {
|
|
12
|
+
type: 'javascript',
|
|
13
|
+
value: `
|
|
14
|
+
let parsed;
|
|
15
|
+
try {
|
|
16
|
+
parsed = JSON.parse(output);
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error('Failed to parse JSON output', error);
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!parsed || !Array.isArray(parsed.memories)) return false;
|
|
23
|
+
|
|
24
|
+
return parsed.memories.every((memory) => {
|
|
25
|
+
return (
|
|
26
|
+
memory.memoryType === 'activity' &&
|
|
27
|
+
memory.title &&
|
|
28
|
+
memory.summary &&
|
|
29
|
+
memory.withActivity?.type &&
|
|
30
|
+
memory.withActivity?.narrative
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
`,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const baseVars = {
|
|
37
|
+
availableCategories: ['work', 'health', 'personal'],
|
|
38
|
+
language: 'English',
|
|
39
|
+
topK: 5,
|
|
40
|
+
username: 'User',
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const testCases: PromptfooTestCase[] = [
|
|
44
|
+
{
|
|
45
|
+
assert: [
|
|
46
|
+
baseSchemaAssert,
|
|
47
|
+
{
|
|
48
|
+
type: 'javascript',
|
|
49
|
+
value: `
|
|
50
|
+
const data = JSON.parse(output);
|
|
51
|
+
const first = data.memories?.[0];
|
|
52
|
+
if (!first) return false;
|
|
53
|
+
|
|
54
|
+
const activity = first.withActivity || {};
|
|
55
|
+
return Boolean(activity.startsAt && activity.endsAt && activity.timezone && activity.associatedLocations?.[0]?.name);
|
|
56
|
+
`,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
provider: 'openai:gpt-5-mini',
|
|
60
|
+
type: 'llm-rubric',
|
|
61
|
+
value:
|
|
62
|
+
'Should extract a meeting activity including timing (start/end/timezone), location name ACME HQ, status completed when implied, and feedback reflecting the positive tone.',
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
description: 'Meeting with explicit time and location',
|
|
66
|
+
vars: {
|
|
67
|
+
...baseVars,
|
|
68
|
+
conversation:
|
|
69
|
+
'User: I met with Alice at ACME HQ on 2024-05-03 from 14:00-15:00 America/New_York. We reviewed Q2 renewal scope and agreed to send revised pricing next week. I felt positive and collaborative about the call.',
|
|
70
|
+
retrievedContexts: ['Previous similar memory: met with Alice about renewal last month.'],
|
|
71
|
+
sessionDate: '2024-05-03',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
assert: [
|
|
76
|
+
baseSchemaAssert,
|
|
77
|
+
{
|
|
78
|
+
type: 'javascript',
|
|
79
|
+
value: `
|
|
80
|
+
const data = JSON.parse(output);
|
|
81
|
+
const first = data.memories?.[0];
|
|
82
|
+
if (!first) return false;
|
|
83
|
+
|
|
84
|
+
const activity = first.withActivity || {};
|
|
85
|
+
return Boolean(activity.narrative && activity.feedback);
|
|
86
|
+
`,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
provider: 'openai:gpt-5-mini',
|
|
90
|
+
type: 'llm-rubric',
|
|
91
|
+
value:
|
|
92
|
+
'Should capture an exercise activity without inventing exact timestamps or timezones; keep the narrative and feedback about the yoga session at home and omit temporal fields that were not provided.',
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
description: 'Exercise without explicit time or timezone',
|
|
96
|
+
vars: {
|
|
97
|
+
...baseVars,
|
|
98
|
+
conversation:
|
|
99
|
+
'User: Over the weekend I did a 30-minute yoga session at home with my roommate. No specific time was set, it was just a casual stretch and it left me feeling calm.',
|
|
100
|
+
retrievedContexts: [],
|
|
101
|
+
sessionDate: '2025-05-05 10:02:00',
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
export default testCases;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { renderPlaceholderTemplate } from '@lobechat/context-engine';
|
|
2
|
+
import { MemorySourceType } from '@lobechat/types';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { isAbsolute, join } from 'node:path';
|
|
5
|
+
|
|
6
|
+
import { BenchmarkLocomoContextProvider, BenchmarkLocomoPart } from '../../../../src/providers';
|
|
7
|
+
import type { IngestPayload } from '../../../../src/converters/locomo';
|
|
8
|
+
import { activityPrompt } from '../../../../src/prompts';
|
|
9
|
+
import type { ExtractorTemplateProps, MemoryExtractionJob } from '../../../../src/types';
|
|
10
|
+
|
|
11
|
+
export interface PromptVars extends ExtractorTemplateProps {
|
|
12
|
+
payloadPath: string;
|
|
13
|
+
sessionId?: string;
|
|
14
|
+
userId?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const resolvePath = (payloadPath: string) =>
|
|
18
|
+
isAbsolute(payloadPath) ? payloadPath : join(process.cwd(), payloadPath);
|
|
19
|
+
|
|
20
|
+
const buildParts = (payload: IngestPayload, sessionId?: string): BenchmarkLocomoPart[] => {
|
|
21
|
+
let partIndex = 0;
|
|
22
|
+
const sessions = payload.sessions.filter(
|
|
23
|
+
(session) => !sessionId || session.sessionId === sessionId,
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
return sessions.flatMap((session) =>
|
|
27
|
+
session.turns.map((turn) => {
|
|
28
|
+
const metadata = {
|
|
29
|
+
diaId: turn.diaId,
|
|
30
|
+
imageCaption: turn.imageCaption,
|
|
31
|
+
imageUrls: turn.imageUrls,
|
|
32
|
+
sessionId: session.sessionId,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
content: turn.text,
|
|
37
|
+
createdAt: turn.createdAt || session.timestamp,
|
|
38
|
+
metadata,
|
|
39
|
+
partIndex: partIndex++,
|
|
40
|
+
sessionId: session.sessionId,
|
|
41
|
+
speaker: turn.speaker,
|
|
42
|
+
};
|
|
43
|
+
}),
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const resolveSessionDate = (payload: IngestPayload, parts: BenchmarkLocomoPart[], sessionId?: string) => {
|
|
48
|
+
const sessionDate =
|
|
49
|
+
payload.sessions.find((session) => session.sessionId === sessionId)?.timestamp ||
|
|
50
|
+
payload.sessions[0]?.timestamp;
|
|
51
|
+
|
|
52
|
+
if (sessionDate) return sessionDate;
|
|
53
|
+
|
|
54
|
+
const latestCreatedAt = parts
|
|
55
|
+
.map((part) => (part.createdAt ? new Date(part.createdAt) : null))
|
|
56
|
+
.filter(Boolean)
|
|
57
|
+
.sort((a, b) => (a!.getTime() > b!.getTime() ? 1 : -1))
|
|
58
|
+
.at(-1);
|
|
59
|
+
|
|
60
|
+
return latestCreatedAt ? latestCreatedAt.toISOString() : new Date().toISOString();
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const buildLocomoActivityMessages = async (vars: PromptVars) => {
|
|
64
|
+
const payloadPath = resolvePath(vars.payloadPath);
|
|
65
|
+
const payloadRaw = await readFile(payloadPath, 'utf8');
|
|
66
|
+
const payload = JSON.parse(payloadRaw) as IngestPayload;
|
|
67
|
+
|
|
68
|
+
const parts = buildParts(payload, vars.sessionId);
|
|
69
|
+
if (parts.length === 0) {
|
|
70
|
+
throw new Error(`No matching parts found in ${payload.sampleId} for session ${vars.sessionId || 'all'}`);
|
|
71
|
+
}
|
|
72
|
+
const userId = vars.userId || `locomo-user-${payload.sampleId}`;
|
|
73
|
+
const sourceId = payload.topicId || `sample_${payload.sampleId}`;
|
|
74
|
+
const sessionDate = vars.sessionDate || resolveSessionDate(payload, parts, vars.sessionId);
|
|
75
|
+
|
|
76
|
+
const provider = new BenchmarkLocomoContextProvider({
|
|
77
|
+
parts,
|
|
78
|
+
sampleId: payload.sampleId,
|
|
79
|
+
sourceId,
|
|
80
|
+
userId,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const extractionJob: MemoryExtractionJob = {
|
|
84
|
+
source: MemorySourceType.BenchmarkLocomo,
|
|
85
|
+
sourceId,
|
|
86
|
+
userId,
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const { context } = await provider.buildContext(extractionJob);
|
|
90
|
+
|
|
91
|
+
const rendered = renderPlaceholderTemplate(activityPrompt, {
|
|
92
|
+
availableCategories: vars.availableCategories,
|
|
93
|
+
language: vars.language || 'English',
|
|
94
|
+
retrievedContext: context || 'No similar memories retrieved.',
|
|
95
|
+
sessionDate,
|
|
96
|
+
topK: vars.topK ?? 5,
|
|
97
|
+
username: vars.username || 'User',
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
return [
|
|
101
|
+
{ content: rendered, role: 'system' as const },
|
|
102
|
+
{ content: rendered, role: 'user' as const },
|
|
103
|
+
];
|
|
104
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
description: LoCoMo regression for activity layer with relative time resolution
|
|
2
|
+
|
|
3
|
+
providers:
|
|
4
|
+
- id: openai:chat:gpt-5-mini
|
|
5
|
+
config:
|
|
6
|
+
response_format: file://../../../response-formats/activity.json
|
|
7
|
+
temperature: 0
|
|
8
|
+
|
|
9
|
+
prompts:
|
|
10
|
+
- file://./prompt.ts
|
|
11
|
+
|
|
12
|
+
tests:
|
|
13
|
+
- file://./tests/cases.ts
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
{
|
|
2
|
+
"force": true,
|
|
3
|
+
"layers": [],
|
|
4
|
+
"sampleId": "conv-26",
|
|
5
|
+
"sessions": [
|
|
6
|
+
{
|
|
7
|
+
"sessionId": "session_1",
|
|
8
|
+
"timestamp": "2023-05-08T13:56:00.000Z",
|
|
9
|
+
"turns": [
|
|
10
|
+
{
|
|
11
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
12
|
+
"diaId": "D1:1",
|
|
13
|
+
"role": "user",
|
|
14
|
+
"speaker": "Caroline",
|
|
15
|
+
"text": "Hey Mel! Good to see you! How have you been?"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
19
|
+
"diaId": "D1:2",
|
|
20
|
+
"role": "assistant",
|
|
21
|
+
"speaker": "Melanie",
|
|
22
|
+
"text": "Hey Caroline! Good to see you! I'm swamped with the kids & work. What's up with you? Anything new?"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
26
|
+
"diaId": "D1:3",
|
|
27
|
+
"role": "user",
|
|
28
|
+
"speaker": "Caroline",
|
|
29
|
+
"text": "I went to a LGBTQ support group yesterday and it was so powerful."
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
33
|
+
"diaId": "D1:4",
|
|
34
|
+
"role": "assistant",
|
|
35
|
+
"speaker": "Melanie",
|
|
36
|
+
"text": "Wow, that's cool, Caroline! What happened that was so awesome? Did you hear any inspiring stories?"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
40
|
+
"diaId": "D1:5",
|
|
41
|
+
"imageCaption": "a photo of a dog walking past a wall with a painting of a woman",
|
|
42
|
+
"imageUrls": [
|
|
43
|
+
"https://i.redd.it/l7hozpetnhlb1.jpg"
|
|
44
|
+
],
|
|
45
|
+
"role": "user",
|
|
46
|
+
"speaker": "Caroline",
|
|
47
|
+
"text": "The transgender stories were so inspiring! I was so happy and thankful for all the support.\n[Image: a photo of a dog walking past a wall with a painting of a woman]"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
51
|
+
"diaId": "D1:6",
|
|
52
|
+
"role": "assistant",
|
|
53
|
+
"speaker": "Melanie",
|
|
54
|
+
"text": "Wow, love that painting! So cool you found such a helpful group. What's it done for you?"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
58
|
+
"diaId": "D1:7",
|
|
59
|
+
"role": "user",
|
|
60
|
+
"speaker": "Caroline",
|
|
61
|
+
"text": "The support group has made me feel accepted and given me courage to embrace myself."
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
65
|
+
"diaId": "D1:8",
|
|
66
|
+
"role": "assistant",
|
|
67
|
+
"speaker": "Melanie",
|
|
68
|
+
"text": "That's really cool. You've got guts. What now?"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
72
|
+
"diaId": "D1:9",
|
|
73
|
+
"role": "user",
|
|
74
|
+
"speaker": "Caroline",
|
|
75
|
+
"text": "Gonna continue my edu and check out career options, which is pretty exciting!"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
79
|
+
"diaId": "D1:10",
|
|
80
|
+
"role": "assistant",
|
|
81
|
+
"speaker": "Melanie",
|
|
82
|
+
"text": "Wow, Caroline! What kinda jobs are you thinkin' of? Anything that stands out?"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
86
|
+
"diaId": "D1:11",
|
|
87
|
+
"role": "user",
|
|
88
|
+
"speaker": "Caroline",
|
|
89
|
+
"text": "I'm keen on counseling or working in mental health - I'd love to support those with similar issues."
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
93
|
+
"diaId": "D1:12",
|
|
94
|
+
"imageCaption": "a photo of a painting of a sunset over a lake",
|
|
95
|
+
"imageUrls": [
|
|
96
|
+
"http://candicealexander.com/cdn/shop/products/IMG_7269_a49d5af8-c76c-4ecd-ae20-48c08cb11dec.jpg"
|
|
97
|
+
],
|
|
98
|
+
"role": "assistant",
|
|
99
|
+
"speaker": "Melanie",
|
|
100
|
+
"text": "You'd be a great counselor! Your empathy and understanding will really help the people you work with. By the way, take a look at this.\n[Image: a photo of a painting of a sunset over a lake]"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
104
|
+
"diaId": "D1:13",
|
|
105
|
+
"role": "user",
|
|
106
|
+
"speaker": "Caroline",
|
|
107
|
+
"text": "Thanks, Melanie! That's really sweet. Is this your own painting?"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
111
|
+
"diaId": "D1:14",
|
|
112
|
+
"role": "assistant",
|
|
113
|
+
"speaker": "Melanie",
|
|
114
|
+
"text": "Yeah, I painted that lake sunrise last year! It's special to me."
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
118
|
+
"diaId": "D1:15",
|
|
119
|
+
"role": "user",
|
|
120
|
+
"speaker": "Caroline",
|
|
121
|
+
"text": "Wow, Melanie! The colors really blend nicely. Painting looks like a great outlet for expressing yourself."
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
125
|
+
"diaId": "D1:16",
|
|
126
|
+
"role": "assistant",
|
|
127
|
+
"speaker": "Melanie",
|
|
128
|
+
"text": "Thanks, Caroline! Painting's a fun way to express my feelings and get creative. It's a great way to relax after a long day."
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
132
|
+
"diaId": "D1:17",
|
|
133
|
+
"role": "user",
|
|
134
|
+
"speaker": "Caroline",
|
|
135
|
+
"text": "Totally agree, Mel. Relaxing and expressing ourselves is key. Well, I'm off to go do some research."
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"createdAt": "2023-05-08T13:56:00.000Z",
|
|
139
|
+
"diaId": "D1:18",
|
|
140
|
+
"role": "assistant",
|
|
141
|
+
"speaker": "Melanie",
|
|
142
|
+
"text": "Yep, Caroline. Taking care of ourselves is vital. I'm off to go swimming with the kids. Talk to you soon!"
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
"source": "benchmark_locomo",
|
|
148
|
+
"topicId": "sample_conv-26"
|
|
149
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
type PromptfooAssert =
|
|
2
|
+
| { type: 'javascript'; value: string }
|
|
3
|
+
| { provider?: string; type: 'llm-rubric'; value: string };
|
|
4
|
+
|
|
5
|
+
interface PromptfooTestCase {
|
|
6
|
+
assert: PromptfooAssert[];
|
|
7
|
+
description?: string;
|
|
8
|
+
vars: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const baseSchemaAssert: PromptfooAssert = {
|
|
12
|
+
type: 'javascript',
|
|
13
|
+
value: `
|
|
14
|
+
let parsed;
|
|
15
|
+
try {
|
|
16
|
+
parsed = JSON.parse(output);
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error('Failed to parse JSON output', error);
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!parsed || !Array.isArray(parsed.memories)) return false;
|
|
23
|
+
|
|
24
|
+
return parsed.memories.every((memory) => {
|
|
25
|
+
return memory.memoryType === 'activity' && memory.withActivity?.type;
|
|
26
|
+
});
|
|
27
|
+
`,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const testCases: PromptfooTestCase[] = [
|
|
31
|
+
{
|
|
32
|
+
assert: [
|
|
33
|
+
baseSchemaAssert,
|
|
34
|
+
{
|
|
35
|
+
type: 'javascript',
|
|
36
|
+
value: `
|
|
37
|
+
const data = JSON.parse(output);
|
|
38
|
+
const target = data.memories?.find((memory) => {
|
|
39
|
+
const text = [memory.title, memory.summary, memory.withActivity?.narrative]
|
|
40
|
+
.filter(Boolean)
|
|
41
|
+
.join(' ')
|
|
42
|
+
.toLowerCase();
|
|
43
|
+
return text.includes('support group');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (!target) return false;
|
|
47
|
+
const startsAt = target.withActivity?.startsAt;
|
|
48
|
+
if (!startsAt) return false;
|
|
49
|
+
|
|
50
|
+
return String(startsAt).startsWith('2023-05-07');
|
|
51
|
+
`,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
provider: 'openai:gpt-5-mini',
|
|
55
|
+
type: 'llm-rubric',
|
|
56
|
+
value:
|
|
57
|
+
'Should extract the LGBTQ support group activity from session_1 diaId D1:3, convert "yesterday" relative to the 2023-05-08 session anchor into 2023-05-07, and include a narrative about feeling supported/accepted.',
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
description: 'LoCoMo conv-26 session_1 resolves relative date',
|
|
61
|
+
vars: {
|
|
62
|
+
availableCategories: ['personal'],
|
|
63
|
+
language: 'English',
|
|
64
|
+
payloadPath: './promptfoo/evals/activity/locomo/tests/benchmark-locomo-payload-conv-26.json',
|
|
65
|
+
sessionId: 'session_1',
|
|
66
|
+
topK: 3,
|
|
67
|
+
username: 'Caroline',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
export default testCases;
|