Skip to main content

x-chat-provider

Focus on implementing custom Chat Provider, helping to adapt any streaming interface to Ant Design X standard format

소스 정보

저장소
modelscope/ms-agent
최근 소스 활동
2026년 9월 8일 10:28
감지된 SKILL.md 언어
영어
스타
4,408
포크
528

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
2 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
x-chat-provider
version
2.8.1
description
Focus on implementing custom Chat Provider, helping to adapt any streaming interface to Ant Design X standard format
# 🎯 Skill Positioning **This skill focuses on solving one problem**: How to quickly adapt your streaming interface to Ant Design X's Chat Provider. **Not involved**: useXChat usage tutorial (that's another skill). ## Table of Contents - [📦 Technology Stack Overview](#-technology-stack-overview) - [🚀 Quick Start](#-quick-start) - [Built-in Provider](#built-in-provider) - [When to Use Custom Provider](#when-to-use-custom-provider) - [📋 Four Steps to Implement Custom Provider](#-four-steps-to-implement-custom-provider) - [🔑 Core Types and Exports](#-core-types-and-exports) - [⚙️ XRequest Advanced Configuration](#️-xrequest-advanced-configuration) - [callbacks](#callbacks) - [retryInterval Retry](#retryinterval-retry) - [transformStream Custom Stream](#transformstream-custom-stream) - [🔧 Common Scenario Adaptation](#-common-scenario-adaptation) - [⚠️ Important Reminders](#️-important-reminders) - [⚡ Quick Checklist](#-quick-checklist) - [🚨 Development Rules](#-development-rules) - [🔗 Reference Resources](#-reference-resources) # 📦 Technology Stack Overview | Layer | Package Name | Core Purpose | | ---------------- | -------------------------- | -------------------------- | | **UI Layer** | **@ant-design/x** | React UI component library | | **Logic Layer** | **@ant-design/x-sdk** | Development toolkit | | **Render Layer** | **@ant-design/x-markdown** | Markdown renderer | ```ts // ✅ Correct import examples import { Bubble } from '@ant-design/x'; import { AbstractChatProvider, OpenAIChatProvider } from '@ant-design/x-sdk'; import XRequest from '@ant-design/x-sdk'; ``` # 🚀 Quick Start ### 🎯 Provider Selection Decision Tree ```mermaid graph TD A[Start] --> B{Use standard OpenAI/DeepSeek API?} B -->|Yes| C[Use built-in Provider] B -->|No| D{Raw data format as message?} D -->|Yes| E[Use DefaultChatProvider] D -->|No| F[Custom Provider] C --> G[OpenAIChatProvider / DeepSeekChatProvider] E --> H[Pass-through, no conversion needed] F --> I[Four-step custom Provider] ``` ### 🏭 Built-in Provider Overview | Provider Type | Applicable Scenario | Import | | --- | --- | --- | | **OpenAIChatProvider** | Standard OpenAI API format | `import { OpenAIChatProvider } from '@ant-design/x-sdk'` | | **DeepSeekChatProvider** | Standard DeepSeek API format | `import { DeepSeekChatProvider } from '@ant-design/x-sdk'` | | **DefaultChatProvider** | Pass-through raw response, no format conversion | `import { DefaultChatProvider } from '@ant-design/x-sdk'` | > ⚠️ Export names are `OpenAIChatProvider` / `DeepSeekChatProvider` / `DefaultChatProvider`, watch spelling #### DefaultChatProvider Use Case `DefaultChatProvider` **passes through raw response data** without any conversion. Suitable for: - The interface response format is already what you want to display - You want full control over `Bubble.List`'s `contentRender` to render messages ```ts import { DefaultChatProvider, XRequest } from '@ant-design/x-sdk'; interface ChatInput { query: string; stream?: boolean; } interface ChatOutput { choices: Array<{ message: { content: string; role: string } }>; } // DefaultChatProvider generic: <ChatMessage, Input, Output> // ChatMessage is your Output type (passed through directly) const provider = new DefaultChatProvider<ChatOutput | ChatInput, ChatInput, ChatOutput>({ request: XRequest('https://your-api.com/chat', { manual: true, params: { stream: false }, }), }); // Render using contentRender in Bubble.List's role config // role={{ assistant: { contentRender(content) { return content?.choices?.[0]?.message?.content } } }} ``` > ⚠️ When using `DefaultChatProvider`, `ChatMessage` is typically your `Output` type or a union type; rendering requires `contentRender` # 📋 Four Steps to Implement Custom Provider ## Step 1: Analyze Interface Format ⏱️ 2 minutes | Information Type | Example Value | | ------------------- | --------------------------- | | **Interface URL** | `https://your-api.com/chat` | | **Request Method** | JSON, POST | | **Response Format** | Server-Sent Events | | **Auth Method** | Bearer Token | ## Step 2: Create Provider Class ⏱️ 5 minutes ```ts // MyChatProvider.ts import { AbstractChatProvider } from '@ant-design/x-sdk'; import type { TransformMessage } from '@ant-design/x-sdk'; import type { XRequestOptions } from '@ant-design/x-sdk'; interface MyInput { query: string; model?: string; stream?: boolean; } interface MyOutput { content: string; finish_reason?: string; } interface MyMessage { content: string; role: 'user' | 'assistant'; } export class MyChatProvider extends AbstractChatProvider<MyMessage, MyInput, MyOutput> { // Parameter conversion: merge onRequest params + XRequest default params // options comes from XRequest(url, options), can access options.params etc. transformParams( requestParams: Partial<MyInput>, options: XRequestOptions<MyInput, MyOutput, MyMessage>, ): MyInput { return { ...(options?.params || {}), query: requestParams.query || '', model: 'gpt-3.5-turbo', stream: true, }; } // Local message: convert onRequest params to the user-side display message (can return array) transformLocalMessage(requestParams: Partial<MyInput>): MyMessage { return { content: requestParams.query || '', role: 'user', }; } // Response conversion: // info.originMessage: previous content of this message (for stream accumulation) // info.chunk: current streaming chunk // info.chunks: all received chunks (used in onSuccess) // info.status: current status // ⚠️ Return only MyMessage type; do NOT add a status field transformMessage(info: TransformMessage<MyMessage, MyOutput>): MyMessage { const { originMessage, chunk } = info; if (!chunk?.content || chunk.content === '[DONE]') { return { ...(originMessage || { content: '', role: 'assistant' }) }; } return { content: `${originMessage?.content || ''}${chunk.content}`, role: 'assistant', }; } } ``` ## Step 3: Verify ⏱️ 1 minute | Check Item | Description | | ----------------------------- | ------------------------------------------------------------- | | **Only 3 methods** | transformParams, transformLocalMessage, transformMessage | | **transformParams signature** | Must include second parameter `options: XRequestOptions<...>` | | **No status in return** | transformMessage return value has no status field | | **No request method** | Confirm no request method implemented | | **Type check passes** | `tsc --noEmit` no errors | ## Step 4: Use Provider ⏱️ 1 minute ```ts import { MyChatProvider } from './MyChatProvider'; import XRequest from '@ant-design/x-sdk'; // ⚠️ Must pass manual: true, otherwise AbstractChatProvider constructor will throw const provider = new MyChatProvider({ request: XRequest('https://your-api.com/chat', { manual: true, headers: { Authorization: 'Bearer your-token', 'Content-Type': 'application/json', }, params: { model: 'gpt-3.5-turbo', stream: true, }, }), }); export { provider }; ``` # 🔑 Core Types and Exports Key types exported from `@ant-design/x-sdk`: ```ts import type { // OpenAI standard message format XModelMessage, // { role: string; content: string | { text: string; type: string } } XModelParams, // Full OpenAI request params type (model, messages, stream, temperature, etc.) XModelResponse, // Full OpenAI response type (choices, usage, etc.) // SSE stream field types SSEFields, // 'data' | 'event' | 'id' | 'retry' SSEOutput, // Partial<Record<SSEFields, any>> // Provider related TransformMessage, // { originMessage, chunk, chunks, status, responseHeaders } // XRequest related XRequestOptions, // Full request config XRequestCallbacks, // { onUpdate, onSuccess, onError } // Message related MessageInfo, // { id, message, status, extraInfo } } from '@ant-design/x-sdk'; ``` ### XModelMessage Structure (OpenAI message format) ```ts // XModelMessage is the standard OpenAI message format // Used for OpenAIChatProvider / DeepSeekChatProvider ChatMessage generic const userMessage: XModelMessage = { role: 'user', content: 'Hello' }; const systemMessage: XModelMessage = { role: 'system', content: 'You are an assistant' }; const developerMessage: XModelMessage = { role: 'developer', content: 'System prompt' }; ``` ### SSEOutput and SSEFields ```ts // SSEOutput is the type for raw SSE stream data // { data?: string; event?: string; id?: string; retry?: number } // DeepSeekChatProvider uses Partial<Record<SSEFields, XModelResponse>> import { DeepSeekChatProvider, XRequest } from '@ant-design/x-sdk'; import type { SSEFields, XModelParams, XModelResponse } from '@ant-design/x-sdk'; const provider = new DeepSeekChatProvider({ request: XRequest<XModelParams, Partial<Record<SSEFields, XModelResponse>>>( 'https://api.deepseek.com/v1/chat/completions', { manual: true, params: { model: 'deepseek-chat', stream: true }, }, ), }); ``` # ⚙️ XRequest Advanced Configuration ## callbacks `callbacks` allows monitoring request events at the Provider level. The third parameter in callbacks is the `MessageInfo` processed by `transformMessage`: ```ts const provider = new OpenAIChatProvider({ request: XRequest<XModelParams, XModelResponse, XModelMessage>(BASE_URL, { manual: true, callbacks: { // onUpdate: triggered on each streaming chunk arrival // chunk: current chunk; responseHeaders: response headers; message: current MessageInfo onUpdate: (chunk, responseHeaders, message) => { console.log('Stream update:', message?.message?.content); }, // onSuccess: triggered when all chunks are received // chunks: all chunks array; message: final MessageInfo onSuccess: (chunks, responseHeaders, message) => { console.log('Request complete:', message?.message?.content); // Good place for analytics, logging, etc. }, // onError: triggered on request failure (including AbortError) // error: error object; errorInfo: extra error info; message: MessageInfo at failure onError: (error, errorInfo, responseHeaders, message) => { console.error('Request failed:', error.message); }, }, params: { model: 'gpt-4o', stream: true }, }), }); ``` > ⚠️ `callbacks` and `useXChat`'s `requestFallback` do not conflict — both execute. `callbacks` is better for logging/reporting; `requestFallback` controls UI display. ## retryInterval Retry ```ts const request = XRequest('https://your-api.com/chat', { manual: true, // Retry interval after failure (ms) retryInterval: 3000, // Max retry count (unlimited if not set) retryTimes: 3, // onError can also return a number to dynamically set retry interval callbacks: { onError: (error) => { if (error.name === 'AbortError') return; // Don't retry on user cancel return 5000; // Return number = retry after 5s (higher priority than retryInterval) }, },
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기