Skip to main content

Create Custom Adapters

If you're building your 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.

An adapter is a component that connects nlux an API. It receives messages from nlux and sends them to the API. It also receives responses from the API and sends them to nlux in a format that can be displayed in the chat UI.

Creating a Custom Adapter

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.

To implement a custom streaming adapter for nlux, you need to implement the following interface:

interface ChatAdapter {
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.

Below is the definition of the StreamingAdapterObserver interface:

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.

Example: Streaming Adapter

Let's say we want to create an adapter for a custom API that sends responses in a stream.
This eventual API has a WebSocket endpoint that can be used to send messages and receive responses.

We can create a streaming adapter for this API by implementing the ChatAdapter interface's streamText method as follows:

import {ChatAdapter, StreamingAdapterObserver} from '@nlux/core';

export const myCustomAdapter: ChatAdapter = {
streamText: (message: string, observer: StreamingAdapterObserver): void => {
const socket = new WebSocket('ws://localhost:8080');

// We register listeners for the WebSocket events here
// and call the observer methods accordingly
socket.onmessage = (event) => observer.next(event.data);
socket.onclose = () => observer.complete();
socket.onerror = (error) => observer.error(error);

// This is where we send the user message to the API
socket.send(message);
}
}

Streaming adapters can also be used with APIs that send responses as Server-Sent Events (SSE). All the examples on this website use this approach.

Promise Adapters

Promise adapters can be used when the API sends responses in a single request (e.g. REST APIs).

The advantage of using a promise adapter is that it's easier to implement.

To implement a custom promise adapter for nlux, you need to implement the following interface:

interface ChatAdapter {
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.

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

Example: Promise Adapter

Let's say we want to create a promise adapter for a custom API that sends responses in a single request.

The API has a REST endpoint that we can use to send messages and receive responses.

We can create a promise adapter for this API by implementing the PromiseAdapter interface:

import {ChatAdapter} from '@nlux/core';

export const myCustomAdapter: ChatAdapter = {
fetchText: (message: string, extras: AdapterExtras): Promise<string> => {
return fetch('http://localhost:8080', {
method: 'POST',
body: JSON.stringify({message})
})
.then(response => response.json())
.then(json => json.message);
}
}

Using Custom Adapters

Once you have created a custom adapter, you can use it to create a chat component and render it in the DOM:

The same custom adapter can be used with the React and JavaScript versions of nlux.

Example: Using a Custom Adapter

import {AiChat} from '@nlux/react';

const App = () => {
const adapter = useMemo(() => myCustomAdapter, []);
return <AiChat adapter={adapter} />;
}

You can refer to the Getting Started guides for React and JavaScript for more details on how to use nlux.