GitHub | Documentation | TS/JS API Documentation | Issues | NPM Package
Welcome to JamAI Base – the real-time database that orchestrates Large Language Models (LLMs) for you. Designed to simplify AI integration, JamAI Base offers a Backend as a Service (BaaS) platform with an intuitive, spreadsheet-like interface. Focus on defining your data requirements through natural language prompts, and let us handle the complexities of RAG, LLMOps, conversation histories, and LLM orchestration.
Transform static database tables into dynamic, AI-enhanced entities.
Facilitate real-time interactions between the application frontend and the LLM backend.
Act as repositories for structured data and documents, enhancing the LLM's contextual understanding.
Simplify the creation and management of intelligent chatbot applications.
Efficient management and querying of large-scale multi-modal data.
Focus on defining "what" you want to achieve rather than "how" to achieve it.
npm install jamaibase@latest
The recommended way of using JamAI Base is via Cloud 🚀. Did we mention that you can get free LLM tokens?
Create a project and give it any name that you want.
Get your API credentials:
Install the package:
npm install jamaibase
In your script, import the JamAI class and create an instance:
import JamAI from "jamaibase";
const jamai = new JamAI({
token: "your_pat",
projectId: "your_project_id"
});
Clone the repository:
git clone https://github.com/EmbeddedLLM/JamAIBase.git
cd JamAIBase
Modify the configuration to suit your needs:
services/api/src/owl/configs/models.json specifies all the available models..env specifies which model to run on the infinity service for locally-hosted embedding and reranking models..env also specifies all the third party API keys to be used.For OSS mode, in order for you to see and use other third party models such as OpenAI, you need to provide your own OpenAI API key in .env file (refer to .env.example file).
Launch the Docker containers by running one of these:
# CPU-only
docker compose -f docker/compose.cpu.yml up --quiet-pull -d
# With NVIDIA GPU
docker compose -f docker/compose.nvidia.yml up --quiet-pull -d
.env or shell like so API_PORT=6968 FRONTEND_PORT=4001 docker compose -f docker/compose.cpu.yml up --quiet-pull -dTry the command below in your terminal, or open your browser and go to localhost:4000.
curl localhost:6969/api/v1/models
To use the TypeScript SDK, install jamaibase:
npm install jamaibase
In your script, import the JamAI class and create an instance:
baseURL should point to the exposed port of owl service.import JamAI from "jamaibase";
const jamai = new JamAI({
baseURL: "http://localhost:6969/api"
});
projectId, token (API key), and baseURL can be configured in multiple ways (from highest priority to least priority):
JAMAI_PROJECT_ID, JAMAI_API_KEY and JAMAI_API_BASE respectively.env file as JAMAI_PROJECT_ID, JAMAI_API_KEY and JAMAI_API_BASE respectivelyimport JamAI from "jamaibase";
// Cloud
const client = new JamAI({ projectId: "...", token: "..." });
console.log(client.baseURL);
// OSS
const client = new JamAI({ baseURL: "..." });
console.log(client.baseURL);
Create an API client with baseURL:
import JamAI from "jamaibase";
const jamai = new JamAI({ baseURL: "http://localhost:5173/" });
Create an API client with api key and project id:
import JamAI from "jamaibase";
const jamai = new JamAI({ token: "jamai_pat", projectId: "proj_id" });
Create an API client with custom HTTP client:
import axios from "axios";
import JamAI from "jamaibase";
const username = "user";
const password = "password";
const credentials = Buffer.from(`${username}:${password}`).toString("base64");
const httpClient = axios.create({
headers: {
Authorization: `Basic ${credentials}`,
"Content-Type": "application/json"
}
});
const jamai = new JamAI({
baseURL: "https://api.jamaibase.com",
httpClient: httpClient
});
Create an API client with maxRetry and timeout:
import JamAI from "jamaibase";
const jamai = new JamAI({
baseURL: "https://api.jamaibase.com",
maxRetries: 3,
timeout: 500
});
Configure httpAgent/httpsAgent:
import JamAI from "jamaibase";
const jamai = new JamAI({
baseURL: "https://api.jamaibase.com"
});
jamai.setHttpagentConfig({
maxSockets: 100,
maxFreeSockets: 10,
freeSocketTimeout: 30000 // free socket keepalive for 30 seconds
});
Types can be imported from resources:
import { ChatRequest } from "jamaibase/resources/llm/chat";
let response: ChatRequest;
There are 3 types of Generative Tables:
We will guide you through the steps of leveraging Generative Tables to unleash the full potential of LLMs.
Let's start with creating simple tables. Create a table by defining a schema.
[!NOTE] When it comes to table names, there are some restrictions:
- Must have at least 1 character and up to 100 characters
- Must start and end with an alphabet or number
- Middle characters can contain alphabets, numbers, underscores
_, dashes-, dots.Column names have almost the same restrictions, except that:
- Spaces
are accepted- Dots
.are not accepted- Cannot be called "ID" or "Updated at" (case-insensitive)
// Create an Action Table
const actionTable = await jamai.table.createActionTable({
id: "action-simple",
cols: [
{ id: "image", dtype: "image" }, // Image input
{ id: "length", dtype: "int" }, // Integer input
{ id: "question", dtype: "str" },
{
id: "answer",
dtype: "str",
gen_config: {
model: "openai/gpt-4o-mini", // Leave this out to use a default model
system_prompt: "You are a concise assistant.",
prompt: "Image: ${image}\n\nQuestion: ${question}\n\nAnswer the question in ${length} words.",
temperature: 0.001,
top_p: 0.001,
max_tokens: 100
}
}
]
});
console.log(actionTable);
// Create a Knowledge Table
const knowledgeTable = await jamai.table.createKnowledgeTable({
id: "knowledge-simple",
cols: [],
embedding_model: "ellm/BAAI/bge-m3"
});
console.log(knowledgeTable);
// Create a Chat Table
const chatTable = await jamai.table.createChatTable({
id: "chat-simple",
cols: [
{ id: "User", dtype: "str" },
{
id: "AI",
dtype: "str",
gen_config: {
model: "openai/gpt-4o-mini", // Leave this out to use a default model
system_prompt: "You are a pirate.",
temperature: 0.001,
top_p: 0.001,
max_tokens: 100
}
}
]
});
console.log(chatTable);
Now that we have our tables, we can start adding rows to them and receive the LLM responses.
First let's try adding to Action Table:
const textA = 'Summarize this: "Arrival" is a 2016 science fiction drama film directed by Denis Villeneuve and adapted by Eric Heisserer.';
const textB = 'Summarize this: "Dune: Part Two is a 2024 epic science fiction film directed by Denis Villeneuve."';
const textC = "Identify the subject of the image.";
// --- Action Table --- //
// Streaming
const streamCompletion = await jamai.table.addRowStream({
table_type: "action",
table_id: "action-simple",
data: [{ length: 5, question: textA }]
});
const reader = streamCompletion.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
if (value) {
console.log(value?.choices[0]?.message.content);
}
}
// Non-streaming
const completion = await jamai.table.addRow({
table_type: "action",
table_id: "action-simple",
data: [{ length: 5, question: textB }],
concurrent: false
});
console.log(completion.rows[0].columns["answer"].text);
// Streaming (with image input)
const uploadResponse = await jamai.file.uploadFile({
file_path: "path/to/rabbit.jpeg"
});
const streamWithImage = await jamai.table.addRowStream({
table_type: "action",
table_id: "action-simple",
data: [{ image: uploadResponse.uri, length: 5, question: textC }]
});
const imageReader = streamWithImage.getReader();
while (true) {
const { done, value } = await imageReader.read();
if (done) break;
console.log(value?.choices[0]?.message.content);
}
Next let's try adding to Chat Table:
// --- Chat Table --- //
// Streaming
const chatStream = await jamai.table.addRowStream({
table_type: "chat",
table_id: "chat-simple",
data: [{ User: "Who directed Arrival (2016)?" }]
});
const chatReader = chatStream.getReader();
while (true) {
const { done, value } = await chatReader.read();
if (done) break;
console.log(value?.choices[0]?.message.content);
}
// Non-streaming
const chatCompletion = await jamai.table.addRow({
table_type: "chat",
table_id: "chat-simple",
data: [{ User: "Who directed Dune (2024)?" }],
concurrent: false
});
console.log(chatCompletion.rows[0].columns["AI"].text);
Finally we can add rows to Knowledge Table too:
[!TIP] Uploading files is the main way to add data into a Knowledge Table. Having said so, adding rows works too!
// --- Knowledge Table --- //
// Streaming
const ktStream = await jamai.table.addRowStream({
table_type: "knowledge",
table_id: "knowledge-simple",
data: [{ Title: "Arrival (2016)", Text: textA }]
});
const ktReader = ktStream.getReader();
while (true) {
const { done } = await ktReader.read();
if (done) break;
}
// Non-streaming
const ktCompletion = await jamai.table.addRow({
table_type: "knowledge",
table_id: "knowledge-simple",
data: [{ Title: "Dune (2024)", Text: textB }],
concurrent: false
});
We can retrieve table rows by listing the rows or by fetching a specific row.
// --- List rows -- //
// Action
const actionRows = await jamai.table.listRows({
table_type: "action",
table_id: "action-simple"
});
// Paginated items
for (const row of actionRows.items) {
console.log(row["ID"], row["answer"]["value"]);
}
// Knowledge
const ktRows = await jamai.table.listRows({
table_type: "knowledge",
table_id: "knowledge-simple"
});
for (const row of ktRows.items) {
console.log(row["ID"], row["Title"]["value"]);
console.log(row["Title Embed"]["value"].slice(0, 3)); // Knowledge Table has embeddings
}
// Chat
const chatRows = await jamai.table.listRows({
table_type: "chat",
table_id: "chat-simple"
});
for (const row of chatRows.items) {
console.log(row["ID"], row["User"]["value"], row["AI"]["value"]);
}
// --- Fetch a specific row -- //
const row = await jamai.table.getRow({
table_type: "chat",
table_id: "chat-simple",
row_id: chatRows.items[0]["ID"]
});
console.log(row["ID"], row["AI"]["value"]);
// --- Filter using a search term -- //
const filteredRows = await jamai.table.listRows({
table_type: "action",
table_id: "action-simple",
search_query: "Dune"
});
for (const row of filteredRows.items) {
console.log(row["ID"], row["answer"]["value"]);
}
// --- Only fetch specific columns -- //
const specificCols = await jamai.table.listRows({
table_type: "action",
table_id: "action-simple",
columns: ["length"]
});
for (const row of specificCols.items) {
// "ID" and "Updated at" will always be fetched
console.log(row["ID"], row["length"]["value"]);
}
We can retrieve tables by listing the tables or by fetching a specific table.
// --- List tables -- //
// Action
const actionTables = await jamai.table.listTables({
table_type: "action",
count_rows: true
});
// Paginated items
for (const table of actionTables.items) {
console.log(`${table.id}, ${table.num_rows}`);
}
// Knowledge
const ktTables = await jamai.table.listTables({
table_type: "knowledge"
});
for (const table of ktTables.items) {
console.log(`${table.id}, ${table.num_rows}`);
}
// Chat
const chatTables = await jamai.table.listTables({
table_type: "chat"
});
for (const table of chatTables.items) {
console.log(`${table.id}, ${table.num_rows}`);
}
// --- Fetch a specific table -- //
const specificTable = await jamai.table.getTable({
table_type: "action",
table_id: "action-simple"
});
console.log(`${specificTable.id}, ${specificTable.num_rows}`);
Now that you know how to add rows into tables, let's see how to delete them instead.
// Get all rows
const rows = await jamai.table.listRows({
table_type: "action",
table_id: "action-simple"
});
// Delete all rows
const response = await jamai.table.deleteRows({
table_type: "action",
table_id: "action-simple",
row_ids: rows.items.map(row => row["ID"])
});
console.log(response.ok); // true
// Assert that the table is empty
const emptyRows = await jamai.table.listRows({
table_type: "action",
table_id: "action-simple"
});
console.log(emptyRows.items.length); // 0
Let's see how to delete tables.
[!TIP] Deletion will return "OK" even if the table does not exist.
// Delete tables
let response = await jamai.table.deleteTable({
table_type: "action",
table_id: "action-simple"
});
console.log(response.ok); // true
response = await jamai.table.deleteTable({
table_type: "knowledge",
table_id: "knowledge-simple"
});
console.log(response.ok); // true
response = await jamai.table.deleteTable({
table_type: "chat",
table_id: "chat-simple"
});
console.log(response.ok); // true
We can combine this with the table list method to delete all tables without having to specify their names:
const batchSize = 100;
const tableTypes = ["action", "knowledge", "chat"];
for (const tableType of tableTypes) {
let offset = 0;
let total = 1;
while (offset < total) {
const tables = await jamai.table.listTables({
table_type: tableType,
offset: offset,
limit: batchSize
});
for (const table of tables.items) {
await jamai.table.deleteTable({
table_type: tableType,
table_id: table.id
});
}
total = tables.total;
offset += batchSize;
}
}
We can create copies of tables under the same project. By default, the method copies over both table schema and its data, but we can choose to exclude data when duplicating.
// By default, both schema (like generation config) and data are included
const duplicateTable = await jamai.table.duplicateTable({
table_type: "action",
table_id_src: "action-simple",
table_id_dst: "action-simple-copy",
include_data: true
});
console.log(duplicateTable.id); // "action-simple-copy"
const rows = await jamai.table.listRows({
table_type: "action",
table_id: "action-simple-copy"
});
console.log(rows.total > 0); // true
// We can also duplicate a table without its data
const schemaOnlyTable = await jamai.table.duplicateTable({
table_type: "action",
table_id_src: "action-simple",
table_id_dst: "action-simple-schema-only",
include_data: false
});
console.log(schemaOnlyTable.id); // "action-simple-schema-only"
const emptyRows = await jamai.table.listRows({
table_type: "action",
table_id: "action-simple-schema-only"
});
console.log(emptyRows.total); // 0
Tables can be renamed while preserving all their data and configuration.
// Rename an Action Table
const renamedTable = await jamai.table.renameTable({
table_type: "action",
table_id_src: "action-simple",
table_id_dst: "action-renamed"
});
console.log(renamedTable.id); // "action-renamed"
// Rename a Knowledge Table
const renamedKT = await jamai.table.renameTable({
table_type: "knowledge",
table_id_src: "knowledge-simple",
table_id_dst: "knowledge-renamed"
});
console.log(renamedKT.id); // "knowledge-renamed"
You can add, rename, reorder, and drop columns from tables.
// Add columns to Action Table
const updatedTable = await jamai.table.addActionColumns({
id: "action-simple",
cols: [
{ id: "new_column", dtype: "str" }
]
});
// Rename columns
const renamedCols = await jamai.table.renameColumns({
table_type: "action",
table_id: "action-simple",
column_map: {
question: "renamed_question"
}
});
// Reorder columns
const reorderedTable = await jamai.table.reorderColumns({
table_type: "action",
table_id: "action-simple",
column_names: ["renamed_question", "answer", "new_column"]
});
// Drop columns
const reducedTable = await jamai.table.dropColumns({
table_type: "action",
table_id: "action-simple",
column_names: ["new_column"]
});
// Update generation config
const updatedGenConfig = await jamai.table.updateGenConfig({
table_type: "action",
table_id: "action-simple",
column_map: {
answer: {
model: "openai/gpt-4o-mini",
system_prompt: "Updated system prompt"
}
}
});
Update existing row data in tables.
// Add some rows first
const addedRows = await jamai.table.addRow({
table_type: "action",
table_id: "action-simple",
data: [
{ question: "What is penguin?" },
{ question: "What is help?" }
],
concurrent: true
});
// List rows to get row IDs
const rows = await jamai.table.listRows({
table_type: "action",
table_id: "action-simple",
limit: 2
});
const rowId = rows.items[0]["ID"];
// Update a specific row
const updateResponse = await jamai.table.updateRows({
table_type: "action",
table_id: "action-simple",
data: {
[rowId]: {
question: "How to update rows on jamaibase?",
answer: "References at https://embeddedllm.github.io/jamaibase-ts-docs/"
}
}
});
console.log(updateResponse.ok); // true
Regenerate LLM outputs for existing rows.
// Add rows
await jamai.table.addRow({
table_type: "action",
table_id: "action-simple",
data: [
{ question: "What is penguin?" },
{ question: "What is help?" }
],
concurrent: true
});
// List rows to get row IDs
const rows = await jamai.table.listRows({
table_type: "action",
table_id: "action-simple"
});
const rowIds = rows.items.map(item => item["ID"]);
// Regenerate rows (non-streaming)
const regenResponse = await jamai.table.regenRow({
table_type: "action",
table_id: "action-simple",
row_ids: rowIds,
concurrent: true
});
// Regenerate rows (streaming)
const regenStream = await jamai.table.regenRowStream({
table_type: "action",
table_id: "action-simple",
row_ids: rowIds,
concurrent: true
});
const regenReader = regenStream.getReader();
while (true) {
const { done, value } = await regenReader.read();
if (done) break;
console.log(value);
}
Perform hybrid search combining keyword-based and vector search.
// Add rows with searchable content
await jamai.table.addRow({
table_type: "action",
table_id: "action-simple",
data: [
{ question: "What is penguin?" },
{ question: "What is help?" },
{ question: "What is kong?" }
],
concurrent: true
});
// Perform hybrid search
const searchResults = await jamai.table.hybridSearch({
table_type: "action",
table_id: "action-simple",
query: "kong",
limit: 3,
metric: "dot",
reranking_model: null
});
for (const result of searchResults.items) {
console.log(result);
}
Import and export table data in CSV or TSV format.
// Export table data to CSV
const csvData = await jamai.table.exportTableData({
table_type: "action",
table_id: "action-simple"
});
// csvData is a Uint8Array containing CSV data
// Export table data to TSV
const tsvData = await jamai.table.exportTableData({
table_type: "action",
table_id: "action-simple",
delimiter: "\t"
});
// Import table data from CSV file
const importResponse = await jamai.table.importTableData({
file_path: "/path/to/data.csv",
table_id: "action-simple",
table_type: "action"
});
console.log(importResponse.rows.length);
// Import table data with streaming
const importStream = await jamai.table.importTableDataStream({
file_path: "/path/to/data.csv",
table_id: "action-simple",
table_type: "action"
});
const importReader = importStream.getReader();
while (true) {
const { done, value } = await importReader.read();
if (done) break;
console.log(value);
}
We can upload files to Knowledge Table for Retrieval Augmented Generation (RAG). This allows LLM to generate answers that are grounded in the provided context and data.
import { File } from "formdata-node";
// Create a Knowledge Table
const ktTable = await jamai.table.createKnowledgeTable({
id: "knowledge-rag",
cols: [],
embedding_model: "ellm/BAAI/bge-m3"
});
// Upload a file to the Knowledge Table
const file = new File(["I bought a Mofusand book in 2024.\n\nI went to Italy in 2018."], "text.txt", {
type: "text/plain"
});
const embedResponse = await jamai.table.embedFile({
file: file,
table_id: "knowledge-rag"
});
console.log(embedResponse.ok); // true
// Create an Action Table with RAG
const ragTable = await jamai.table.createActionTable({
id: "action-rag",
cols: [
{ id: "question", dtype: "str" },
{
id: "answer",
dtype: "str",
gen_config: {
model: "openai/gpt-4o-mini",
system_prompt: "You are a concise assistant.",
prompt: "${question}",
rag_params: {
table_id: "knowledge-rag",
k: 2
},
temperature: 0.001,
top_p: 0.001,
max_tokens: 100
}
}
]
});
// Ask a question with streaming
const ragStream = await jamai.table.addRowStream({
table_type: "action",
table_id: "action-rag",
data: [{ question: "Where did I go in 2018?" }]
});
const ragReader = ragStream.getReader();
while (true) {
const { done, value } = await ragReader.read();
if (done) break;
console.log(value?.choices[0]?.message.content);
}
Generate chat completions using various models. Supports streaming and non-streaming modes.
// Streaming
const streamRequest = {
model: "openai/gpt-4o-mini",
messages: [
{ role: "system", content: "You are a concise assistant." },
{ role: "user", content: "What is a llama?" }
],
temperature: 0.001,
top_p: 0.001,
max_tokens: 10
};
const completionStream = await jamai.llm.generateChatCompletionsStream(streamRequest);
const llmReader = completionStream.getReader();
while (true) {
const { done, value } = await llmReader.read();
if (done) break;
console.log(value?.choices[0]?.delta?.content);
}
// Non-streaming
const request = {
model: "openai/gpt-4o-mini",
messages: [
{ role: "system", content: "You are a concise assistant." },
{ role: "user", content: "What is a llama?" }
],
temperature: 0.001,
top_p: 0.001,
max_tokens: 10
};
const completion = await jamai.llm.generateChatCompletions(request);
console.log(completion.choices[0].message.content);
Generate embeddings for given input text.
const texts = ["What is love?", "What is a llama?"];
const embeddings = await jamai.llm.generateEmbeddings({
model: "ellm/BAAI/bge-m3",
type: "document",
input: texts
});
// Inspect one of the embeddings
console.log(embeddings.data[0].embedding.slice(0, 3));
// Print the text and its embedding
for (let i = 0; i < texts.length; i++) {
console.log(texts[i], embeddings.data[i].embedding.slice(0, 3));
}
Retrieve information about available models.
// Get all model info
const models = await jamai.llm.modelInfo();
const model = models.data[0];
console.log(`Model: ${model.id} Context length: ${model.context_length}`);
// Get specific model info
const specificModel = await jamai.llm.modelInfo({
model: "openai/gpt-4o"
});
console.log(specificModel.data[0]);
// Filter based on capability: "chat", "embed", "rerank", "image"
const chatModels = await jamai.llm.modelInfo({
capabilities: ["chat"]
});
for (const model of chatModels.data) {
console.log(model);
}
const embedModels = await jamai.llm.modelInfo({
capabilities: ["embed"]
});
for (const model of embedModels.data) {
console.log(model);
}
const rerankModels = await jamai.llm.modelInfo({
capabilities: ["rerank"]
});
for (const model of rerankModels.data) {
console.log(model);
}
// Get model IDs/names
const modelNames = await jamai.llm.modelNames();
console.log(modelNames);
// Model IDs with the preferred model at the top if available
const preferredModels = await jamai.llm.modelNames({
prefer: "openai/gpt-4o"
});
console.log(preferredModels[0]);
// Filter based on capability
const chatModelNames = await jamai.llm.modelNames({
capabilities: ["chat"]
});
console.log(chatModelNames);
Upload and manage files for use in tables and LLM inputs.
// Upload a file by file path
const uploadResponse = await jamai.file.uploadFile({
file_path: "/path/to/image.png"
});
console.log(uploadResponse.uri);
// Get raw URLs for uploaded files
const rawUrls = await jamai.file.getRawUrls({
uris: [uploadResponse.uri]
});
console.log(rawUrls);
// Get thumbnail URLs for uploaded images
const thumbUrls = await jamai.file.getThumbUrls({
uris: [uploadResponse.uri]
});
console.log(thumbUrls);
// Upload audio file
const audioUpload = await jamai.file.uploadFile({
file_path: "/path/to/audio.mp3"
});
console.log(audioUpload.uri);
Manage organizations, members, and organization-level settings.
// Create organization
const org = await jamai.organizations.createOrganization({
name: "My Organization"
});
console.log(org.id, org.name);
// List organizations
const orgs = await jamai.organizations.listOrganizations({});
for (const org of orgs.items) {
console.log(org.id, org.name);
}
// List organizations with pagination
const paginatedOrgs = await jamai.organizations.listOrganizations({
limit: 10,
offset: 0
});
// Get specific organization
const specificOrg = await jamai.organizations.getOrganization(org.id);
console.log(specificOrg);
// Update organization
const updatedOrg = await jamai.organizations.updateOrganization(org.id, {
name: "Updated Organization Name"
});
console.log(updatedOrg.name);
// Delete organization
const deleteResponse = await jamai.organizations.deleteOrganization(org.id);
console.log(deleteResponse.ok); // true
// List organization members
const members = await jamai.organizations.listMembers(org.id, {});
for (const member of members.items) {
console.log(member.user_id, member.role);
}
// Get specific member
const currentUser = await jamai.users.getUser();
const member = await jamai.organizations.getMember(currentUser.id, org.id);
console.log(member.role);
// Get model catalogue for organization
const catalogue = await jamai.organizations.modelCatalogue(org.id, {});
for (const model of catalogue.items) {
console.log(model.id);
}
// Create organization invite
const invite = await jamai.organizations.createInvite({
user_email: "user@example.com",
organization_id: org.id,
role: "MEMBER",
valid_days: 7
});
console.log(invite.id);
// List organization invites
const invites = await jamai.organizations.listInvites(org.id, {});
for (const invite of invites.items) {
console.log(invite.user_email, invite.role);
}
// Revoke organization invite
const revokeResponse = await jamai.organizations.revokeInvite(invite.id);
console.log(revokeResponse.ok); // true
// Refresh organization quota
const refreshedOrg = await jamai.organizations.refreshQuota(org.id);
console.log(refreshedOrg.quota_reset_at);
Manage projects within organizations.
// Create project
const project = await jamai.projects.createProject({
organization_id: org.id,
name: "My Project"
});
console.log(project.id, project.name);
// List projects
const projects = await jamai.projects.listProjects(org.id, {});
for (const project of projects.items) {
console.log(project.id, project.name);
}
// List projects with pagination
const paginatedProjects = await jamai.projects.listProjects(org.id, {
limit: 10,
offset: 0
});
// Get specific project
const specificProject = await jamai.projects.getProject(project.id);
console.log(specificProject);
// Update project
const updatedProject = await jamai.projects.updateProject(project.id, {
name: "Updated Project Name",
description: "Updated description"
});
console.log(updatedProject.name, updatedProject.description);
// Delete project
const deleteProjectResponse = await jamai.projects.deleteProject(project.id);
console.log(deleteProjectResponse.ok); // true
// List project members
const projectMembers = await jamai.projects.listMembers(project.id, {});
for (const member of projectMembers.items) {
console.log(member.user_id, member.role);
}
// Get specific project member
const projectMember = await jamai.projects.getMember(currentUser.id, project.id);
console.log(projectMember.role);
// Create project invite
const projectInvite = await jamai.projects.createInvite({
user_email: "user@example.com",
project_id: project.id,
role: "MEMBER",
valid_days: 7
});
console.log(projectInvite.id);
// List project invites
const projectInvites = await jamai.projects.listInvites(project.id, {});
for (const invite of projectInvites.items) {
console.log(invite.user_email, invite.role);
}
// Revoke project invite
const revokeProjectInvite = await jamai.projects.revokeInvite(projectInvite.id);
console.log(revokeProjectInvite.ok); // true
// Export project
const exportData = await jamai.projects.exportProject(project.id);
// exportData is a Uint8Array containing the exported project data
console.log(exportData.length);
Manage user accounts and authentication.
// Get current user
const currentUser = await jamai.users.getUser();
console.log(currentUser.id, currentUser.name, currentUser.email);
// List users
const users = await jamai.users.listUsers({});
for (const user of users.items) {
console.log(user.id, user.name);
}
// List users with pagination
const paginatedUsers = await jamai.users.listUsers({
limit: 10,
offset: 0
});
// Update current user
const updatedUser = await jamai.users.updateUser({
name: "Updated Name"
});
console.log(updatedUser.name);
// Create personal access token (PAT)
const pat = await jamai.users.createPat({
name: "My API Token"
});
console.log(pat.id, pat.name);
// List personal access tokens
const pats = await jamai.users.listPats({});
for (const token of pats.items) {
console.log(token.id, token.name);
}
// Update personal access token
const updatedPat = await jamai.users.updatePat(pat.id, {
name: "Updated Token Name"
});
console.log(updatedPat.name);
// Delete personal access token
const deletePat = await jamai.users.deletePat(pat.id);
console.log(deletePat.ok); // true
// Create email verification code
const verificationCode = await jamai.users.createEmailVerificationCode();
console.log(verificationCode.id);
// List email verification codes
const codes = await jamai.users.listEmailVerificationCodes({});
for (const code of codes.items) {
console.log(code.id);
}
// Get specific email verification code
const specificCode = await jamai.users.getEmailVerificationCode(verificationCode.id);
console.log(specificCode);
// Revoke email verification code
const revokeCode = await jamai.users.revokeEmailVerificationCode(verificationCode.id);
console.log(revokeCode.ok); // true
Manage secrets and API keys at the organization level.
// Create secret
const secret = await jamai.secrets.createSecret(
{
name: "MY_API_KEY",
value: "secret-value-here"
},
org.id
);
console.log(secret.name, secret.organization_id);
// Create secret with allowed projects
const secretWithProjects = await jamai.secrets.createSecret(
{
name: "PROJECT_API_KEY",
value: "secret-value",
allowed_projects: [project.id]
},
org.id
);
// List secrets
const secrets = await jamai.secrets.listSecrets(org.id, {});
for (const secret of secrets.items) {
console.log(secret.name, secret.value); // value is masked
}
// List secrets with pagination
const paginatedSecrets = await jamai.secrets.listSecrets(org.id, {
limit: 10,
offset: 0
});
// Get specific secret
const specificSecret = await jamai.secrets.getSecret(org.id, "MY_API_KEY");
console.log(specificSecret.value); // value is masked
// Update secret
const updatedSecret = await jamai.secrets.updateSecret(org.id, "MY_API_KEY", {
value: "new-secret-value"
});
console.log(updatedSecret.value); // value is unmasked on update
// Delete secret
const deleteSecret = await jamai.secrets.deleteSecret(org.id, "MY_API_KEY");
console.log(deleteSecret.ok); // true
[!NOTE] Secret names must:
- Start with a letter or underscore
- Contain only alphanumeric characters and underscores
- Be uppercase (automatically converted)
Manage conversations with AI agents (Chat Tables).
// Create a chat table (agent) first
const agent = await jamai.table.createChatTable({
id: "my-agent",
cols: [
{ id: "User", dtype: "str" },
{
id: "AI",
dtype: "str",
gen_config: {
model: "openai/gpt-4o-mini",
system_prompt: "You are a helpful assistant."
}
}
]
});
// Create a conversation
const conversationStream = await jamai.conversations.createConversation({
agent_id: "my-agent",
title: "My Conversation",
data: {}
});
// Read the stream to get conversation ID
const convReader = conversationStream.getReader();
let conversationId: string | null = null;
while (true) {
const { done, value } = await convReader.read();
if (done) break;
if (value && "conversation_id" in value) {
conversationId = value.conversation_id as string;
break;
}
}
// List conversations
const conversations = await jamai.conversations.listConversations({
agent_id: "my-agent"
});
for (const conv of conversations.items) {
console.log(conv.id, conv.title);
}
// Get specific conversation
const conversation = await jamai.conversations.getConversation(conversationId);
console.log(conversation.title);
// Update conversation
const updatedConv = await jamai.conversations.updateConversation(conversationId, {
title: "Updated Title"
});
console.log(updatedConv.title);
// Continue conversation
const continueStream = await jamai.conversations.continueConversation({
conversation_id: conversationId,
data: { User: "Hello, how are you?" }
});
const continueReader = continueStream.getReader();
while (true) {
const { done, value } = await continueReader.read();
if (done) break;
console.log(value);
}
// Delete conversation
const deleteConv = await jamai.conversations.deleteConversation(conversationId);
console.log(deleteConv.ok); // true
To integrate JamAI into a React application, follow these steps:
npx create-react-app my-app
cd my-app
npm install jamaibase
// App.tsx
import { useEffect, useState } from "react";
import JamAI from "jamaibase";
import { PageListTableMetaResponse } from "jamaibase/resources/gen_tables/tables";
export default function Home() {
const [tableData, setTableData] = useState<PageListTableMetaResponse>();
useEffect(() => {
const fetchData = async () => {
const jamai = new JamAI({
baseURL: process.env.NEXT_PUBLIC_JAMAI_BASEURL!,
token: process.env.JAMAI_API_KEY,
projectId: process.env.JAMAI_PROJECT_ID,
});
try {
const response = await jamai.table.listTables({
table_type: "action",
});
setTableData(response);
} catch (err: any) {
console.error(err.message);
}
};
fetchData();
}, []);
return (
<div>
<h1>List of Tables</h1>
<ul>
{tableData?.items.map((table) => (
<li key={table.id}>
<h2>Table ID: {table.id}</h2>
<h3>Columns:</h3>
<ul>
{table.cols.map((column) => (
<li key={column.id}>
<p>ID: {column.id}</p>
<p>Data Type: {column.dtype}</p>
</li>
))}
</ul>
</li>
))}
</ul>
</div>
);
}
To integrate JamAI into a Next.js application, follow these steps:
npx create-next-app@latest
cd (path/to/your/app)
npm install jamaibase
Generate API Key -> Go to cloud.jamaibase.com/organization/secrets and collect API Key
Collect Project ID -> Go to cloud.jamaibase.com/project and copy the project id.
Create .env.local file at the root of your project and add the keys:
NEXT_PUBLIC_JAMAI_BASEURL=http://api.jamaibase.com/
JAMAI_API_KEY=your_jamai_sk_api_key
JAMAI_PROJECT_ID=your_proj_id
// src/app/api/list-tables/route.ts
import JamAI from "jamaibase";
import {
PageListTableMetaResponse,
TableTypes,
} from "jamaibase/resources/gen_tables/tables";
import { NextRequest, NextResponse } from "next/server";
const jamai = new JamAI({
baseURL: process.env.NEXT_PUBLIC_JAMAI_BASEURL!,
token: process.env.JAMAI_API_KEY,
projectId: process.env.JAMAI_PROJECT_ID,
});
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const tableType = (searchParams.get("type") || "action") as TableTypes;
try {
let data: PageListTableMetaResponse = await jamai.table.listTables({
table_type: tableType,
});
return NextResponse.json(data);
} catch (error: any) {
console.error("Error fetching tables:", error.response);
return NextResponse.json(
{ message: "Internal server error" },
{ status: 500 }
);
}
}
// src/app/page.tsx
"use client";
import { PageListTableMetaResponse } from "jamaibase/resources/gen_tables/tables";
import { ChangeEvent, useEffect, useState } from "react";
export default function Home() {
const [tableData, setTableData] = useState<PageListTableMetaResponse>();
const [tableType, setTableType] = useState("action");
const handleTableTypeChange = (e: ChangeEvent<HTMLSelectElement>) => {
setTableType(e.target.value);
};
useEffect(() => {
const fetchData = async () => {
console.log("fetch data");
const response = await fetch(`/api/list-tables?type=${tableType}`);
if (response.ok) {
const data: PageListTableMetaResponse = await response.json();
setTableData(data);
} else {
console.error("Failed to fetch data:", response.statusText);
}
};
fetchData();
}, [tableType]);
return (
<main className="flex min-h-screen flex-col p-24">
<div className="max-w-sm mx-auto my-10 p-5 bg-white rounded-lg shadow-md">
<label className="block text-sm font-medium text-gray-700 mb-2">
Choose Table Type:
</label>
<select
value={tableType}
onChange={handleTableTypeChange}
className="block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm text-black"
>
<option value="action">Action</option>
<option value="chat">Chat</option>
<option value="knowledge">Knowledge</option>
</select>
</div>
<div className="space-y-6">
<h1 className="text-4xl">List of Tables</h1>
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Table ID
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Columns
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Column Type
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Number of Rows
</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-300 text-black">
{tableData?.items.map((table) => (
<tr key={table.id}>
<td className="px-6 py-4 whitespace-nowrap">
{table.id}
</td>
<td className="px-6 py-4 whitespace-nowrap">
<ul className="space-y-2">
{table.cols.map((column) => (
<li className="" key={column.id}>
<span>{column.id}: </span>
<span>{column.dtype}</span>
</li>
))}
</ul>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<ul className="space-y-2">
{table.cols.map((column) => (
<li className="" key={column.id}>
<span>
{column.gen_config
? "Output"
: "Input"}
</span>
</li>
))}
</ul>
</td>
<td className="px-6 py-4 whitespace-nowrap">
{table.num_rows}
</td>
</tr>
))}
</tbody>
</table>
</div>
</main>
);
}
npm run dev
npm create svelte@latest jamai-example-app
cd jamai-example-app
npm install
npm i jamaibase
Generate API Key -> Go to cloud.jamaibase.com/organization/secrets and collect API Key
Collect Project ID -> Go to cloud.jamaibase.com/project and copy the project id.
Create .env file at the root of your project and add the keys:
PUBLIC_JAMAI_BASEURL=http://api.jamaibase.com/
JAMAI_API_KEY=your_jamai_sk_api_key
JAMAI_PROJECT_ID=your_proj_id
<script>
<script lang="ts">
export let form;
</script>
<main>
<h1>Create Action Table</h1>
{#if form?.success}
<p>Successfully created the table.</p>
{/if}
{#if !form?.success}
<p>Sorry, something went wrong!</p>
{/if}
<form method="POST" action="/create-table">
<label>
Table ID
<input name="table_id" />
</label>
<label>
Column Name
<input name="column_name" />
</label>
<label>
Column Data Type
<select name="column_d_type">
<option value="str">str</option>
<option value="int">int</option>
<option value="float">float</option>
<option value="bool">bool</option>
</select>
</label>
<button type="submit">Create</button>
</form>
</main>
+page.server.ts file in the same path to accept post data from the form.import JamAI from "jamaibase";
import { fail } from "@sveltejs/kit";
import { PUBLIC_JAMAI_URL } from "$env/static/public";
import { JAMAI_API_KEY, JAMAI_PROJECT_ID } from "$env/static/private";
const jamai = new JamAI({
baseURL: PUBLIC_JAMAI_URL,
token: JAMAI_API_KEY,
projectId: JAMAI_PROJECT_ID,
});
export const actions = {
default: async ({ request }) => {
type DTypes = "float" | "int" | "bool" | "str" | undefined;
const data = await request.formData();
const tableId = data.get("table_id")?.toString();
const columnName = data.get("column_name")?.toString();
const columnDType = data.get("column_d_type")?.toString() as DTypes;
console.log("data: ", data);
try {
const response = await jamai.table.createActionTable({
id: tableId!,
cols: [{ id: columnName!, dtype: columnDType! }],
});
return { success: true, data: response };
} catch (error) {
console.error(error);
fail(500, { message: "Something went wrong!" });
}
},
};
npm run dev
npx nuxi init jamai-example-app
cd jamai-example-app
npm install
npm i jamaibase
Generate API Key -> Go to cloud.jamaibase.com/organization/secrets and collect API Key
Collect Project ID -> Go to cloud.jamaibase.com/project and copy the project id.
.env file at the root of your project and add the keys:PUBLIC_JAMAI_BASEURL=http://api.jamaibase.com/
JAMAI_API_KEY=your_jamai_sk_api_key
JAMAI_PROJECT_ID=your_proj_id
nuxt.config.ts file, add runtimeConfig to use the environment variables:runtimeConfig: {
JAMAI_API_KEY: process.env.JAMAI_API_KEY,
public: {
JAMAI_BASEURL: process.env.JAMAI_BASEURL,
JAMAI_PROJECT_ID: process.env.JAMAI_PROJECT_ID,
},
},
<template>
<main>
<div class="container">
<label>Choose Table Type:</label>
<select v-model="tableType" @change="fetchTables">
<option value="action">Action</option>
<option value="chat">Chat</option>
<option value="knowledge">Knowledge</option>
</select>
</div>
<div class="container">
<h1>List of Tables</h1>
<table>
<thead>
<tr>
<th>Table ID</th>
<th>Columns</th>
<th>Column Type</th>
<th>Number of Rows</th>
</tr>
</thead>
<tbody>
<tr v-for="table in tableData.items" :key="table.id">
<td>{{ table.id }}</td>
<td>
<ul>
<li v-for="column in table.cols" :key="column.id">{{ column.id }}: {{ column.dtype }}</li>
</ul>
</td>
<td>
<ul>
<li v-for="column in table.cols" :key="column.id">{{ column.gen_config ? "Output" : "Input" }}</li>
</ul>
</td>
<td>{{ table.num_rows }}</td>
</tr>
</tbody>
</table>
</div>
</main>
</template>
<script setup>
import { ref, onMounted } from "vue";
const tableType = ref("action");
const tableData = ref({ items: [] });
async function fetchTables() {
const response = await $fetch(`/api/list-tables?type=${tableType.value}`);
if (response.success) {
tableData.value = response.data;
} else {
console.error("Failed to fetch data");
}
}
onMounted(() => {
fetchTables();
});
</script>
server/api/list-tables.js and add the following code:import JamAI from "jamaibase";
const {
JAMAI_API_KEY,
public: { JAMAI_BASEURL, JAMAI_PROJECT_ID }
} = useRuntimeConfig();
const jamai = new JamAI({
baseURL: JAMAI_BASEURL,
token: JAMAI_API_KEY,
projectId: JAMAI_PROJECT_ID
});
export default defineEventHandler(async (event) => {
const { type = "action" } = getQuery(event);
try {
const data = await jamai.table.listTables({ table_type: type });
return { success: true, data: data };
} catch (error) {
console.error("Error fetching tables:", error);
return { success: false, data: "Something went wrong" };
}
});
npm run dev
| Parameter | Type | Description | Default Value | Required / Optional |
|---|---|---|---|---|
baseURL |
string |
Base URL for the API requests. | https://api.jamaibase.com |
optional |
maxRetries |
number |
Maximum number of retries for failed requests. | 0 | Optional |
httpClient |
AxiosInstance |
Axios instance for making HTTP requests. | AxiosInstance |
Optional |
timeout |
number | undefined |
Timeout for the requests. | undefined |
Optional |
token |
string | undefined |
API token (Personal Access Token). | undefined |
Required if accessing cloud |
projectId |
string | undefined |
Project ID. | undefined |
Optional if accessing cloud |
dangerouslyAllowBrowser |
boolean |
Allowing the insecure usage of JamAI API Key on client side. | false |
Optional if accessing cloud |