Skip to content

Commit

Permalink
Added nlbridge adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
salmenus committed Feb 18, 2024
1 parent 202871f commit 21a0f29
Show file tree
Hide file tree
Showing 59 changed files with 938 additions and 86 deletions.
31 changes: 20 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# [`nlux`](https://nlux.ai) 🌲✨💬
# [nlux](https://nlux.ai) 🌲✨💬

![Free And Open Source](https://img.shields.io/badge/Free%20%26%20Open%20Source-1ccb61)
[![npm version](https://img.shields.io/badge/NPM-@nlux/react-1ccb61)](https://www.npmjs.com/package/@nlux/react)
[![Docs nlux.ai](https://img.shields.io/badge/Docs_Website-nlux.dev-fa896b)](https://nlux.dev)

## The JS / React Library For Building Conversational AI Interfaces ✨💬
## The React + JS Library For Building Conversational AI Interfaces ✨💬

[![nlux UI For Any LLM](https://nlux.ai/images/github/nlux-ui-for-llms-banner.gif)](https://nlux.dev)

`nlux` (for Natural Language User Experience) is an open-source Javascript library that makes it super simple to
`nlux` (_for Natural Language User Experience_) is an open-source Javascript library that makes it super simple to
integrate powerful large language models (LLMs) like ChatGPT into your web app or website. With just a few lines
of code, you can add conversational AI capabilities and interact with your favourite LLM.

Expand All @@ -20,8 +20,10 @@ of code, you can add conversational AI capabilities and interact with your favou
* A flexible interface to **Create Your Own Adapter** for any LLM or API, with support for stream or fetch modes.
* **Bot and User Personas** ― Customize the bot and user personas with names, images, and descriptions.
* **Streaming LLM Output** ― Stream the chat response to the UI as it's being generated.
* **High Customizability** - Tune almost every UI aspect through theming, layout options, and more.
* **Zero Dependencies** ― Lightweight codebase ― **Core** with zero dependencies and no external UI libraries.
* **High Customizability** ― Tune almost every UI aspect through theming, layout options, and more.
* **`nlbridge` Integration** ― Seamless integration with [nlbridge](https://www.npmjs.com/package/@nlbridge/express),
the LLM middleware library by the same team.
* **Zero Dependencies** ― Lightweight codebase ― Core with zero dependencies and no external UI libraries.

[![200+ Unit Tests](https://github.com/nluxai/nlux/actions/workflows/run-all-tests.yml/badge.svg)](https://github.com/nluxai/nlux/actions/workflows/run-all-tests.yml)

Expand All @@ -35,7 +37,10 @@ It is a monorepo that contains the following NPM packages:
* [`@nlux/react`](https://www.npmjs.com/package/@nlux/react) ― React JS components for `nlux`.
* [`@nlux/langchain-react`](https://www.npmjs.com/package/@nlux/langchain-react) ― React hooks and adapter for APIs
created using LangChain's LangServe library.
* [`@nlux/openai-react`](https://www.npmjs.com/package/@nlux/openai-react) ― React hooks for the OpenAI API.
* [`@nlux/nlbridge-react`](https://www.npmjs.com/package/@nlux/nlbridge-react) ― Integration with
`nlbridge`, the LLM middleware library by the same team.
* [`@nlux/openai-react`](https://www.npmjs.com/package/@nlux/openai-react) ― React hooks for the OpenAI API, for testing
and development.
* [`@nlux/hf-react`](https://www.npmjs.com/package/@nlux/hf-react) ― React hooks and pre-processors for the Hugging Face
Inference API

Expand All @@ -44,7 +49,10 @@ It is a monorepo that contains the following NPM packages:
* [`@nlux/core`](https://www.npmjs.com/package/@nlux/core) ― The core Vanilla JS library to use with any web framework.
* [`@nlux/langchain`](https://www.npmjs.com/package/@nlux/langchain) ― Adapter for APIs created using LangChain's
LangServe library.
* [`@nlux/openai`](https://www.npmjs.com/package/@nlux/openai) ― Adapter for the OpenAI API.
* [`@nlux/nlbridge`](https://www.npmjs.com/package/@nlux/nlbridge) ― Integration with
`nlbridge`, the LLM middleware library by the same team.
* [`@nlux/openai`](https://www.npmjs.com/package/@nlux/openai) ― Adapter for the OpenAI API, for testing and
development.
* [`@nlux/hf`](https://www.npmjs.com/package/@nlux/hf) ― Adapter and pre-processors for the Hugging Face Inference API.

**Themes & Extensions:**
Expand All @@ -59,7 +67,8 @@ Please visit each package's NPM page for information on how to use it.

## Docs & Examples 🤩

* For developer documentation, examples, and API reference ― please visit: **[nlux.dev](https://nlux.dev/)**
* For developer documentation, examples, and API reference ― please visit:
[nlux.dev](https://nlux.dev/)

## Design Principles ⚜️

Expand Down Expand Up @@ -91,11 +100,11 @@ cross platforms, with a focus on performance and usability.

* **Star The Repo** 🌟 ― If you like `nlux`, please star the repo to show your support.
Your support is what keeps this open-source project going 🧡
* **[GitHub Discussions](https://github.com/nluxai/nlux/discussions)** ― Ask questions, report issues, and share your
* [GitHub Discussions](https://github.com/nluxai/nlux/discussions) ― Ask questions, report issues, and share your
ideas with the community.
* **[Discord Community](https://discord.gg/SRwDmZghNB)** ― Join our Discord server to chat with the community and get
* [Discord Community](https://discord.gg/SRwDmZghNB) ― Join our Discord server to chat with the community and get
support.
* **[nlux.dev](https://nlux.dev/)** Developer Website ― Examples, learning resources, and API reference.
* [nlux.dev](https://nlux.dev/) Developer Website ― Examples, learning resources, and API reference.

## License 📃

Expand Down
3 changes: 0 additions & 3 deletions packages/js/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ export type {

export type {
StandardAdapter,
StandardAdapterEvent,
StandardAdapterStatus,
StandardAdapterEventData,
} from './types/standardAdapter';

export type {
Expand Down
16 changes: 0 additions & 16 deletions packages/js/core/src/types/standardAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,6 @@
import {Adapter, AdapterExtras, DataTransferMode, StreamingAdapterObserver} from './adapter';
import {StandardAdapterConfig, StandardAdapterInfo} from './standardAdapterConfig';

export type StandardAdapterStatus = 'disconnected'
| 'connecting'
| 'connected'
| 'disconnecting'
| 'idle'
| 'error';

export type StandardAdapterEvent = 'state-change'
| 'message-received'
| 'message-sent'
| 'chunk-received';

export type StandardAdapterEventData = string | StandardAdapterStatus;

export interface StandardAdapter<InboundPayload, OutboundPayload> extends Adapter {
get config(): StandardAdapterConfig<InboundPayload, OutboundPayload>;
get dataTransferMode(): DataTransferMode;
Expand All @@ -23,7 +9,6 @@ export interface StandardAdapter<InboundPayload, OutboundPayload> extends Adapte
fetchText(message: string, extras: AdapterExtras): Promise<string>;
get id(): string;
get info(): StandardAdapterInfo;
get status(): StandardAdapterStatus;
streamText(message: string, observer: StreamingAdapterObserver, extras: AdapterExtras): void;
}

Expand All @@ -34,6 +19,5 @@ export const isStandardAdapter = (adapter: Adapter): boolean => {
&& 'encode' in adapter
&& 'id' in adapter
&& 'info' in adapter
&& 'status' in adapter
&& ('fetchText' in adapter || 'streamText' in adapter);
};
5 changes: 0 additions & 5 deletions packages/js/hf/src/hf/adapter/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
StandardAdapter,
StandardAdapterConfig,
StandardAdapterInfo,
StandardAdapterStatus,
StreamingAdapterObserver,
uid,
warn,
Expand Down Expand Up @@ -70,10 +69,6 @@ export class HfAdapterImpl implements StandardAdapter<any, any> {
};
}

get status(): StandardAdapterStatus {
return 'idle';
}

async decode(payload: any): Promise<string> {
const output = (() => {
if (typeof payload === 'string') {
Expand Down
5 changes: 0 additions & 5 deletions packages/js/langchain/src/langserve/adapter/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
StandardAdapter,
StandardAdapterConfig,
StandardAdapterInfo,
StandardAdapterStatus,
StreamingAdapterObserver,
uid,
warn,
Expand Down Expand Up @@ -100,10 +99,6 @@ export abstract class LangServeAbstractAdapter implements StandardAdapter<string
return this.theRunnableNameToUse;
}

get status(): StandardAdapterStatus {
return 'idle';
}

get useInputSchema(): boolean {
return this.theUseInputSchemaOptionToUse;
}
Expand Down
30 changes: 30 additions & 0 deletions packages/js/nlbridge/package.template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "@nlux-dev/nlbridge",
"version": "0.0.0-latest",
"license": "MPL-2.0",
"scripts": {
"build": "rollup --config rollup.config.ts --configPlugin 'typescript={moduleResolution: \"bundler\"}' --resolveJsonModule",
"watch": "rollup --config rollup.config.ts --configPlugin 'typescript={moduleResolution: \"bundler\"}' --resolveJsonModule --watch"
},
"dependencies": {
"@nlux/core": "{versions.nlux}"
},
"peerDependencies": {
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-replace": "^5.0.5",
"@rollup/plugin-strip": "^3.0.4",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.6",
"rollup": "^4.9.6",
"rollup-plugin-dts": "^6.1.0",
"rollup-plugin-esbuild": "^6.1.1",
"tslib": "^2.6.2"
},
"main": "index.js",
"types": "nlbridge.d.ts",
"module": "esm/nlbridge.js",
"browser": "umd/nlbridge.js"
}
46 changes: 46 additions & 0 deletions packages/js/nlbridge/rollup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import commonjs from '@rollup/plugin-commonjs';
import {nodeResolve} from '@rollup/plugin-node-resolve';
import replace from '@rollup/plugin-replace';
import strip from '@rollup/plugin-strip';
import terser from '@rollup/plugin-terser';
import {RollupOptions} from 'rollup';
import esbuild from 'rollup-plugin-esbuild';
// @ts-ignore
import {generateDts} from '../../../pipeline/utils/rollup/generateDts';
import {generateOutputConfig} from '../../../pipeline/utils/rollup/generateOutputConfig';

const isProduction = process.env.NODE_ENV === 'production';
const packageName = '@nlux/nlbridge';
const outputFile = 'nlbridge';

const packageConfig: () => Promise<RollupOptions[]> = async () => ([
{
input: './src/index.ts',
logLevel: 'silent',
treeshake: 'smallest',
strictDeprecations: true,
plugins: [
commonjs(),
esbuild(),
isProduction && strip({
include: '**/*.(mjs|js|ts)',
functions: ['debug', 'console.log', 'console.info'],
}),
!isProduction && nodeResolve(),
replace({
values: {
'process.env.NLUX_DEBUG_ENABLED': JSON.stringify(isProduction ? 'false' : 'true'),
},
preventAssignment: true,
}),
isProduction && terser(),
],
external: [
'@nlux/core',
],
output: generateOutputConfig(packageName, outputFile, isProduction),
},
generateDts(outputFile, isProduction),
]);

export default packageConfig;
14 changes: 14 additions & 0 deletions packages/js/nlbridge/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export type {
Adapter,
StandardAdapter,
StreamingAdapterObserver,
DataTransferMode,
} from '@nlux/core';

export {debug} from '@nlux/core';

export type {NlBridgeAdapterOptions} from './nlbridge/types/adapterOptions';

export type {NlBridgeAdapterBuilder} from './nlbridge/builder/builder';

export {createAdapter} from './nlbridge/builder/createAdapter';
76 changes: 76 additions & 0 deletions packages/js/nlbridge/src/nlbridge/adapter/adapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {
AdapterExtras,
DataTransferMode,
StandardAdapter,
StandardAdapterConfig,
StandardAdapterInfo,
StreamingAdapterObserver,
uid,
} from '@nlux/core';
import {NlBridgeAdapterOptions} from '../types/adapterOptions';

export abstract class NlBridgeAbstractAdapter implements StandardAdapter<string, string | undefined> {
static defaultDataTransferMode: DataTransferMode = 'stream';

private readonly __instanceId: string;
private readonly __options: NlBridgeAdapterOptions;

private readonly theDataTransferModeToUse: DataTransferMode;
private readonly theEndpointUrlToUse: string;

constructor(options: NlBridgeAdapterOptions) {
this.__instanceId = `${this.info.id}-${uid()}`;
this.__options = {...options};

this.theDataTransferModeToUse = options.dataTransferMode ?? NlBridgeAbstractAdapter.defaultDataTransferMode;
this.theEndpointUrlToUse = options.url;
}

get config(): StandardAdapterConfig<any, any> {
return {
encodeMessage: (message: string) => {
return Promise.resolve(message);
},
decodeMessage: (payload: any) => {
return Promise.resolve(payload);
},
};
}

get dataTransferMode(): DataTransferMode {
return this.theDataTransferModeToUse;
}

get endpointUrl(): string {
return this.theEndpointUrlToUse;
}

get id(): string {
return this.__instanceId;
}

get info(): StandardAdapterInfo {
return {
id: 'nlbridge-adapter',
capabilities: {
textChat: true,
audio: false,
fileUpload: false,
},
inputFormats: ['text'],
outputFormats: ['text', 'markdown'],
};
}

async decode(payload: string): Promise<string | undefined> {
return undefined;
}

async encode(message: string): Promise<string | undefined> {
return undefined;
}

abstract fetchText(message: string, extras: AdapterExtras): Promise<string>;

abstract streamText(message: string, observer: StreamingAdapterObserver, extras: AdapterExtras): void;
}
51 changes: 51 additions & 0 deletions packages/js/nlbridge/src/nlbridge/adapter/fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {AdapterExtras, NluxError, NluxUsageError, StreamingAdapterObserver} from '@nlux/core';
import {NlBridgeAbstractAdapter} from './adapter';

export class NlBridgeFetchAdapter extends NlBridgeAbstractAdapter {
constructor(options: any) {
super(options);
}

async fetchText(message: string, extras: AdapterExtras): Promise<string> {
const response = await fetch(this.endpointUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
action: 'chat',
payload: {
message,
},
}),
});

if (!response.ok) {
throw new NluxError({
source: this.constructor.name,
message: `NlBridge adapter returned status code: ${response.status}`,
});
}

const body = await response.json();
if (
typeof body === 'object' && body !== null && body.success === true &&
typeof body.result === 'object' && body.result !== null &&
typeof body.result.response === 'string'
) {
return body.result.response;
} else {
throw new NluxError({
source: this.constructor.name,
message: 'Invalid response from NlBridge: String expected.',
});
}
}

streamText(message: string, observer: StreamingAdapterObserver, extras: AdapterExtras): void {
throw new NluxUsageError({
source: this.constructor.name,
message: 'Cannot stream text from the fetch adapter!',
});
}
}
Loading

0 comments on commit 21a0f29

Please sign in to comment.