@lobehub/chat 1.26.9 → 1.26.10

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 CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.26.10](https://github.com/lobehub/lobe-chat/compare/v1.26.9...v1.26.10)
6
+
7
+ <sup>Released on **2024-10-29**</sup>
8
+
9
+ #### ♻ Code Refactoring
10
+
11
+ - **misc**: Refactor the aiChat slice actions.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Code refactoring
19
+
20
+ - **misc**: Refactor the aiChat slice actions, closes [#4542](https://github.com/lobehub/lobe-chat/issues/4542) ([8b33ba4](https://github.com/lobehub/lobe-chat/commit/8b33ba4))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ### [Version 1.26.9](https://github.com/lobehub/lobe-chat/compare/v1.26.8...v1.26.9)
6
31
 
7
32
  <sup>Released on **2024-10-29**</sup>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.26.9",
3
+ "version": "1.26.10",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -2,8 +2,8 @@ import { useCallback, useMemo } from 'react';
2
2
 
3
3
  import { useChatStore } from '@/store/chat';
4
4
  import { chatSelectors } from '@/store/chat/selectors';
5
- import { SendMessageParams } from '@/store/chat/slices/aiChat/action';
6
5
  import { fileChatSelectors, useFileStore } from '@/store/file';
6
+ import { SendMessageParams } from '@/types/message';
7
7
 
8
8
  export type UseSendMessageParams = Pick<
9
9
  SendMessageParams,
@@ -0,0 +1,117 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { ChatFileItem, ChatImageItem } from '@/types/message';
4
+
5
+ import { filesPrompts } from './index';
6
+
7
+ describe('filesPrompts', () => {
8
+ // 创建测试用的示例数据
9
+ const mockImage: ChatImageItem = {
10
+ id: 'img-1',
11
+ alt: 'test image',
12
+ url: 'https://example.com/image.jpg',
13
+ };
14
+
15
+ const mockFile: ChatFileItem = {
16
+ id: 'file-1',
17
+ name: 'test.pdf',
18
+ fileType: 'application/pdf',
19
+ size: 1024,
20
+ url: 'https://example.com/test.pdf',
21
+ };
22
+
23
+ it('should generate prompt with only images', () => {
24
+ const result = filesPrompts({
25
+ imageList: [mockImage],
26
+ fileList: undefined,
27
+ });
28
+
29
+ expect(result).toEqual(
30
+ `<files_info>
31
+ <images>
32
+ <images_docstring>here are user upload images you can refer to</images_docstring>
33
+ <image name="test image" url="https://example.com/image.jpg"></image>
34
+ </images>
35
+
36
+ </files_info>`,
37
+ );
38
+ });
39
+
40
+ it('should generate prompt with only files', () => {
41
+ const result = filesPrompts({
42
+ imageList: [],
43
+ fileList: [mockFile],
44
+ });
45
+
46
+ expect(result).toEqual(
47
+ `<files_info>
48
+
49
+ <files>
50
+ <files_docstring>here are user upload files you can refer to</files_docstring>
51
+ <file id="file-1" name="test.pdf" type="application/pdf" size="1024" url="https://example.com/test.pdf"></file>
52
+ </files>
53
+ </files_info>`,
54
+ );
55
+ });
56
+
57
+ it('should generate prompt with both images and files', () => {
58
+ const result = filesPrompts({
59
+ imageList: [mockImage],
60
+ fileList: [mockFile],
61
+ });
62
+
63
+ expect(result).toEqual(
64
+ `<files_info>
65
+ <images>
66
+ <images_docstring>here are user upload images you can refer to</images_docstring>
67
+ <image name="test image" url="https://example.com/image.jpg"></image>
68
+ </images>
69
+ <files>
70
+ <files_docstring>here are user upload files you can refer to</files_docstring>
71
+ <file id="file-1" name="test.pdf" type="application/pdf" size="1024" url="https://example.com/test.pdf"></file>
72
+ </files>
73
+ </files_info>`,
74
+ );
75
+ });
76
+
77
+ it('should generate prompt with empty lists', () => {
78
+ const result = filesPrompts({
79
+ imageList: [],
80
+ fileList: [],
81
+ });
82
+
83
+ expect(result).toEqual('');
84
+ });
85
+
86
+ it('should handle multiple images and files', () => {
87
+ const images: ChatImageItem[] = [
88
+ mockImage,
89
+ {
90
+ id: 'img-2',
91
+ alt: 'second image',
92
+ url: 'https://example.com/image2.jpg',
93
+ },
94
+ ];
95
+
96
+ const files: ChatFileItem[] = [
97
+ mockFile,
98
+ {
99
+ id: 'file-2',
100
+ name: 'document.docx',
101
+ fileType: 'application/docx',
102
+ size: 2048,
103
+ url: 'https://example.com/document.docx',
104
+ },
105
+ ];
106
+
107
+ const result = filesPrompts({
108
+ imageList: images,
109
+ fileList: files,
110
+ });
111
+
112
+ expect(result).toContain('second image');
113
+ expect(result).toContain('document.docx');
114
+ expect(result).toMatch(/<image.*?>.*<image.*?>/s); // Check for multiple image tags
115
+ expect(result).toMatch(/<file.*?>.*<file.*?>/s); // Check for multiple file tags
116
+ });
117
+ });
@@ -10,6 +10,8 @@ export const filesPrompts = ({
10
10
  fileList?: ChatFileItem[];
11
11
  imageList: ChatImageItem[];
12
12
  }) => {
13
+ if (imageList.length === 0 && (fileList || []).length === 0) return '';
14
+
13
15
  const prompt = `<files_info>
14
16
  ${imagesPrompts(imageList)}
15
17
  ${fileList ? filePrompts(fileList) : ''}
@@ -422,7 +422,7 @@ class ChatService {
422
422
 
423
423
  const filesContext = filesPrompts({ fileList: m.fileList, imageList });
424
424
  return [
425
- { text: m.content + '\n\n' + filesContext, type: 'text' },
425
+ { text: (m.content + '\n\n' + filesContext).trim(), type: 'text' },
426
426
  ...imageList.map(
427
427
  (i) => ({ image_url: { detail: 'auto', url: i.url }, type: 'image_url' }) as const,
428
428
  ),
@@ -14,7 +14,7 @@ import { sessionMetaSelectors } from '@/store/session/selectors';
14
14
  import { UploadFileItem } from '@/types/files/upload';
15
15
  import { ChatMessage } from '@/types/message';
16
16
 
17
- import { useChatStore } from '../../store';
17
+ import { useChatStore } from '../../../../store';
18
18
 
19
19
  vi.stubGlobal(
20
20
  'fetch',
@@ -16,27 +16,14 @@ import { chatHelpers } from '@/store/chat/helpers';
16
16
  import { ChatStore } from '@/store/chat/store';
17
17
  import { messageMapKey } from '@/store/chat/utils/messageMapKey';
18
18
  import { useSessionStore } from '@/store/session';
19
- import { UploadFileItem } from '@/types/files/upload';
20
- import { ChatMessage, CreateMessageParams } from '@/types/message';
19
+ import { ChatMessage, CreateMessageParams, SendMessageParams } from '@/types/message';
21
20
  import { MessageSemanticSearchChunk } from '@/types/rag';
22
21
  import { setNamespace } from '@/utils/storeDebug';
23
22
 
24
- import { chatSelectors, topicSelectors } from '../../selectors';
25
- import { ChatRAGAction, chatRag } from './actions/rag';
23
+ import { chatSelectors, topicSelectors } from '../../../selectors';
26
24
 
27
25
  const n = setNamespace('ai');
28
26
 
29
- export interface SendMessageParams {
30
- message: string;
31
- files?: UploadFileItem[];
32
- onlyAddUserMessage?: boolean;
33
- /**
34
- *
35
- * https://github.com/lobehub/lobe-chat/pull/2086
36
- */
37
- isWelcomeQuestion?: boolean;
38
- }
39
-
40
27
  interface ProcessMessageParams {
41
28
  traceId?: string;
42
29
  isWelcomeQuestion?: boolean;
@@ -46,7 +33,7 @@ interface ProcessMessageParams {
46
33
  ragQuery?: string;
47
34
  }
48
35
 
49
- export interface ChatAIChatAction extends ChatRAGAction {
36
+ export interface AIGenerateAction {
50
37
  /**
51
38
  * Sends a new message to the AI chat system
52
39
  */
@@ -110,14 +97,12 @@ const getAgentConfig = () => agentSelectors.currentAgentConfig(useAgentStore.get
110
97
  const getAgentChatConfig = () => agentSelectors.currentAgentChatConfig(useAgentStore.getState());
111
98
  const getAgentKnowledge = () => agentSelectors.currentEnabledKnowledge(useAgentStore.getState());
112
99
 
113
- export const chatAiChat: StateCreator<
100
+ export const generateAIChat: StateCreator<
114
101
  ChatStore,
115
102
  [['zustand/devtools', never]],
116
103
  [],
117
- ChatAIChatAction
118
- > = (set, get, ...rest) => ({
119
- ...chatRag(set, get, ...rest),
120
-
104
+ AIGenerateAction
105
+ > = (set, get) => ({
121
106
  delAndRegenerateMessage: async (id) => {
122
107
  const traceId = chatSelectors.getTraceIdByMessageId(id)(get());
123
108
  get().internal_resendMessage(id, traceId);
@@ -0,0 +1,20 @@
1
+ import { StateCreator } from 'zustand/vanilla';
2
+
3
+ import { ChatStore } from '@/store/chat/store';
4
+
5
+ import { AIGenerateAction, generateAIChat } from './generateAIChat';
6
+ import { ChatRAGAction, chatRag } from './rag';
7
+
8
+ export interface ChatAIChatAction extends ChatRAGAction, AIGenerateAction {
9
+ /**/
10
+ }
11
+
12
+ export const chatAiChat: StateCreator<
13
+ ChatStore,
14
+ [['zustand/devtools', never]],
15
+ [],
16
+ ChatAIChatAction
17
+ > = (...params) => ({
18
+ ...chatRag(...params),
19
+ ...generateAIChat(...params),
20
+ });
@@ -13,7 +13,7 @@ import { ChatMessageAction, chatMessage } from './slices/message/action';
13
13
  import { ChatPluginAction, chatPlugin } from './slices/plugin/action';
14
14
  import { ShareAction, chatShare } from './slices/share/action';
15
15
  import { ChatTopicAction, chatTopic } from './slices/topic/action';
16
- import { chatAiChat, ChatAIChatAction } from './slices/aiChat/action';
16
+ import { chatAiChat, ChatAIChatAction } from './slices/aiChat/actions';
17
17
 
18
18
  export interface ChatStoreAction
19
19
  extends ChatMessageAction,
@@ -2,6 +2,7 @@ import { IPluginErrorType } from '@lobehub/chat-plugin-sdk';
2
2
 
3
3
  import { ILobeAgentRuntimeErrorType } from '@/libs/agent-runtime';
4
4
  import { ErrorType } from '@/types/fetch';
5
+ import { UploadFileItem } from '@/types/files';
5
6
  import { MessageSemanticSearchChunk } from '@/types/rag';
6
7
 
7
8
  import { BaseDataModel } from '../meta';
@@ -131,3 +132,14 @@ export interface CreateMessageParams
131
132
  topicId?: string;
132
133
  traceId?: string;
133
134
  }
135
+
136
+ export interface SendMessageParams {
137
+ files?: UploadFileItem[];
138
+ /**
139
+ *
140
+ * https://github.com/lobehub/lobe-chat/pull/2086
141
+ */
142
+ isWelcomeQuestion?: boolean;
143
+ message: string;
144
+ onlyAddUserMessage?: boolean;
145
+ }