Skip to content

feat: use llamacloud for chat #149

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

Merged
merged 12 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
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/tough-pugs-destroy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-llama": patch
---

use llamacloud for chat
20 changes: 20 additions & 0 deletions helpers/env-variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,26 @@ const getVectorDBEnvs = (
"Optional API key for authenticating requests to Qdrant.",
},
];
case "llamacloud":
return [
{
name: "LLAMA_CLOUD_INDEX_NAME",
description:
"The name of the LlamaCloud index to use (part of the LlamaCloud project).",
value: "test",
},
{
name: "LLAMA_CLOUD_PROJECT_NAME",
description: "The name of the LlamaCloud project.",
value: "Default",
},
{
name: "LLAMA_CLOUD_BASE_URL",
description:
"The base URL for the LlamaCloud API. Only change this for non-production environments",
value: "https://api.cloud.llamaindex.ai",
},
];
case "chroma":
const envs = [
{
Expand Down
6 changes: 6 additions & 0 deletions helpers/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ const getAdditionalDependencies = (
version: "^2.9.9",
});
break;
case "llamacloud":
dependencies.push({
name: "llama-index-indices-managed-llama-cloud",
version: "^0.2.1",
});
break;
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions helpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ export type TemplateVectorDB =
| "milvus"
| "astra"
| "qdrant"
| "chroma";
| "chroma"
| "llamacloud";
export type TemplatePostInstallAction =
| "none"
| "VSCode"
Expand All @@ -36,7 +37,7 @@ export type TemplateDataSource = {
type: TemplateDataSourceType;
config: TemplateDataSourceConfig;
};
export type TemplateDataSourceType = "file" | "web" | "db";
export type TemplateDataSourceType = "file" | "web" | "db" | "llamacloud";
export type TemplateObservability = "none" | "opentelemetry";
// Config for both file and folder
export type FileSourceConfig = {
Expand Down
10 changes: 8 additions & 2 deletions helpers/typescript.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fs from "fs/promises";
import os from "os";
import path from "path";
import { bold, cyan } from "picocolors";
import { bold, cyan, yellow } from "picocolors";
import { assetRelocator, copy } from "../helpers/copy";
import { callPackageManager } from "../helpers/install";
import { templatesDir } from "./dir";
Expand Down Expand Up @@ -105,7 +105,13 @@ export const installTSTemplate = async ({
const enginePath = path.join(root, relativeEngineDestPath, "engine");

// copy vector db component
console.log("\nUsing vector DB:", vectorDb ?? "none", "\n");
if (vectorDb === "llamacloud") {
console.log(
`\nUsing managed index from LlamaCloud. Ensure the ${yellow("LLAMA_CLOUD_* environment variables are set correctly.")}`,
);
} else {
console.log("\nUsing vector DB:", vectorDb ?? "none");
}
await copy("**", enginePath, {
parents: true,
cwd: path.join(compPath, "vectordbs", "typescript", vectorDb ?? "none"),
Expand Down
80 changes: 57 additions & 23 deletions questions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,13 @@ export const getDataSourceChoices = (
framework: TemplateFramework,
selectedDataSource: TemplateDataSource[],
) => {
// If LlamaCloud is already selected, don't show any other options
if (selectedDataSource.find((s) => s.type === "llamacloud")) {
return [];
}

const choices = [];

if (selectedDataSource.length > 0) {
choices.push({
title: "No",
Expand Down Expand Up @@ -171,6 +177,13 @@ export const getDataSourceChoices = (
value: "db",
});
}

if (!selectedDataSource.length) {
choices.push({
title: "Use managed index from LlamaCloud",
value: "llamacloud",
});
}
return choices;
};

Expand Down Expand Up @@ -484,17 +497,19 @@ export const askQuestions = async (
// continue asking user for data sources if none are initially provided
while (true) {
const firstQuestion = program.dataSources.length === 0;
const choices = getDataSourceChoices(
program.framework,
program.dataSources,
);
if (choices.length === 0) break;
const { selectedSource } = await prompts(
{
type: "select",
name: "selectedSource",
message: firstQuestion
? "Which data source would you like to use?"
: "Would you like to add another data source?",
choices: getDataSourceChoices(
program.framework,
program.dataSources,
),
choices,
initial: firstQuestion ? 1 : 0,
},
questionHandlers,
Expand Down Expand Up @@ -591,19 +606,22 @@ export const askQuestions = async (
config: await prompts(dbPrompts, questionHandlers),
});
}
case "llamacloud": {
program.dataSources.push({
type: "llamacloud",
config: {},
});
break;
}
}
}
}
}

// Asking for LlamaParse if user selected file or folder data source
if (
program.dataSources.some((ds) => ds.type === "file") &&
program.useLlamaParse === undefined
) {
// Asking for LlamaParse if user selected file data source
if (program.dataSources.some((ds) => ds.type === "file")) {
if (ciInfo.isCI) {
program.useLlamaParse = getPrefOrDefault("useLlamaParse");
program.llamaCloudKey = getPrefOrDefault("llamaCloudKey");
} else {
const { useLlamaParse } = await prompts(
{
Expand All @@ -618,24 +636,40 @@ export const askQuestions = async (
questionHandlers,
);
program.useLlamaParse = useLlamaParse;
preferences.useLlamaParse = useLlamaParse;
}
}

const isUsingLlamaCloud = program.dataSources.some(
(ds) => ds.type === "llamacloud",
);

// Ask for LlamaCloud API key when using a LlamaCloud index or LlamaParse
if (isUsingLlamaCloud || program.useLlamaParse) {
if (ciInfo.isCI) {
program.llamaCloudKey = getPrefOrDefault("llamaCloudKey");
} else {
// Ask for LlamaCloud API key
if (useLlamaParse && program.llamaCloudKey === undefined) {
const { llamaCloudKey } = await prompts(
{
type: "text",
name: "llamaCloudKey",
message:
"Please provide your LlamaIndex Cloud API key (leave blank to skip):",
},
questionHandlers,
);
program.llamaCloudKey = llamaCloudKey;
}
const { llamaCloudKey } = await prompts(
{
type: "text",
name: "llamaCloudKey",
message:
"Please provide your LlamaCloud API key (leave blank to skip):",
},
questionHandlers,
);
program.llamaCloudKey = preferences.llamaCloudKey =
llamaCloudKey || process.env.LLAMA_CLOUD_API_KEY;
}
}

if (program.dataSources.length > 0 && !program.vectorDb) {
if (isUsingLlamaCloud) {
// When using a LlamaCloud index, don't ask for vector database and use code in `llamacloud` folder for vector database
const vectorDb = "llamacloud";
program.vectorDb = vectorDb;
preferences.vectorDb = vectorDb;
} else if (program.dataSources.length > 0 && !program.vectorDb) {
if (ciInfo.isCI) {
program.vectorDb = getPrefOrDefault("vectorDb");
} else {
Expand Down
3 changes: 1 addition & 2 deletions templates/components/engines/typescript/agent/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { BaseToolWithCall, OpenAIAgent, QueryEngineTool } from "llamaindex";
import fs from "node:fs/promises";
import path from "node:path";
import { getDataSource } from "./index";
import { STORAGE_CACHE_DIR } from "./shared";
import { createTools } from "./tools";

export async function createChatEngine() {
Expand All @@ -17,7 +16,7 @@ export async function createChatEngine() {
queryEngine: index.asQueryEngine(),
metadata: {
name: "data_query_engine",
description: `A query engine for documents in storage folder: ${STORAGE_CACHE_DIR}`,
description: `A query engine for documents from your data source.`,
},
}),
);
Expand Down
10 changes: 5 additions & 5 deletions templates/components/engines/typescript/chat/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ export async function createChatEngine() {
`StorageContext is empty - call 'npm run generate' to generate the storage first`,
);
}
const retriever = index.asRetriever();
retriever.similarityTopK = process.env.TOP_K
? parseInt(process.env.TOP_K)
: 3;
const retriever = index.asRetriever({
similarityTopK: process.env.TOP_K ? parseInt(process.env.TOP_K) : 3,
});

return new ContextChatEngine({
chatModel: Settings.llm,
retriever,
systemPrompt: process.env.SYSTEM_PROMPT,
// disable as a custom system prompt disables the generated context
// systemPrompt: process.env.SYSTEM_PROMPT,
Comment on lines +18 to +19
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider removing or clarifying the commented-out systemPrompt.

Commented-out code can lead to confusion if the reason isn't documented. If systemPrompt is no longer needed due to changes in how the chat engine handles prompts, it should be removed to avoid clutter. If it might be needed later, add a comment explaining the conditions under which it would be re-enabled.

-    // systemPrompt: process.env.SYSTEM_PROMOT,
+    // systemPrompt: process.env.SYSTEM_PROMPT, // Temporarily disabled until [condition/reason]
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// disable as a custom system prompt disables the generated context
// systemPrompt: process.env.SYSTEM_PROMPT,
// disable as a custom system prompt disables the generated context
// systemPrompt: process.env.SYSTEM_PROMPT, // Temporarily disabled until [condition/reason]

});
}
Empty file.
45 changes: 45 additions & 0 deletions templates/components/vectordbs/python/llamacloud/generate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from dotenv import load_dotenv

load_dotenv()

import os
import logging
from app.settings import init_settings
from app.engine.loaders import get_documents
from llama_index.indices.managed.llama_cloud import LlamaCloudIndex


logging.basicConfig(level=logging.INFO)
logger = logging.getLogger()


def generate_datasource():
init_settings()
logger.info("Generate index for the provided data")

name = os.getenv("LLAMA_CLOUD_INDEX_NAME")
project_name = os.getenv("LLAMA_CLOUD_PROJECT_NAME")
api_key = os.getenv("LLAMA_CLOUD_API_KEY")
base_url = os.getenv("LLAMA_CLOUD_BASE_URL")

if not name or not project_name or not api_key:
raise ValueError(
"Please set LLAMA_CLOUD_INDEX_NAME, LLAMA_CLOUD_PROJECT_NAME and LLAMA_CLOUD_API_KEY"
" to your environment variables or config them in .env file"
)

documents = get_documents()

LlamaCloudIndex.from_documents(
documents,
name,
project_name=project_name,
api_key=api_key,
base_url=base_url,
)

logger.info("Finished generating the index")


if __name__ == "__main__":
generate_datasource()
32 changes: 32 additions & 0 deletions templates/components/vectordbs/python/llamacloud/index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from dotenv import load_dotenv

load_dotenv()

import logging
import os
from llama_index.indices.managed.llama_cloud import LlamaCloudIndex


logger = logging.getLogger("uvicorn")


def get_index():
name = os.getenv("LLAMA_CLOUD_INDEX_NAME")
project_name = os.getenv("LLAMA_CLOUD_PROJECT_NAME")
api_key = os.getenv("LLAMA_CLOUD_API_KEY")
base_url = os.getenv("LLAMA_CLOUD_BASE_URL")

if not name or not project_name or not api_key:
raise ValueError(
"Please set LLAMA_CLOUD_INDEX_NAME, LLAMA_CLOUD_PROJECT_NAME and LLAMA_CLOUD_API_KEY"
" to your environment variables or config them in .env file"
)

index = LlamaCloudIndex(
name,
project_name=project_name,
api_key=api_key,
base_url=base_url,
)

return index
26 changes: 26 additions & 0 deletions templates/components/vectordbs/typescript/llamacloud/generate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as dotenv from "dotenv";
import { LlamaCloudIndex } from "llamaindex";
import { getDocuments } from "./loader";
import { initSettings } from "./settings";
import { checkRequiredEnvVars } from "./shared";

dotenv.config();

async function loadAndIndex() {
const documents = await getDocuments();
await LlamaCloudIndex.fromDocuments({
documents,
name: process.env.LLAMA_CLOUD_INDEX_NAME!,
projectName: process.env.LLAMA_CLOUD_PROJECT_NAME!,
apiKey: process.env.LLAMA_CLOUD_API_KEY,
baseUrl: process.env.LLAMA_CLOUD_BASE_URL,
});
console.log(`Successfully created embeddings!`);
}

(async () => {
checkRequiredEnvVars();
initSettings();
await loadAndIndex();
console.log("Finished generating storage.");
})();
13 changes: 13 additions & 0 deletions templates/components/vectordbs/typescript/llamacloud/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { LlamaCloudIndex } from "llamaindex/cloud/LlamaCloudIndex";
import { checkRequiredEnvVars } from "./shared";

export async function getDataSource() {
checkRequiredEnvVars();
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,
baseUrl: process.env.LLAMA_CLOUD_BASE_URL,
});
return index;
}
Loading
Loading