Browse Source

feat: update api name and fix some style bug

林艳 4 days ago
parent
commit
6a2acfe622

+ 9 - 0
packages/semi-foundation/aiChatDialogue/aiChatDialogue.scss

@@ -79,6 +79,10 @@ $module: #{$prefix}-ai-chat-dialogue;
         max-width: $width-aiChatDialogue_content_max;
         font-size: $font-aiChatDialogue_content-fontSize;
 
+        pre {
+            background-color: transparent;
+        } 
+
         &-editing {
             width: $width-aiChatDialogue_content_editing;
         }
@@ -88,6 +92,10 @@ $module: #{$prefix}-ai-chat-dialogue;
             align-items: end;
         }
 
+        &-inner {
+            margin-left: auto;
+        }
+
         &-failed {
             color: $color-aiChatDialogue_failed;
             margin-right: $spacing-aiChatDialogue_content_failed-marginRight;
@@ -595,6 +603,7 @@ $module: #{$prefix}-ai-chat-dialogue;
             margin: 0px;
             background: $color-aiChatDialogue_code_content-bg;
         } 
+
     }
 
     &-hints {

+ 2 - 1
packages/semi-foundation/aiChatDialogue/dataAdapter/chatCompletionToMessage.ts

@@ -1,3 +1,4 @@
+import { Message } from 'aiChatDialogue/foundation';
 import { ChatCompletion, Choice, ToolCalls, FunctionToolCall, CustomToolCall } from './interface';
 /* 
 Chat Completion VS. Response
@@ -5,7 +6,7 @@ Chat Completion VS. Response
 - The former annotations belongs to content;
 - The former function_call and tool_calls do not have call_id and status;
 */
-export default function chatCompletionToMessage(chatCompletion: ChatCompletion) {
+export default function chatCompletionToMessage(chatCompletion: ChatCompletion): Message[] {
     return chatCompletion.choices.map((choice: Choice) => {
         const message = choice.message;
         const role = message.role;

+ 3 - 1
packages/semi-foundation/aiChatDialogue/dataAdapter/index.ts

@@ -2,11 +2,13 @@ import responseToMessage from './responseToMessage';
 import chatCompletionToMessage from './chatCompletionToMessage';
 import streamingChatCompletionToMessage from './streamingChatCompletionToMessage';
 import streamingResponseToMessage from './streamingResponseToMessage';
+import aiChatInputContentToMessage from './aiChatInputContentToMessage';
 
 
 export { 
     chatCompletionToMessage, 
     streamingChatCompletionToMessage, 
     responseToMessage, 
-    streamingResponseToMessage 
+    streamingResponseToMessage,
+    aiChatInputContentToMessage,
 };

+ 2 - 1
packages/semi-foundation/aiChatDialogue/dataAdapter/interface.ts

@@ -144,7 +144,8 @@ export interface Response {
     max_tool_calls?: number;
     model?: string;
     object?: string;
-    output?: ContentItem;
+    output?: ContentItem | ContentItem[];
+    output_text?: string;
     parallel_tool_calls?: boolean;
     previous_response_id?: string;
     reasoning?: ResponseReasoning;

+ 3 - 2
packages/semi-foundation/aiChatDialogue/dataAdapter/responseToMessage.ts

@@ -1,12 +1,13 @@
+import { Message, ContentItem } from 'aiChatDialogue/foundation';
 import { Response } from './interface';
 
-export default function responseToMessage(response: Response) {
+export default function responseToMessage(response: Response): Message {
     const { id, model, status, output, output_text, created_at } = response;
 
     return {
         id: id,
         role: "assistant",
-        content: output,
+        content: output as (string | ContentItem[]),
         createdAt: created_at,
         output_text: output_text,
         model: model,

+ 6 - 2
packages/semi-foundation/aiChatDialogue/dataAdapter/streamingChatCompletionToMessage.ts

@@ -39,13 +39,17 @@ export default function streamingChatCompletionToMessage(chatCompletionChunks: C
                 refusal += delta.refusal;
             }
             if (delta?.function_call) {
-                functionCall.name += delta.function_call.name;
+                if (delta.function_call.name) {
+                    functionCall.name += delta.function_call.name;
+                }
                 functionCall.arguments += delta.function_call.arguments;
             }
             if (delta?.tool_calls) {
                 delta?.tool_calls.forEach((toolCall: FunctionToolCall) => {
                     if (toolCalls[toolCall.id]) {
-                        toolCalls[toolCall.id].name += toolCall.function.name;
+                        if (toolCall.function.name) {
+                            toolCalls[toolCall.id].name += toolCall.function.name;
+                        }
                         toolCalls[toolCall.id].arguments += toolCall.function.arguments;
                     } else {
                         toolCalls[toolCall.id] = {

+ 1 - 2
packages/semi-foundation/aiChatDialogue/foundation.ts

@@ -143,7 +143,7 @@ export interface Message {
     updatedAt?: number;
     model?: string;
     status?: string;
-    type?: string;
+    // type?: string;
     [x: string]: any
 }
 
@@ -153,7 +153,6 @@ export type InputContentItem = InputMessage | ItemReference;
 export type OutputContentItem = OutputMessage | ToolCallContentItem | MCPContentItem | Reasoning ;
 
 export type ToolCallContentItem = FileSearchToolCall | WebSearchToolCall | FunctionToolCall | CustomToolCall | ImageGenerationCall| CustomObject;
-// todo: 补全 MCP 的所有类型
 export type MCPContentItem = MCPToolCall;
 
 export interface CommonContentItem {

+ 1 - 1
packages/semi-foundation/aiChatDialogue/variables.scss

@@ -34,7 +34,7 @@ $color-aiChatDialogue_video_icon-bg: rgba(var(--semi-green-4), 1); // video icon
 $color-aiChatDialogue_default_icon-bg: rgba(var(--semi-grey-4), 1); // default icon 背景色
 $color-aiChatDialogue_icon-text: var(--semi-color-white); // icon 文本颜色
 $color-aiChatDialogue_failed: var(--semi-color-danger); // 失败提示颜色
-$color-aiChatDialogue_code_content-bg: rgba(var(--semi-teal-4), 1); // code content 背景色
+$color-aiChatDialogue_code_content-bg: var(--semi-color-bg-0); // code content 背景色
 
 // Width/Height
 $width-aiChatDialogue_wrapper: 100%; // 外层宽度

+ 8 - 8
packages/semi-ui/aiChatDialogue/Dialogue.tsx

@@ -23,23 +23,23 @@ class AIChatDialogue extends BaseComponent<AIChatDialogueItemProps, AIChatDialog
     }
 
     avatarNode = () => {
-        const { role, renderConfig } = this.props;
+        const { role, dialogueRenderConfig } = this.props;
         return <DialogueAvatar
             role={role}
-            customRenderFunc={renderConfig?.renderDialogueAvatar}
+            customRenderFunc={dialogueRenderConfig?.renderDialogueAvatar}
         />;
     };
 
     titleNode = () => {
-        const { role, renderConfig } = this.props;
+        const { role, dialogueRenderConfig } = this.props;
         return <DialogueTitle 
             role={role}
-            customRenderFunc={renderConfig?.renderDialogueTitle}
+            customRenderFunc={dialogueRenderConfig?.renderDialogueTitle}
         />;
     };
 
     contentNode = () => {
-        const { message, mode, renderConfig, customMarkDownComponents, markdownRenderProps, messageEditRender, onFileClick, onImageClick, disabledFileItemClick, renderDialogueContentItem, onAnnotationClick } = this.props;
+        const { message, mode, dialogueRenderConfig, customMarkDownComponents, markdownRenderProps, messageEditRender, onFileClick, onImageClick, disabledFileItemClick, renderDialogueContentItem, onAnnotationClick } = this.props;
 
         return <DialogueContent 
             key={message.editing}
@@ -53,13 +53,13 @@ class AIChatDialogue extends BaseComponent<AIChatDialogueItemProps, AIChatDialog
             renderDialogueContentItem={renderDialogueContentItem}
             onAnnotationClick={onAnnotationClick}
             customMarkDownComponents={customMarkDownComponents}
-            customRenderFunc={renderConfig?.renderDialogueContent}
+            customRenderFunc={dialogueRenderConfig?.renderDialogueContent}
             markdownRenderProps={markdownRenderProps} 
         />;
     };
 
     actionNode = () => {
-        const { role, message, showReset, isLastChat, renderConfig,
+        const { role, message, showReset, isLastChat, dialogueRenderConfig,
             onMessageReset, onMessageGoodFeedback, onMessageBadFeedback, onMessageCopy, 
             onMessageShare, messageEditRender, onMessageEdit, onMessageDelete
         } = this.props;
@@ -77,7 +77,7 @@ class AIChatDialogue extends BaseComponent<AIChatDialogueItemProps, AIChatDialog
             onMessageEdit={onMessageEdit}
             onMessageDelete={onMessageDelete}
             messageEditRender={messageEditRender}
-            customRenderFunc={renderConfig?.renderDialogueAction}
+            customRenderFunc={dialogueRenderConfig?.renderDialogueAction}
         />;
     };
 

+ 1 - 5
packages/semi-ui/aiChatDialogue/_story/DataAdapter/streamingChatCompletionToMessage.jsx

@@ -33,9 +33,8 @@ export default function StreamingChatCompletionToMessageDemo() {
     }, []);
 
     useEffect(() => {
-        // 以 100ms 为间隔,从 1 块逐步增加到全部块,模拟流输出
+        // 以 100ms 为间隔,从 1 块逐步增加到全部块,模拟流输出
         const total = STREAMING_CHAT_COMPLETION_DATA.length;
-        const accByIndex = new Map();
         let i = 1;
 
         const timer = setInterval(() => {
@@ -48,9 +47,6 @@ export default function StreamingChatCompletionToMessageDemo() {
             const { messages: partial, state: nextState } = streamingChatCompletionToMessage(slice, state);
             setState(nextState);
 
-            // 基于当前新增的最后一块,确定其 choice index 并合并
-            const lastChunk = slice[slice.length - 1];
-
             // 将合并后的消息映射转换为数组,并加上默认的用户消息
             const merged = [defaultMessages[0], ...partial];
             setMessage(merged);

+ 0 - 3
packages/semi-ui/aiChatDialogue/_story/DataAdapter/streamingResponseToMessage.jsx

@@ -86,11 +86,8 @@ export default function StreamingResponseToMessageDemo() {
             if (result) {
                 const { message: responseMessage, nextState } = result;
 
-                console.log('currentChunks', REASONING_CHUNKS[2], nextState);
-
                 // 更新消息列表 / Update message list
                 if (responseMessage) {
-                    console.log('responseMessage', responseMessage);
                     setMessage([...defaultMessages, responseMessage]);
                 }
                 

+ 2 - 26
packages/semi-ui/aiChatDialogue/_story/aiChatDialogue.stories.jsx

@@ -387,7 +387,7 @@ export const Action = () => {
       mode="bubble"
       chats={messages}
       roleConfig={roleConfig}
-      isSelecting={selected}
+      selecting={selected}
       onMessageCopy={(message) => {
         console.log('onMessageCopy', message);
       }}
@@ -485,7 +485,7 @@ export const Selecting = () => {
             align={align}
             mode="bubble"
             chats={defaultMessages}
-            isSelecting={select}
+            selecting={select}
             onSelect={onSelect}
             roleConfig={roleConfig}
             hints={hints}
@@ -720,13 +720,6 @@ export const Hints = () => {
     )
 }
 
-// export const Response2Message = ResponseToMessageDemo;
-// export const ChatCompletion2Message = ChatCompletionToMessageDemo;
-// export const StreamingResponse2Message = StreamingResponseToMessageDemo;
-
-// ResponseToMessageDemo.story = {
-//   name: 'response to message',
-// };
 
 export const ResponseToMessageStory = () => <ResponseToMessageDemo />;
 ResponseToMessageStory.storyName =  'adapter: response';
@@ -740,22 +733,5 @@ StreamingResponseToMessageStory.storyName =  'adapter: streaming response';
 export const StreamingChatCompletionToMessageStory = () => <StreamingChatCompletionToMessageDemo />;
 StreamingChatCompletionToMessageStory.storyName =  'adapter: streaming chatCompletion';
 
-// export const Streaming = () => {
-//     const [messages, setMessage] = useState(defaultMessages);
-
-//     const onChatsChange = useCallback((chats) => {
-//         setMessage(chats);
-//     }, []);
-  
-//     return (
-//       <AIChatDialogue 
-//           align="leftRight"
-//           mode="bubble"
-//           chats={messages}
-//           roleConfig={roleConfig}
-//           onChatsChange={onChatsChange}
-//       />
-//     )
-// }
 
 

+ 1 - 1
packages/semi-ui/aiChatDialogue/interface.ts

@@ -33,7 +33,7 @@ export interface AIChatDialogueProps {
     onMessageReset?: (message?: Message) => void;
     onMessageShare?: (message?: Message) => void;
     onSelect?: (selectedIds: string[]) => void;
-    renderConfig?: DialogueRenderConfig; 
+    dialogueRenderConfig?: DialogueRenderConfig;
     renderDialogueContentItem?: (message?: Message) => DialogueContentItemRendererMap;
     renderHintBox?: (props: {content: string; index: number;onHintClick: () => void}) => React.ReactNode;
     roleConfig: RoleConfig;

+ 4 - 3
packages/semi-ui/aiChatDialogue/widgets/dialogueContent.tsx

@@ -34,8 +34,9 @@ const DialogueContent = (props: DialogueContentProps) => {
         const bubble = mode === MODE.BUBBLE;
         const userBubble = mode === MODE.USER_BUBBLE && isUser;
         return cls({
-            [`${PREFIX_CONTENT}-no-bubble`]: true,
+            [`${PREFIX_CONTENT}`]: true,
             [`${PREFIX_CONTENT}-${mode}`]: bubble || userBubble,
+            [`${PREFIX_CONTENT}-no-bubble`]: !(bubble || userBubble),
             [`${PREFIX_CONTENT}-user`]: (bubble && isUser) || userBubble,
             [`${PREFIX_CONTENT}-error`]: status === STATUS.FAILED && (bubble || userBubble)
         });
@@ -285,10 +286,10 @@ const DialogueContent = (props: DialogueContentProps) => {
             }
             return (
                 <div className={`${PREFIX_CONTENT}-wrapper`}>
-                    {status === STATUS.FAILED && <div className={`${PREFIX_CONTENT}-failed`}>
+                    {(status === STATUS.FAILED || status === STATUS.CANCELLED) && <div className={`${PREFIX_CONTENT}-failed`}>
                         <IconAlertCircle />
                     </div>}
-                    <div>{realContent}</div>
+                    <div className={`${PREFIX_CONTENT}-inner`}>{realContent}</div>
                 </div>
             );
         }