Iudex client
Easily build 🛠️ natural language interfaces for ✨ your own ✨ applications 💻
Iudex is an API layer that allows you to quickly build applications that can use LLM reasoning in a way that is more
accurate, secure, and scalable than the toy examples from other projects. Iudex does this by providing an out-of-the-box
LLM orchestration architecture capable of working with millions of functions and documents.
❗ Leverage the power 🦾 of LLMs 🤖 with Iudex ❗
Installation
npm install iudex
yarn add iudex
pnpm add iudex
Getting Started
- Sign up at iudex.ai or shoot a message at support@iudex.ai to get an API key.
- Install either the Node or Python client into your project. For Node, use
npm install iudex
. - Store the API key as an environment variable e.g.
IUDEX_API_KEY
. - Upload your function specs as function JSON schema.
- Send a message to Iudex.
- Get a computed result back.
What can Iudex help you build?
-
Chat bots that can perform actions.
-
Connecting LLMs with any external APIs (Google, Reddit, Twitter, Slack, etc).
-
Automatically extracting data for dashboard generation.
-
Adding rules to data extraction.
How Iudex Works
Iudex works by first indexing your functions. Afterwards, when making a query, Iudex will figure out the best way to accomplish that query
by intelligently sequencing the functions you have connected and with the prebuilt functions we have created. This way, Iudex ensures
that the functions that get called do not suffer from hallucinations and can properly use the results from previously run functions.
Usage
Basic example
import dotenv from 'dotenv';
import { Iudex } from 'iudex';
const iudex = new Iudex({ apiKey: process.env.IUDEX_API_KEY });
await iudex.uploadFunctions([
{
name: 'getCurrentWeather',
description: 'Gets the current weather',
parameters: {
type: 'object',
properties: {
location: {
type: 'string',
description: 'The city and state, e.g. San Francisco, CA',
},
unit: { type: 'string', enum: ['celsius', 'fahrenheit'] },
},
required: ['location'],
},
},
]);
function getCurrentWeather({ location, unit }: { location: string; unit: string }) {
if (location.toLowerCase().includes('tokyo')) {
return { location: 'Tokyo', temperature: '10', unit: 'celsius' };
} else if (location.toLowerCase().includes('san francisco')) {
return { location: 'San Francisco', temperature: '72', unit: 'fahrenheit' };
} else if (location.toLowerCase().includes('paris')) {
return { location: 'Paris', temperature: '22', unit: 'fahrenheit' };
} else {
return { location, temperature: 'unknown' };
}
}
function functionLinker(fnName: string) {
return {
getCurrentWeather,
}[fnName];
};
const message = 'What is the weather in tokyo?';
const iudexReply = await iudex.sendMessage(message);
console.log(`Result for "${message}": ${iudexReply}`);
Example where using Iudex replaces OpenAI
Iudex replaces instances of the OpenAI client where function calling is used.
fnMap
just needs to be defined to link all functions you want the function calling
api to be able to call. For Iudex all parameters except messages
is ignored.
Functions only need to be uploaded once.
import dotenv from 'dotenv';
dotenv.config();
import OpenAI from 'openai';
import { Iudex } from 'iudex';
import _ from 'lodash';
const iudex = new Iudex({ apiKey: process.env.IUDEX_API_KEY });
await iudex.uploadFunctions([
{
name: 'getCurrentWeather',
description: 'Gets the current weather',
parameters: {
type: 'object',
properties: {
location: {
type: 'string',
description: 'The city and state, e.g. San Francisco, CA',
},
unit: { type: 'string', enum: ['celsius', 'fahrenheit'] },
},
required: ['location'],
},
},
]);
function getCurrentWeather({ location, unit }: { location: string; unit: string }) {
if (location.toLowerCase().includes('tokyo')) {
return { location: 'Tokyo', temperature: '10', unit: 'celsius' };
} else if (location.toLowerCase().includes('san francisco')) {
return { location: 'San Francisco', temperature: '72', unit: 'fahrenheit' };
} else if (location.toLowerCase().includes('paris')) {
return { location: 'Paris', temperature: '22', unit: 'fahrenheit' };
} else {
return { location, temperature: 'unknown' };
}
}
const fnMap: Record<string, (...args: any[]) => any> = {
getCurrentWeather,
};
const messages = createMessages();
messages.push({ role: 'user', content: `what is the weather in San Francisco?` });
messages.push(await iudex.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: messages.value,
tools: [],
tool_choice: 'auto',
}).then(res => res.choices[0].message));
let toolMessage = _.last(messages.value);
while (toolMessage && messageHasToolCall(toolMessage)) {
const { function: fnCall, id: tool_call_id } = toolMessage.tool_calls[0];
const { name: fnName, arguments: fnArgs } = fnCall;
const fnReturn = await fnMap[fnName](JSON.parse(fnArgs));
messages.push({
role: 'tool',
tool_call_id,
content: JSON.stringify(fnReturn),
});
messages.push(await iudex.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: messages.value,
}).then(res => res.choices[0].message));
toolMessage = _.last(messages.value);
}
console.log('Result: ', toolMessage);
class Messages {
messagesHist: OpenAI.ChatCompletionMessageParam[] = [];
push = (...items: OpenAI.ChatCompletionMessageParam[]) => {
console.log('new message:', items);
this.messagesHist.push(...items);
};
get value() {
return this.messagesHist;
}
}
function createMessages() {
return new Messages();
}
type OpenAIToolCallMessage = OpenAI.ChatCompletionAssistantMessageParam
& { tool_calls: OpenAI.ChatCompletionMessageToolCall[] };
function messageHasToolCall(
message: OpenAI.ChatCompletionMessageParam,
): message is OpenAIToolCallMessage {
return !!(message as OpenAI.ChatCompletionAssistantMessageParam).tool_calls;
}