@lobehub/chat 1.134.3 → 1.134.5

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.
Files changed (47) hide show
  1. package/.github/workflows/docker-database.yml +2 -0
  2. package/.github/workflows/docker-pglite.yml +2 -0
  3. package/.github/workflows/docker.yml +2 -0
  4. package/.github/workflows/release.yml +6 -0
  5. package/.github/workflows/sync-database-schema.yml +2 -0
  6. package/CHANGELOG.md +50 -0
  7. package/changelog/v1.json +14 -0
  8. package/docs/development/database-schema.dbml +27 -0
  9. package/package.json +3 -2
  10. package/packages/database/migrations/0036_add_group_messages.sql +21 -0
  11. package/packages/database/migrations/meta/0036_snapshot.json +6772 -0
  12. package/packages/database/migrations/meta/_journal.json +7 -0
  13. package/packages/database/package.json +1 -1
  14. package/packages/database/src/core/migrations.json +15 -0
  15. package/packages/database/src/models/__tests__/aiModel.test.ts +43 -0
  16. package/packages/database/src/models/aiModel.ts +25 -1
  17. package/packages/database/src/repositories/tableViewer/index.test.ts +1 -1
  18. package/packages/database/src/schemas/_helpers.ts +3 -1
  19. package/packages/database/src/schemas/message.ts +55 -4
  20. package/packages/database/src/schemas/relations.ts +24 -1
  21. package/packages/database/src/utils/idGenerator.ts +1 -0
  22. package/packages/prompts/CLAUDE.md +329 -0
  23. package/packages/prompts/README.md +224 -0
  24. package/packages/prompts/package.json +14 -1
  25. package/packages/prompts/promptfoo/emoji-picker/eval.yaml +170 -0
  26. package/packages/prompts/promptfoo/emoji-picker/prompt.ts +16 -0
  27. package/packages/prompts/promptfoo/knowledge-qa/eval.yaml +89 -0
  28. package/packages/prompts/promptfoo/knowledge-qa/prompt.ts +26 -0
  29. package/packages/prompts/promptfoo/language-detection/eval.yaml +65 -0
  30. package/packages/prompts/promptfoo/language-detection/prompt.ts +16 -0
  31. package/packages/prompts/promptfoo/summary-title/eval.yaml +85 -0
  32. package/packages/prompts/promptfoo/summary-title/prompt.ts +18 -0
  33. package/packages/prompts/promptfoo/translate/eval.yaml +79 -0
  34. package/packages/prompts/promptfoo/translate/prompt.ts +18 -0
  35. package/packages/prompts/promptfooconfig.yaml +35 -0
  36. package/packages/prompts/src/chains/__tests__/__snapshots__/answerWithContext.test.ts.snap +164 -0
  37. package/packages/prompts/src/chains/__tests__/__snapshots__/pickEmoji.test.ts.snap +58 -0
  38. package/packages/prompts/src/chains/__tests__/__snapshots__/summaryTitle.test.ts.snap +26 -0
  39. package/packages/prompts/src/chains/__tests__/__snapshots__/translate.test.ts.snap +22 -0
  40. package/packages/prompts/src/chains/__tests__/answerWithContext.test.ts +18 -63
  41. package/packages/prompts/src/chains/__tests__/pickEmoji.test.ts +2 -37
  42. package/packages/prompts/src/chains/__tests__/summaryTitle.test.ts +2 -16
  43. package/packages/prompts/src/chains/__tests__/translate.test.ts +1 -12
  44. package/packages/prompts/src/chains/answerWithContext.ts +45 -21
  45. package/packages/prompts/src/chains/pickEmoji.ts +20 -6
  46. package/packages/prompts/src/chains/summaryTitle.ts +20 -15
  47. package/packages/prompts/src/chains/translate.ts +8 -2
@@ -11,25 +11,11 @@ describe('chainSummaryTitle', () => {
11
11
  { content: 'I need help with my account.', role: 'user' },
12
12
  ];
13
13
  const currentLanguage = 'en-US';
14
- const tokenCount = 10000; // Arbitrary token count below the GPT-3.5 limit
15
14
 
16
15
  // Act
17
- const result = await chainSummaryTitle(messages, currentLanguage);
16
+ const result = chainSummaryTitle(messages, currentLanguage);
18
17
 
19
18
  // Assert
20
- expect(result).toEqual({
21
- messages: [
22
- {
23
- content: '你是一名擅长会话的助理,你需要将用户的会话总结为 10 个字以内的标题',
24
- role: 'system',
25
- },
26
- {
27
- content: `assistant: Hello, how can I assist you?\nuser: I need help with my account.
28
-
29
- 请总结上述对话为10个字以内的标题,不需要包含标点符号,输出语言语种为:${currentLanguage}`,
30
- role: 'user',
31
- },
32
- ],
33
- });
19
+ expect(result).toMatchSnapshot();
34
20
  });
35
21
  });
@@ -12,17 +12,6 @@ describe('chainTranslate', () => {
12
12
  const result = chainTranslate(content, targetLang);
13
13
 
14
14
  // Assert
15
- expect(result).toEqual({
16
- messages: [
17
- {
18
- content: '你是一名擅长翻译的助理,你需要将输入的语言翻译为目标语言',
19
- role: 'system',
20
- },
21
- {
22
- content: `请将以下内容 ${content},翻译为 ${targetLang} `,
23
- role: 'user',
24
- },
25
- ],
26
- });
15
+ expect(result).toMatchSnapshot();
27
16
  });
28
17
  });
@@ -1,33 +1,57 @@
1
1
  import { ChatStreamPayload } from '@lobechat/types';
2
2
 
3
+ interface AnswerWithContext {
4
+ context: string[];
5
+ knowledge: string[];
6
+ question: string;
7
+ }
3
8
  export const chainAnswerWithContext = ({
4
9
  context,
5
10
  knowledge,
6
11
  question,
7
- }: {
8
- context: string[];
9
- knowledge: string[];
10
- question: string;
11
- }): Partial<ChatStreamPayload> => ({
12
- messages: [
13
- {
14
- content: `You are also a helpful assistant good answering questions related to ${knowledge.join('/')}. And you'll be provided with a question and several passages that might be relevant. And currently your task is to provide answer based on the question and passages.
12
+ }: AnswerWithContext): Partial<ChatStreamPayload> => {
13
+ const filteredContext = context.filter((c) => c.trim());
14
+ const hasContext = filteredContext.length > 0;
15
+
16
+ return {
17
+ messages: [
18
+ {
19
+ content: hasContext
20
+ ? `You are a helpful assistant specialized in ${knowledge.join('/')}. Your task is to answer questions based on the provided context passages.
21
+
22
+ IMPORTANT RULES:
23
+ - First, check if the context is relevant to the question topic
24
+ - If the context is about a COMPLETELY DIFFERENT topic than the question:
25
+ * State what topic the context is about
26
+ * Clearly state "The provided context does not contain information about [question topic]"
27
+ * Do NOT answer using your general knowledge
28
+ - If the context is related to the question topic (even if information is limited):
29
+ * ALWAYS use the context information as a foundation
30
+ * You SHOULD supplement with your general knowledge to provide a complete, helpful answer
31
+ * For "how to" questions, MUST provide practical, actionable steps combining context + your expertise
32
+ * The context provides the topic relevance - you provide the comprehensive answer
33
+ * Example: If context mentions "Docker is for containerization", and question is "How to deploy with Docker?", you should explain deployment steps using your knowledge
34
+ - Answer in the same language as the question
35
+ - Use markdown formatting for better readability
36
+
37
+ The provided context passages:
15
38
 
16
- Note that passages might not be relevant to the question, please only use the passages that are relevant. Or if there is no relevant passage, please answer using your knowledge.
39
+ <context>
40
+ ${filteredContext.join('\n')}
41
+ </context>
17
42
 
18
- Answer should use the same original language as the question and follow markdown syntax.
43
+ Question to answer:
19
44
 
20
- The provided passages as context:
45
+ ${question}`
46
+ : `You are a helpful assistant specialized in ${knowledge.join('/')}. Please answer the following question using your knowledge.
21
47
 
22
- <Context>
23
- ${context.join('\n')}
24
- </Context>
48
+ Answer in the same language as the question and use markdown formatting for better readability.
25
49
 
26
- The question to answer is:
50
+ Question to answer:
27
51
 
28
- ${question}
29
- `,
30
- role: 'user',
31
- },
32
- ],
33
- });
52
+ ${question}`,
53
+ role: 'user',
54
+ },
55
+ ],
56
+ };
57
+ };
@@ -7,25 +7,39 @@ import { ChatStreamPayload } from '@lobechat/types';
7
7
  export const chainPickEmoji = (content: string): Partial<ChatStreamPayload> => ({
8
8
  messages: [
9
9
  {
10
- content:
11
- '你是一名擅长进行概念抽象的设计师与 Emoji 专家,你需要根据角色能力的描述抽象出一个表达物理实体的概念 Emoji 作为角色头像, 格式要求如下:\n输入: {文本作为JSON引用字符串}\n输出: {一个Emoji}',
10
+ content: `You are an emoji expert who selects the most appropriate emoji to represent concepts, emotions, or topics.
11
+
12
+ Rules:
13
+ - Output ONLY a single emoji (1-2 characters maximum)
14
+ - Focus on the CONTENT meaning, not the language it's written in
15
+ - Choose an emoji that best represents the core topic, activity, or subject matter
16
+ - Prioritize topic-specific emojis over generic emotion emojis (e.g., for sports, use 🏃 instead of 😅)
17
+ - For work/projects, use work-related emojis (💼, 🚀, 💪) not cultural symbols
18
+ - For pure emotions without specific topics, use face emojis (happy: 🎉, sad: 😢, thinking: 🤔)
19
+ - For activities or subjects, use object or symbol emojis that represent the main topic
20
+ - No explanations or additional text`,
12
21
  role: 'system',
13
22
  },
14
23
  {
15
- content: `输入: {你是一名文案大师,帮我为一些设计 / 艺术作品起名,名字需要有文学内涵,注重精炼和赋子意境,表达作品的情景氛国,使名称既简洁又富有诗意。}`,
24
+ content: 'I am a copywriting master who helps name design and art works with literary depth',
16
25
  role: 'user',
17
26
  },
18
27
  { content: '✒️', role: 'assistant' },
19
28
  {
20
- content: `输入: {你是一名代码巫师,请将下面的代码转成 ts,不要修改实现。如果原本 js 中没有定义的全局变量,需要补充 declare 的类型声明。}`,
29
+ content: 'I am a code wizard who converts JavaScript code to TypeScript',
21
30
  role: 'user',
22
31
  },
23
32
  { content: '🧙‍♂️', role: 'assistant' },
24
33
  {
25
- content: `输入: {你是一名创业计划撰写专家,可以提供包括创意名称、简短的标语、目标用户画像、用户痛点、主要价值主张、销售/营销渠道、收入流、成本结构等计划生成。}`,
34
+ content: 'I just got a promotion at work',
35
+ role: 'user',
36
+ },
37
+ { content: '🎉', role: 'assistant' },
38
+ {
39
+ content: 'I am a business plan expert who helps with startup strategies and marketing',
26
40
  role: 'user',
27
41
  },
28
42
  { content: '🚀', role: 'assistant' },
29
- { content: `输入: {${content}}`, role: 'user' },
43
+ { content, role: 'user' },
30
44
  ],
31
45
  });
@@ -3,19 +3,24 @@ import { ChatStreamPayload, OpenAIChatMessage } from '@/types/openai/chat';
3
3
  export const chainSummaryTitle = (
4
4
  messages: OpenAIChatMessage[],
5
5
  locale: string,
6
- ): Partial<ChatStreamPayload> => {
7
- return {
8
- messages: [
9
- {
10
- content: '你是一名擅长会话的助理,你需要将用户的会话总结为 10 个字以内的标题',
11
- role: 'system',
12
- },
13
- {
14
- content: `${messages.map((message) => `${message.role}: ${message.content}`).join('\n')}
6
+ ): Partial<ChatStreamPayload> => ({
7
+ messages: [
8
+ {
9
+ content: `You are a professional conversation summarizer. Generate a concise title that captures the essence of the conversation.
15
10
 
16
- 请总结上述对话为10个字以内的标题,不需要包含标点符号,输出语言语种为:${locale}`,
17
- role: 'user',
18
- },
19
- ],
20
- };
21
- };
11
+ Rules:
12
+ - Output ONLY the title text, no explanations or additional context
13
+ - Maximum 10 words
14
+ - Maximum 50 characters
15
+ - No punctuation marks
16
+ - Use the language specified by the locale code: ${locale}
17
+ - The title should accurately reflect the main topic of the conversation
18
+ - Keep it short and to the point`,
19
+ role: 'system',
20
+ },
21
+ {
22
+ content: messages.map((message) => `${message.role}: ${message.content}`).join('\n'),
23
+ role: 'user',
24
+ },
25
+ ],
26
+ });
@@ -6,11 +6,17 @@ export const chainTranslate = (
6
6
  ): Partial<ChatStreamPayload> => ({
7
7
  messages: [
8
8
  {
9
- content: '你是一名擅长翻译的助理,你需要将输入的语言翻译为目标语言',
9
+ content: `You are a professional translator. Translate the input text to ${targetLang}.
10
+
11
+ Rules:
12
+ - Output ONLY the translated text, no explanations or additional context
13
+ - Preserve technical terms, code identifiers, API keys, and proper nouns exactly as they appear
14
+ - Maintain the original formatting and structure
15
+ - Use natural, idiomatic expressions in the target language`,
10
16
  role: 'system',
11
17
  },
12
18
  {
13
- content: `请将以下内容 ${content},翻译为 ${targetLang} `,
19
+ content,
14
20
  role: 'user',
15
21
  },
16
22
  ],