> ## Documentation Index
> Fetch the complete documentation index at: https://ai-kb.automationanywhere.com/llms.txt
> Use this file to discover all available pages before exploring further.

# チャットSDK

> EKB Chat SDK を使用して、会話型 AI インターフェイスをアプリケーションに統合します。

ChatSDK は、会話型 AI アプリケーションを簡単に構築できるようにする EKB Content Creator SDK のコア コンポーネントです。包括的なチャット管理、メッセージ処理、ストリーミング応答、ナレッジベースの統合を提供します。この記事では、SDK をインストールし、「クイック スタート」の例を使用してすぐに起動して実行する方法を学びます。さまざまな構成オプションを調べ、認証と、この SDK で使用できる中心的なメソッドについて学ぶことができます。使用例も見つかります

## インストール

```bash theme={null}
npm install @odin-ai-staging/sdk
```

## クイックスタート

```typescript theme={null}
import { ChatSDK } from '@odin-ai-staging/sdk';

// Initialize the SDK
const chatSDK = new ChatSDK({
  baseUrl: 'https://your-api-endpoint.com/',
  projectId: 'your-project-id',
  apiKey: 'your-api-key',
  apiSecret: 'your-api-secret'
});

// Create a chat and send a message
async function quickExample() {
  // Create a new chat
  const chat = await chatSDK.createChat('My First Chat');
  
  // Send a message
  const response = await chatSDK.sendMessage('Hello, how can you help me?', {
    chatId: chat.chat_id
  });
  
  console.log('AI Response:', response.message);
}
```

＃＃ 構成

### ChatSDKConfig インターフェイス

```typescript theme={null}
interface ChatSDKConfig {
  baseUrl: string;          // API endpoint URL
  projectId: string;        // Your project identifier
  apiKey?: string;          // API key for authentication
  apiSecret?: string;       // API secret for authentication
  accessToken?: string;     // Access token for web app usage
}
```

### 構成オプション

* **baseUrl**: API エンドポイントのベース URL
* **projectId**: 一意のプロジェクト識別子
* **apiKey** および **apiSecret**: サーバー側認証用
* **accessToken**: クライアント側認証用 (Web アプリ)

## 認証

ChatSDK は 2 つの認証方法をサポートしています。

### API キー認証 (サーバー側)

```typescript theme={null}
const chatSDK = new ChatSDK({
  baseUrl: 'https://api.example.com/',
  projectId: 'proj_123',
  apiKey: 'your-api-key',
  apiSecret: 'your-api-secret'
});
```

### アクセストークン認証 (クライアント側)

```typescript theme={null}
const chatSDK = new ChatSDK({
  baseUrl: 'https://api.example.com/',
  projectId: 'proj_123',
  accessToken: 'your-access-token'
});
```

## コアメソッド

### チャット管理

#### `createChat(name?, documentKeys?)`

新しいチャット会話を作成します。

```typescript theme={null}
async createChat(
  name?: string,           // Optional chat name (defaults to "Untitled")
  documentKeys?: string[]  // Optional document keys for knowledge base context
): Promise<CreateChatResponse>
```

**例：**

```typescript theme={null}
// Create a basic chat
const chat = await chatSDK.createChat('Customer Support Chat');

// Create a chat with knowledge base context
const chatWithDocs = await chatSDK.createChat(
  'Product Documentation Chat',
  ['doc_key_1', 'doc_key_2']
);
```

#### `listChats(cursor?, limit?)`

プロジェクト内のチャットのページ分割されたリストを取得します。

```typescript theme={null}
async listChats(
  cursor?: number,  // Optional cursor for pagination
  limit?: number    // Number of chats to return (default: 30, max: 100)
): Promise<ListChatsResponse>
```

**例：**

```typescript theme={null}
// Get first 10 chats
const chats = await chatSDK.listChats(undefined, 10);

// Get next page using cursor
if (chats.next_cursor) {
  const nextPage = await chatSDK.listChats(chats.next_cursor, 10);
}
```

#### `getChatHistory(chatId)`

完全なメッセージ履歴を含むチャットを取得します。

```typescript theme={null}
async getChatHistory(chatId: string): Promise<ChatHistoryResponse>
```

**例：**

```typescript theme={null}
const chatHistory = await chatSDK.getChatHistory('chat_123');
console.log('Messages:', chatHistory.messages);
```

#### `deleteChat(chatId)`

チャットとそのすべてのメッセージを完全に削除します。

```typescript theme={null}
async deleteChat(chatId: string): Promise<void>
```

**例：**

```typescript theme={null}
await chatSDK.deleteChat('chat_123');
```

#### `updateChatName(chatId, newName)`

既存のチャットの表示名を更新します。

```typescript theme={null}
async updateChatName(chatId: string, newName: string): Promise<void>
```

**例：**

```typescript theme={null}
await chatSDK.updateChatName('chat_123', 'Updated Chat Name');
```

### メッセージの処理

#### `sendMessage(message, options?)`

メッセージを送信し、AI 応答を受け取ります。

```typescript theme={null}
async sendMessage(
  message: string,
  options?: SendMessageOptions
): Promise<SendMessageResponse>
```

**SendMessageOptions:**

```typescript theme={null}
interface SendMessageOptions {
  chatId?: string;          // Target chat ID
  agentType?: AgentType;    // Type of AI agent to use
  agentId?: string;         // Specific agent ID
  documentKeys?: string[];  // Knowledge base documents
  images?: File[];          // Image attachments
  metadata?: Record<string, any>;  // Custom metadata
  modelName?: ModelName;    // AI model to use
  useKnowledgebase?: boolean;      // Enable knowledge base
  isTest?: boolean;         // Test mode flag
  googleSearch?: boolean;   // Enable web search
  formatInstructions?: string;     // Response format guidance
  ignoreChatHistory?: boolean;     // Ignore conversation history
  exampleJson?: string;     // Example JSON for structured responses
  skipStream?: boolean;     // Disable streaming
}
```

**例：**

```typescript theme={null}
// Basic message
const response = await chatSDK.sendMessage('What is artificial intelligence?', {
  chatId: 'chat_123'
});

// Advanced message with options
const advancedResponse = await chatSDK.sendMessage(
  'Analyze this data and provide insights',
  {
    chatId: 'chat_123',
    modelName: 'gpt-4o',
    useKnowledgebase: true,
    googleSearch: true,
    formatInstructions: 'Provide response in bullet points'
  }
);
```

#### `sendFeedback(messageId, chatId, feedback)`

AI の応答に関するフィードバックを提供します。

```typescript theme={null}
async sendFeedback(
  messageId: string,
  chatId: string,
  feedback: boolean  // true = thumbs up, false = thumbs down
): Promise<void>
```

**例：**

```typescript theme={null}
// Positive feedback
await chatSDK.sendFeedback('msg_123', 'chat_123', true);

// Negative feedback
await chatSDK.sendFeedback('msg_123', 'chat_123', false);
```

## ストリーミングのサポート

### `sendMessageStream(message, options)`

リアルタイムのストリーミング応答でメッセージを送信します。

```typescript theme={null}
async sendMessageStream(
  message: string,
  options: SendMessageOptions & StreamCallbacks
): Promise<void>
```

**ストリームコールバック:**

```typescript theme={null}
interface StreamCallbacks {
  onChunk?: (chunk: string) => void;           // Text chunks
  onMessageObject?: (messageObject: any) => void;  // Structured data
  onComplete?: (message: Message) => void;     // Final message
  onError?: (error: Error) => void;           // Error handler
  onChatNameUpdate?: (chatName: string) => void;   // Chat name changes
  onDocumentChunk?: (chunk: string) => void;  // Document processing updates
  onMessageEnd?: () => void;                  // Stream completion
}
```

**例：**

```typescript theme={null}
await chatSDK.sendMessageStream(
  'Tell me about machine learning',
  {
    chatId: 'chat_123',
    onChunk: (chunk) => {
      // Display text as it streams in
      console.log('Chunk:', chunk);
      updateUI(chunk);
    },
    onComplete: (message) => {
      console.log('Complete message:', message);
      finalizeUI(message);
    },
    onError: (error) => {
      console.error('Stream error:', error);
      showError(error.message);
    }
  }
);
```

## エラー処理

SDK は、API 関連のエラーに対して `APIError` オブジェクトをスローします。

```typescript theme={null}
interface APIError {
  message: string;  // Error description
  status: number;   // HTTP status code
  detail?: string;  // Additional error details
}
```

**例：**

```typescript theme={null}
try {
  const response = await chatSDK.sendMessage('Hello');
} catch (error) {
  if (error instanceof APIError) {
    console.error(`API Error ${error.status}: ${error.message}`);
    if (error.detail) {
      console.error('Details:', error.detail);
    }
  } else {
    console.error('Unexpected error:', error);
  }
}
```

## 例

### 基本的なチャット アプリケーション

この例では、EKB SDK を使用して、単純な非ストリーミング メッセージ交換を行う基本的なチャット アプリケーションを構築する方法を学習します。まず、環境変数 (ベース URL、プロジェクト ID、API キー、およびシークレット) から取得した API 資格情報を使用して ChatSDK を初期化する `SimpleChatApp` クラスを作成します。このクラスは、`currentChatId` を使用して現在のチャット セッションを追跡し、3 つの主要なメソッドを提供します。`startNewChat()` はカスタム名で新しいチャット会話を作成し、`sendMessage()` は AI にメッセージを送信して完全な応答を返します (チャットが存在しない場合は自動的に新しいチャットを作成します)。`getChatList()` は既存のチャット会話をすべて取得します。ストリーミング実装とは異なり、このアプローチは完全な AI 応答を待ってから表示するため、リアルタイムのトークンごとの更新が必要ない単純なユースケースに最適です。この例では GPT-4o-mini モデルを使用しており、会話フローの追跡に役立つコンソール ログ機能を備えたエラー処理が全体に含まれており、ストリーミング コールバックの複雑さを必要とせずに、基本的なチャットボット機能を構築するための簡単な基盤が提供されます。

```typescript theme={null}
import { ChatSDK } from '@odin-ai-staging/sdk';

class SimpleChatApp {
  private chatSDK: ChatSDK;
  private currentChatId?: string;

  constructor() {
    this.chatSDK = new ChatSDK({
      baseUrl: process.env.API_BASE_URL,
      projectId: process.env.PROJECT_ID,
      apiKey: process.env.API_KEY,
      apiSecret: process.env.API_SECRET
    });
  }

  async startNewChat(name: string = 'New Chat') {
    try {
      const chat = await this.chatSDK.createChat(name);
      this.currentChatId = chat.chat_id;
      console.log(`Created chat: ${chat.name} (${chat.chat_id})`);
      return chat;
    } catch (error) {
      console.error('Failed to create chat:', error);
      throw error;
    }
  }

  async sendMessage(message: string) {
    if (!this.currentChatId) {
      await this.startNewChat();
    }

    try {
      const response = await this.chatSDK.sendMessage(message, {
        chatId: this.currentChatId,
        modelName: 'gpt-4o-mini'
      });

      console.log('User:', message);
      console.log('AI:', response.message);
      
      return response;
    } catch (error) {
      console.error('Failed to send message:', error);
      throw error;
    }
  }

  async getChatList() {
    try {
      const chats = await this.chatSDK.listChats();
      return chats.chats;
    } catch (error) {
      console.error('Failed to get chat list:', error);
      throw error;
    }
  }
}

// Usage
const app = new SimpleChatApp();
await app.sendMessage('Hello, how are you?');
```

### リアルタイム更新によるストリーミング チャット

この例では、EKB API に接続し、AI 応答をリアルタイムで表示するストリーミング チャット インターフェイスを構築する方法を学びます。まず、API 資格情報とメッセージが表示される HTML 要素への参照を使用して ChatSDK を初期化する `StreamingChat` クラスを作成します。 `sendStreamingMessage()` を使用してメッセージを送信する場合、ストリーミング応答が到着したときにそれを処理するコールバック ハンドラーをセットアップします。`onChunk` コールバックは、各テキストを UI にすぐに追加します (特徴的な「入力」効果を作成します)。一方、`onMessageObject` を使用すると、画像などのリッチ コンテンツを処理できます。また、`onError` を使用してエラー処理を実装し、`onChatNameUpdate` を使用してチャット タイトルを更新し、メッセージのストリーミングが終了したら `onComplete` を使用して親指を上げる/下げるフィードバック ボタンを追加します。この例では、画像を動的に表示し、AI 応答に関するユーザー フィードバックを収集し、ナレッジ ベース統合で GPT-4o を使用するようにチャットを構成する方法を示します。これにより、リアルタイム ストリーミング応答とインタラクティブ機能を備えた ChatGPT のようなインターフェイスを作成するために必要なものがすべて提供されます。

```typescript theme={null}
import { ChatSDK, StreamCallbacks } from '@odin-ai-staging/sdk';

class StreamingChat {
  private chatSDK: ChatSDK;
  private messageElement: HTMLElement;

  constructor(messageElement: HTMLElement) {
    this.messageElement = messageElement;
    this.chatSDK = new ChatSDK({
      baseUrl: 'https://your-api.com/',
      projectId: 'your-project-id',
      accessToken: 'your-access-token'
    });
  }

  async sendStreamingMessage(message: string, chatId: string) {
    // Clear previous content
    this.messageElement.innerHTML = '';

    const callbacks: StreamCallbacks = {
      onChunk: (chunk: string) => {
        // Append each chunk to the UI
        this.messageElement.innerHTML += chunk;
        this.messageElement.scrollIntoView();
      },

      onMessageObject: (messageObj: any) => {
        // Handle structured data like images, cards, etc.
        if (messageObj.image_urls) {
          this.displayImages(messageObj.image_urls);
        }
      },

      onComplete: (message: any) => {
        console.log('Message complete:', message);
        // Add final styling, enable feedback buttons, etc.
        this.finalizeMessage(message);
      },

      onError: (error: Error) => {
        console.error('Streaming error:', error);
        this.messageElement.innerHTML = `Error: ${error.message}`;
      },

      onChatNameUpdate: (chatName: string) => {
        // Update chat title in UI
        document.title = chatName;
      }
    };

    try {
      await this.chatSDK.sendMessageStream(message, {
        chatId,
        modelName: 'gpt-4o',
        useKnowledgebase: true,
        ...callbacks
      });
    } catch (error) {
      console.error('Failed to send streaming message:', error);
    }
  }

  private displayImages(imageUrls: string[]) {
    imageUrls.forEach(url => {
      const img = document.createElement('img');
      img.src = url;
      img.style.maxWidth = '100%';
      this.messageElement.appendChild(img);
    });
  }

  private finalizeMessage(message: any) {
    // Add feedback buttons
    const feedbackDiv = document.createElement('div');
    feedbackDiv.innerHTML = `
      <button onclick="this.provideFeedback('${message.id}', true)">👍</button>
      <button onclick="this.provideFeedback('${message.id}', false)">👎</button>
    `;
    this.messageElement.appendChild(feedbackDiv);
  }

  async provideFeedback(messageId: string, isPositive: boolean) {
    try {
      await this.chatSDK.sendFeedback(messageId, 'chat_id', isPositive);
      console.log('Feedback sent successfully');
    } catch (error) {
      console.error('Failed to send feedback:', error);
    }
  }
}
```

### ナレッジベースの統合

この例では、ナレッジ ベースにアップロードした特定のドキュメントに基づいて質問に回答できる、ナレッジ ベースを利用したチャット アプリケーションを構築する方法を説明します。 `KnowledgeBasedChat` クラスは、環境変数からの API 認証情報を使用して ChatSDK を初期化し、次に 2 つの主要なメソッドを使用してドキュメントを操作します。 `createDocumentChat()` は、documentKeys (アップロードされたドキュメントの一意の識別子) の配列を渡すことで特定のドキュメントにリンクされた新しいチャット セッションを設定し、`askDocumentQuestion()` はナレッジ ベース機能を有効にして AI に質問を送信します。質問するときは、`useKnowledgebase: true` を使用するようにチャットを構成し、AI がドキュメントから関連情報を確実に取得できるように `agentType: 'document_agent'` を指定します。また、`formatInstructions` は、出典の引用を含めるよう AI に指示します。応答には、AI が応答を生成するときにどのドキュメントを参照したかを示すソース プロパティが含まれているため、ドキュメント Q\&A システム、リサーチ アシスタント、または一般的な知識ではなく特定のコンテンツに基づいた AI 応答が必要なアプリケーションの構築に最適です。これにより、AI がどのように答えに到達したかを完全に透明化できます。

```typescript theme={null}
import { ChatSDK } from '@odin-ai-staging/sdk';

class KnowledgeBasedChat {
  private chatSDK: ChatSDK;

  constructor() {
    this.chatSDK = new ChatSDK({
      baseUrl: process.env.API_BASE_URL,
      projectId: process.env.PROJECT_ID,
      apiKey: process.env.API_KEY,
      apiSecret: process.env.API_SECRET
    });
  }

  async createDocumentChat(documentKeys: string[], chatName?: string) {
    try {
      const chat = await this.chatSDK.createChat(
        chatName || 'Document Q&A',
        documentKeys
      );
      
      console.log(`Created document chat with ${documentKeys.length} documents`);
      return chat;
    } catch (error) {
      console.error('Failed to create document chat:', error);
      throw error;
    }
  }

  async askDocumentQuestion(question: string, chatId: string, documentKeys?: string[]) {
    try {
      const response = await this.chatSDK.sendMessage(question, {
        chatId,
        documentKeys,
        useKnowledgebase: true,
        agentType: 'document_agent',
        formatInstructions: 'Provide citations for your sources'
      });

      // Display sources if available
      if (response.message.sources) {
        console.log('Sources:', response.message.sources);
      }

      return response;
    } catch (error) {
      console.error('Failed to ask document question:', error);
      throw error;
    }
  }
}

// Usage
const kbChat = new KnowledgeBasedChat();
const chat = await kbChat.createDocumentChat(['doc_1', 'doc_2'], 'Product FAQ');
const answer = await kbChat.askDocumentQuestion(
  'What are the key features of the product?',
  chat.chat_id
);
```

## ベストプラクティス

### エラー処理

すべての SDK メソッドに対して常に適切なエラー処理を実装します。

```typescript theme={null}
try {
  const response = await chatSDK.sendMessage(message, options);
  // Handle success
} catch (error) {
  if (error instanceof APIError) {
    // Handle API errors
    console.error(`API Error: ${error.message}`);
  } else {
    // Handle unexpected errors
    console.error('Unexpected error:', error);
  }
}
```

### ストリーミングによる UX の向上

リアルタイムのフィードバックを提供するには、より長い応答に対してストリーミングを使用します。

```typescript theme={null}
// Instead of waiting for complete response
const response = await chatSDK.sendMessage(longQuery);

// Use streaming for better user experience
await chatSDK.sendMessageStream(longQuery, {
  onChunk: (chunk) => updateUI(chunk),
  onComplete: (message) => finalizeUI(message)
});
```

### API 呼び出しを最適化する

* メッセージごとに新しいチャットを作成するのではなく、チャット ID を再利用します。
* チャットリストにページネーションを使用する
* 頻繁にアクセスされるデータのキャッシュを実装する

```typescript theme={null}
class OptimizedChatManager {
  private chatCache = new Map<string, any>();
  private currentChatId?: string;

  async getOrCreateChat(name?: string) {
    if (this.currentChatId) {
      return this.currentChatId;
    }

    const chat = await this.chatSDK.createChat(name);
    this.currentChatId = chat.chat_id;
    return this.currentChatId;
  }

  async getCachedChatHistory(chatId: string) {
    if (this.chatCache.has(chatId)) {
      return this.chatCache.get(chatId);
    }

    const history = await this.chatSDK.getChatHistory(chatId);
    this.chatCache.set(chatId, history);
    return history;
  }
}
```

### 構成管理

設定を安全に保存し、環境変数を使用します。

```typescript theme={null}
// Good: Use environment variables
const chatSDK = new ChatSDK({
  baseUrl: process.env.ODIN_API_BASE_URL,
  projectId: process.env.ODIN_PROJECT_ID,
  apiKey: process.env.ODIN_API_KEY,
  apiSecret: process.env.ODIN_API_SECRET
});

// Bad: Hardcode credentials
const chatSDK = new ChatSDK({
  baseUrl: 'https://api.example.com',
  projectId: 'hardcoded-project-id',
  apiKey: 'hardcoded-api-key',
  apiSecret: 'hardcoded-secret'
});
```

### メモリ管理

リソースをクリーンアップしてメモリ リークを回避します。

```typescript theme={null}
class ChatApplication {
  private activeStreams = new Set<AbortController>();

  async sendStreamingMessage(message: string, options: any) {
    const controller = new AbortController();
    this.activeStreams.add(controller);

    try {
      await this.chatSDK.sendMessageStream(message, {
        ...options,
        signal: controller.signal  // If supported
      });
    } finally {
      this.activeStreams.delete(controller);
    }
  }

  cleanup() {
    // Cancel all active streams
    this.activeStreams.forEach(controller => controller.abort());
    this.activeStreams.clear();
  }
}
```
