---
sidebar_label: 'Custom Adapters'
---

import {PlatformSelector} from '@site/src/components/PlatformSelector/PlatformSelector';
import {PlatformSection} from '@site/src/components/PlatformSection/PlatformSection';

import ReactJs from './_004-custom-adapters/#react.mdx';
import Javascript from './_004-custom-adapters/#js.mdx';

import CustomStreamingAdapterJavascript from './_004-custom-adapters/#js/customStreamingAdapter.mdx';
import CustomStreamingAdapterReactJs from './_004-custom-adapters/#react/customStreamingAdapter.mdx';

import CustomPromiseAdapterJavascript from './_004-custom-adapters/#js/customPromiseAdapter.mdx';
import CustomPromiseAdapterReactJs from './_004-custom-adapters/#react/customPromiseAdapter.mdx';

# Custom Adapters

If you're building your own APIs and you would like to use `NLUX` as the UI for your own AI chatbot,
you can do so by creating a custom adapter.

<PlatformSelector reactJs={ReactJs} javascript={Javascript}/>

There are 2 types of custom adapters that you can create:

* Streaming Adapters
* Promise Adapters

## Streaming Adapters

Streaming adapters are used when the API sends responses in a stream (e.g. WebSockets, or Server-Sent Events).

The advantage of using a streaming adapter is that **the chat UI will be updated in real-time while the LLM is still
generating text**. This is particularly useful if the API takes a long time to process a request and sends responses
in a stream. Most major LLM APIs (e.g. OpenAI, Anthropic) support streaming responses.

In order to implement a custom streaming adapter for `NLUX`, you need to implement the following interface:

```typescript
interface Adapter {
    streamText: (
        message: string,
        observer: StreamingAdapterObserver,
        extras: AdapterExtras,
    ) => void;
}
```

The `streamText` method takes 2 parameters:

* `message` - The prompt message typed by the user, to be sent to the API.
* `observer` - An observer that will receive the responses from the API and pass them to `NLUX`.
* `extras` - An object containing [additional information](#adapter-extras) that the adapter might need.

Below is the definition of the `StreamingAdapterObserver` interface:

```typescript
interface StreamingAdapterObserver {
    next: (partialResponse: string) => void;
    error: (error: Error) => void;
    complete: () => void;
}
```

You can call the `next` method of the observer as responses are received from the API.
The `complete` method should be called when the API has finished sending responses, and
The `error` method should be called if an error occurs.

:::tip
You can check the [Create Custom Adapters](/learn/adapters/custom-adapters/create-custom-adapter) guide for an example of how to
implement a custom streaming adapter.
:::

## Promise Adapters

Promise adapters can be used when the API sends responses in a single request (e.g. REST APIs).<br />
The advantage of using a promise adapter is that **it's easier to implement**.

In order to implement a custom promise adapter for `NLUX`, you need to implement the following interface:

```typescript
interface Adapter {
    fetchText(message: string, extras: AdapterExtras): Promise<string>;
}
```

The `fetchText` method takes 1 parameter:

* `message` - The prompt message typed by the user, to be sent to the API.
* `extras` - An object containing [additional information](#adapter-extras) that the adapter might need.

The `fetchText` method should return a promise that resolves to the response from the API.

:::tip
You can check the [Create Custom Adapters](/learn/adapters/custom-adapters/create-custom-adapter) guide for an example of how to
implement a custom promise adapter.
:::

## Adapter Extras

The `AdapterExtras` object passed as last parameter to the `fetchText` and `streamText` methods contains
information that the adapter might need. It has the following properties. It has the following properties:

```typescript
interface AdapterExtras {
    // The props that were passed to the AiChat component
    aiChatProps: AiChatProps;

    // The conversation history
    // Available when `conversationOptions.historyPayloadSize`
    // is set to a value greater than 0 or to `'max'`
    conversationHistory?: Readonly<ConversationItem[]>;
}
```