Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement selector to configure LlamaCloud parameters #200

Merged
merged 38 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
f3f8fa4
feat: call APIs to get llamacloud projects and pipelines
thucpn Aug 1, 2024
39282dc
feat: update chat config API to response llamacloud config
thucpn Aug 1, 2024
eac3d74
feat: add shadcn select component
thucpn Aug 1, 2024
d39ffda
feat: render llamacloud pipeline options
thucpn Aug 1, 2024
9e0a303
feat: update llamacloud service to manage config
thucpn Aug 1, 2024
8c99b76
feat: update chat config API to get and update llamacloud config
thucpn Aug 1, 2024
27a2a05
feat: update llamacloud datasource to use config json
thucpn Aug 1, 2024
a759447
feat: able to change config from UI
thucpn Aug 1, 2024
b5581d5
feat: add should fetch options to reduce requests
thucpn Aug 1, 2024
6f694b6
fix: update style of selector
thucpn Aug 1, 2024
d11d71e
Create quick-walls-switch.md
thucpn Aug 1, 2024
90c3ca1
feat: update UI to send pipeline config via request body
thucpn Aug 2, 2024
5bc6937
refactor: don't use config from json file
thucpn Aug 2, 2024
37cef3e
feat: pass configs from chat request to datasource
thucpn Aug 2, 2024
c1deb40
style: enhance UI llamacloud selector
thucpn Aug 2, 2024
3dbfc8a
refactor: remove this and use class name
thucpn Aug 2, 2024
1534343
docs: update change log
thucpn Aug 2, 2024
6a1730f
refactor: use type instead of interface
thucpn Aug 2, 2024
38b6434
refactor: params instead of configs
thucpn Aug 2, 2024
38a1065
fix: add params to agent and simple vector store
thucpn Aug 2, 2024
1014f34
docs: message
thucpn Aug 2, 2024
9702c38
refactor: move logic to useLlamaCloud and split apis
thucpn Aug 2, 2024
f698b9b
update chat input
thucpn Aug 2, 2024
d0454a8
feat: add llamacloud config api for express
thucpn Aug 2, 2024
fb93572
fix: update express chat stream controller
thucpn Aug 2, 2024
a282665
feat: support llamacloud config in Python
thucpn Aug 5, 2024
8143c46
refactor: add optional params to get datasouce function
thucpn Aug 5, 2024
73ad38d
feat: return default option from env
thucpn Aug 5, 2024
042fee2
refactor: clean up
thucpn Aug 5, 2024
a3f921d
fix: using llamacloud from env
thucpn Aug 5, 2024
8fe83cf
refactor: remove usellamacloud
thucpn Aug 5, 2024
fc0192f
refactor: make chat request type any
thucpn Aug 5, 2024
9c0b143
refactor: do not pass request data
thucpn Aug 5, 2024
0d8160f
fix: generation of env variables
marcusschiesser Aug 5, 2024
2960079
fix: check if LlamaCloud config is valid
marcusschiesser Aug 5, 2024
df2b9ab
fix: compile error
marcusschiesser Aug 5, 2024
bf66fc3
fix: e2e test
marcusschiesser Aug 5, 2024
52850a4
fix: e2e test
marcusschiesser Aug 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/quick-walls-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-llama": patch
---

Let user change indexes in LlamaCloud projects
17 changes: 17 additions & 0 deletions helpers/env-variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,17 @@ const getVectorDBEnvs = (
description:
"The organization ID for the LlamaCloud project (uses default organization if not specified - Python only)",
},
...(framework === "nextjs"
? // activate index selector per default (not needed for non-NextJS backends as it's handled by createFrontendEnvFile)
[
{
name: "NEXT_PUBLIC_USE_LLAMACLOUD",
description:
"Let's the user change indexes in LlamaCloud projects",
value: "true",
},
]
: []),
];
case "chroma":
const envs = [
Expand Down Expand Up @@ -493,6 +504,7 @@ export const createFrontendEnvFile = async (
root: string,
opts: {
customApiPath?: string;
vectorDb?: TemplateVectorDB;
},
) => {
const defaultFrontendEnvs = [
Expand All @@ -503,6 +515,11 @@ export const createFrontendEnvFile = async (
? opts.customApiPath
: "http://localhost:8000/api/chat",
},
{
name: "NEXT_PUBLIC_USE_LLAMACLOUD",
description: "Let's the user change indexes in LlamaCloud projects",
value: opts.vectorDb === "llamacloud" ? "true" : "false",
},
];
const content = renderEnvVar(defaultFrontendEnvs);
await fs.writeFile(path.join(root, ".env"), content);
Expand Down
1 change: 1 addition & 0 deletions helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ export const installTemplate = async (
// this is a frontend for a full-stack app, create .env file with model information
await createFrontendEnvFile(props.root, {
customApiPath: props.customApiPath,
vectorDb: props.vectorDb,
});
}
};
Expand Down
2 changes: 1 addition & 1 deletion templates/components/engines/python/agent/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from app.engine.index import get_index


def get_chat_engine(filters=None):
def get_chat_engine(filters=None, params=None):
system_prompt = os.getenv("SYSTEM_PROMPT")
top_k = os.getenv("TOP_K", "3")
tools = []
Expand Down
4 changes: 2 additions & 2 deletions templates/components/engines/python/chat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
from fastapi import HTTPException


def get_chat_engine(filters=None):
def get_chat_engine(filters=None, params=None):
system_prompt = os.getenv("SYSTEM_PROMPT")
top_k = os.getenv("TOP_K", 3)

index = get_index()
index = get_index(params)
if index is None:
raise HTTPException(
status_code=500,
Expand Down
4 changes: 2 additions & 2 deletions templates/components/engines/typescript/agent/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import path from "node:path";
import { getDataSource } from "./index";
import { createTools } from "./tools";

export async function createChatEngine(documentIds?: string[]) {
export async function createChatEngine(documentIds?: string[], params?: any) {
thucpn marked this conversation as resolved.
Show resolved Hide resolved
const tools: BaseToolWithCall[] = [];

// Add a query engine tool if we have a data source
// Delete this code if you don't have a data source
const index = await getDataSource();
const index = await getDataSource(params);
if (index) {
tools.push(
new QueryEngineTool({
Expand Down
4 changes: 2 additions & 2 deletions templates/components/engines/typescript/chat/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {
} from "llamaindex";
import { getDataSource } from "./index";

export async function createChatEngine(documentIds?: string[]) {
const index = await getDataSource();
export async function createChatEngine(documentIds?: string[], params?: any) {
const index = await getDataSource(params);
if (!index) {
throw new Error(
`StorageContext is empty - call 'npm run generate' to generate the storage first`,
Expand Down
95 changes: 77 additions & 18 deletions templates/components/llamaindex/typescript/streaming/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,51 @@ const LLAMA_CLOUD_OUTPUT_DIR = "output/llamacloud";
const LLAMA_CLOUD_BASE_URL = "https://cloud.llamaindex.ai/api/v1";
const FILE_DELIMITER = "$"; // delimiter between pipelineId and filename

interface LlamaCloudFile {
type LlamaCloudFile = {
name: string;
file_id: string;
project_id: string;
}
};

type LLamaCloudProject = {
id: string;
organization_id: string;
name: string;
is_default: boolean;
};

type LLamaCloudPipeline = {
id: string;
name: string;
project_id: string;
};

export class LLamaCloudFileService {
private static readonly headers = {
Accept: "application/json",
Authorization: `Bearer ${process.env.LLAMA_CLOUD_API_KEY}`,
};

public static async getAllProjectsWithPipelines() {
try {
const projects = await LLamaCloudFileService.getAllProjects();
const pipelines = await LLamaCloudFileService.getAllPipelines();
return projects.map((project) => ({
...project,
pipelines: pipelines.filter((p) => p.project_id === project.id),
}));
} catch (error) {
console.error("Error listing projects and pipelines:", error);
return [];
}
}

public static async downloadFiles(nodes: NodeWithScore<Metadata>[]) {
const files = this.nodesToDownloadFiles(nodes);
const files = LLamaCloudFileService.nodesToDownloadFiles(nodes);
if (!files.length) return;
console.log("Downloading files from LlamaCloud...");
for (const file of files) {
await this.downloadFile(file.pipelineId, file.fileName);
await LLamaCloudFileService.downloadFile(file.pipelineId, file.fileName);
}
}

Expand Down Expand Up @@ -59,13 +91,19 @@ export class LLamaCloudFileService {

private static async downloadFile(pipelineId: string, fileName: string) {
try {
const downloadedName = this.toDownloadedName(pipelineId, fileName);
const downloadedName = LLamaCloudFileService.toDownloadedName(
pipelineId,
fileName,
);
const downloadedPath = path.join(LLAMA_CLOUD_OUTPUT_DIR, downloadedName);

// Check if file already exists
if (fs.existsSync(downloadedPath)) return;

const urlToDownload = await this.getFileUrlByName(pipelineId, fileName);
const urlToDownload = await LLamaCloudFileService.getFileUrlByName(
pipelineId,
fileName,
);
if (!urlToDownload) throw new Error("File not found in LlamaCloud");

const file = fs.createWriteStream(downloadedPath);
Expand Down Expand Up @@ -93,22 +131,24 @@ export class LLamaCloudFileService {
pipelineId: string,
name: string,
): Promise<string | null> {
const files = await this.getAllFiles(pipelineId);
const files = await LLamaCloudFileService.getAllFiles(pipelineId);
const file = files.find((file) => file.name === name);
if (!file) return null;
return await this.getFileUrlById(file.project_id, file.file_id);
return await LLamaCloudFileService.getFileUrlById(
file.project_id,
file.file_id,
);
}

private static async getFileUrlById(
projectId: string,
fileId: string,
): Promise<string> {
const url = `${LLAMA_CLOUD_BASE_URL}/files/${fileId}/content?project_id=${projectId}`;
const headers = {
Accept: "application/json",
Authorization: `Bearer ${process.env.LLAMA_CLOUD_API_KEY}`,
};
const response = await fetch(url, { method: "GET", headers });
const response = await fetch(url, {
method: "GET",
headers: LLamaCloudFileService.headers,
});
const data = (await response.json()) as { url: string };
return data.url;
}
Expand All @@ -117,12 +157,31 @@ export class LLamaCloudFileService {
pipelineId: string,
): Promise<LlamaCloudFile[]> {
const url = `${LLAMA_CLOUD_BASE_URL}/pipelines/${pipelineId}/files`;
const headers = {
Accept: "application/json",
Authorization: `Bearer ${process.env.LLAMA_CLOUD_API_KEY}`,
};
const response = await fetch(url, { method: "GET", headers });
const response = await fetch(url, {
method: "GET",
headers: LLamaCloudFileService.headers,
});
const data = await response.json();
return data;
}

private static async getAllProjects(): Promise<LLamaCloudProject[]> {
const url = `${LLAMA_CLOUD_BASE_URL}/projects`;
const response = await fetch(url, {
method: "GET",
headers: LLamaCloudFileService.headers,
});
const data = (await response.json()) as LLamaCloudProject[];
return data;
}

private static async getAllPipelines(): Promise<LLamaCloudPipeline[]> {
const url = `${LLAMA_CLOUD_BASE_URL}/pipelines`;
const response = await fetch(url, {
method: "GET",
headers: LLamaCloudFileService.headers,
});
const data = (await response.json()) as LLamaCloudPipeline[];
return data;
}
}
9 changes: 5 additions & 4 deletions templates/components/vectordbs/python/llamacloud/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@

logger = logging.getLogger("uvicorn")


def get_index():
name = os.getenv("LLAMA_CLOUD_INDEX_NAME")
project_name = os.getenv("LLAMA_CLOUD_PROJECT_NAME")
def get_index(params=None):
configParams = params or {}
pipelineConfig = configParams.get("llamaCloudPipeline", {})
name = pipelineConfig.get("pipeline", os.getenv("LLAMA_CLOUD_INDEX_NAME"))
project_name = pipelineConfig.get("project", os.getenv("LLAMA_CLOUD_PROJECT_NAME"))
api_key = os.getenv("LLAMA_CLOUD_API_KEY")
base_url = os.getenv("LLAMA_CLOUD_BASE_URL")
organization_id = os.getenv("LLAMA_CLOUD_ORGANIZATION_ID")
Expand Down
2 changes: 1 addition & 1 deletion templates/components/vectordbs/python/none/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def get_storage_context(persist_dir: str) -> StorageContext:
return StorageContext.from_defaults(persist_dir=persist_dir)


def get_index():
def get_index(params=None):
storage_dir = os.getenv("STORAGE_DIR", "storage")
# check if storage already exists
if not os.path.exists(storage_dir):
Expand Down
2 changes: 1 addition & 1 deletion templates/components/vectordbs/typescript/astra/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { VectorStoreIndex } from "llamaindex";
import { AstraDBVectorStore } from "llamaindex/storage/vectorStore/AstraDBVectorStore";
import { checkRequiredEnvVars } from "./shared";

export async function getDataSource() {
export async function getDataSource(params?: any) {
checkRequiredEnvVars();
const store = new AstraDBVectorStore();
await store.connect(process.env.ASTRA_DB_COLLECTION!);
Expand Down
2 changes: 1 addition & 1 deletion templates/components/vectordbs/typescript/chroma/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { VectorStoreIndex } from "llamaindex";
import { ChromaVectorStore } from "llamaindex/storage/vectorStore/ChromaVectorStore";
import { checkRequiredEnvVars } from "./shared";

export async function getDataSource() {
export async function getDataSource(params?: any) {
marcusschiesser marked this conversation as resolved.
Show resolved Hide resolved
checkRequiredEnvVars();
const chromaUri = `http://${process.env.CHROMA_HOST}:${process.env.CHROMA_PORT}`;

Expand Down
26 changes: 20 additions & 6 deletions templates/components/vectordbs/typescript/llamacloud/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import { LlamaCloudIndex } from "llamaindex/cloud/LlamaCloudIndex";
import { checkRequiredEnvVars } from "./shared";

export async function getDataSource() {
checkRequiredEnvVars();
type LlamaCloudDataSourceParams = {
llamaCloudPipeline?: {
project: string;
pipeline: string;
};
};

export async function getDataSource(params?: LlamaCloudDataSourceParams) {
const { project, pipeline } = params?.llamaCloudPipeline ?? {};
const projectName = project ?? process.env.LLAMA_CLOUD_PROJECT_NAME;
const pipelineName = pipeline ?? process.env.LLAMA_CLOUD_INDEX_NAME;
const apiKey = process.env.LLAMA_CLOUD_API_KEY;
if (!projectName || !pipelineName || !apiKey) {
throw new Error(
"Set project, pipeline, and api key in the params or as environment variables.",
);
}
const index = new LlamaCloudIndex({
name: process.env.LLAMA_CLOUD_INDEX_NAME!,
projectName: process.env.LLAMA_CLOUD_PROJECT_NAME!,
apiKey: process.env.LLAMA_CLOUD_API_KEY,
name: pipelineName,
projectName,
apiKey,
baseUrl: process.env.LLAMA_CLOUD_BASE_URL,
});
return index;
Expand Down
2 changes: 1 addition & 1 deletion templates/components/vectordbs/typescript/milvus/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { VectorStoreIndex } from "llamaindex";
import { MilvusVectorStore } from "llamaindex/storage/vectorStore/MilvusVectorStore";
import { checkRequiredEnvVars, getMilvusClient } from "./shared";

export async function getDataSource() {
export async function getDataSource(params?: any) {
checkRequiredEnvVars();
const milvusClient = getMilvusClient();
const store = new MilvusVectorStore({ milvusClient });
Expand Down
2 changes: 1 addition & 1 deletion templates/components/vectordbs/typescript/mongo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { MongoDBAtlasVectorSearch } from "llamaindex/storage/vectorStore/MongoDB
import { MongoClient } from "mongodb";
import { checkRequiredEnvVars } from "./shared";

export async function getDataSource() {
export async function getDataSource(params?: any) {
marcusschiesser marked this conversation as resolved.
Show resolved Hide resolved
checkRequiredEnvVars();
const client = new MongoClient(process.env.MONGO_URI!);
const store = new MongoDBAtlasVectorSearch({
Expand Down
2 changes: 1 addition & 1 deletion templates/components/vectordbs/typescript/none/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { SimpleDocumentStore, VectorStoreIndex } from "llamaindex";
import { storageContextFromDefaults } from "llamaindex/storage/StorageContext";
import { STORAGE_CACHE_DIR } from "./shared";

export async function getDataSource() {
export async function getDataSource(params?: any) {
thucpn marked this conversation as resolved.
Show resolved Hide resolved
const storageContext = await storageContextFromDefaults({
persistDir: `${STORAGE_CACHE_DIR}`,
});
Expand Down
2 changes: 1 addition & 1 deletion templates/components/vectordbs/typescript/pg/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
checkRequiredEnvVars,
} from "./shared";

export async function getDataSource() {
export async function getDataSource(params?: any) {
checkRequiredEnvVars();
const pgvs = new PGVectorStore({
connectionString: process.env.PG_CONNECTION_STRING,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { VectorStoreIndex } from "llamaindex";
import { PineconeVectorStore } from "llamaindex/storage/vectorStore/PineconeVectorStore";
import { checkRequiredEnvVars } from "./shared";

export async function getDataSource() {
export async function getDataSource(params?: any) {
checkRequiredEnvVars();
const store = new PineconeVectorStore();
return await VectorStoreIndex.fromVectorStore(store);
Expand Down
2 changes: 1 addition & 1 deletion templates/components/vectordbs/typescript/qdrant/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { checkRequiredEnvVars, getQdrantClient } from "./shared";

dotenv.config();

export async function getDataSource() {
export async function getDataSource(params?: any) {
checkRequiredEnvVars();
const collectionName = process.env.QDRANT_COLLECTION;
const store = new QdrantVectorStore({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Request, Response } from "express";
import { LLamaCloudFileService } from "./llamaindex/streaming/service";

export const chatConfig = async (_req: Request, res: Response) => {
let starterQuestions = undefined;
Expand All @@ -12,3 +13,14 @@ export const chatConfig = async (_req: Request, res: Response) => {
starterQuestions,
});
};

export const chatLlamaCloudConfig = async (_req: Request, res: Response) => {
const config = {
projects: await LLamaCloudFileService.getAllProjectsWithPipelines(),
pipeline: {
pipeline: process.env.LLAMA_CLOUD_INDEX_NAME,
project: process.env.LLAMA_CLOUD_PROJECT_NAME,
},
};
return res.status(200).json(config);
};
marcusschiesser marked this conversation as resolved.
Show resolved Hide resolved
Loading
Loading