mirror of
https://github.com/run-llama/create-llama.git
synced 2026-07-09 07:15:59 -04:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 670e2631f3 | |||
| afb519d231 |
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"create-llama": patch
|
||||
---
|
||||
|
||||
fix: add trycatch for generating error
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"create-llama": patch
|
||||
---
|
||||
|
||||
bump: chat-ui and tailwind v4
|
||||
+24
-27
@@ -1,13 +1,12 @@
|
||||
name: E2E Tests for create-llama package
|
||||
name: E2E Tests
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths-ignore:
|
||||
- "python/llama-index-server/**"
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths-ignore:
|
||||
- "python/llama-index-server/**"
|
||||
|
||||
env:
|
||||
POETRY_VERSION: "1.6.1"
|
||||
|
||||
jobs:
|
||||
e2e-python:
|
||||
@@ -33,10 +32,10 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Install uv
|
||||
run: curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
- name: Add uv to PATH # Ensure uv is available in subsequent steps
|
||||
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
||||
- name: Install Poetry
|
||||
uses: snok/install-poetry@v1
|
||||
with:
|
||||
version: ${{ env.POETRY_VERSION }}
|
||||
|
||||
- uses: pnpm/action-setup@v3
|
||||
|
||||
@@ -51,15 +50,15 @@ jobs:
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: pnpm exec playwright install --with-deps
|
||||
working-directory: packages/create-llama
|
||||
working-directory: .
|
||||
|
||||
- name: Build create-llama
|
||||
run: pnpm run build
|
||||
working-directory: packages/create-llama
|
||||
working-directory: .
|
||||
|
||||
- name: Install
|
||||
run: pnpm run pack-install
|
||||
working-directory: packages/create-llama
|
||||
working-directory: .
|
||||
|
||||
- name: Run Playwright tests for Python
|
||||
run: pnpm run e2e:python
|
||||
@@ -68,15 +67,13 @@ jobs:
|
||||
LLAMA_CLOUD_API_KEY: ${{ secrets.LLAMA_CLOUD_API_KEY }}
|
||||
FRAMEWORK: ${{ matrix.frameworks }}
|
||||
DATASOURCE: ${{ matrix.datasources }}
|
||||
PYTHONIOENCODING: utf-8
|
||||
PYTHONLEGACYWINDOWSSTDIO: utf-8
|
||||
working-directory: packages/create-llama
|
||||
working-directory: .
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report-python-${{ matrix.os }}-${{ matrix.frameworks }}-${{ matrix.datasources }}
|
||||
path: packages/create-llama/playwright-report/
|
||||
path: ./playwright-report/
|
||||
overwrite: true
|
||||
retention-days: 30
|
||||
|
||||
@@ -86,10 +83,10 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
node-version: [20, 22]
|
||||
node-version: [18, 20]
|
||||
python-version: ["3.11"]
|
||||
os: [macos-latest, windows-latest, ubuntu-22.04]
|
||||
frameworks: ["nextjs"]
|
||||
frameworks: ["nextjs", "express"]
|
||||
datasources: ["--no-files", "--example-file", "--llamacloud"]
|
||||
defaults:
|
||||
run:
|
||||
@@ -103,10 +100,10 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Install uv
|
||||
run: curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
- name: Add uv to PATH # Ensure uv is available in subsequent steps
|
||||
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
||||
- name: Install Poetry
|
||||
uses: snok/install-poetry@v1
|
||||
with:
|
||||
version: ${{ env.POETRY_VERSION }}
|
||||
|
||||
- uses: pnpm/action-setup@v3
|
||||
|
||||
@@ -121,15 +118,15 @@ jobs:
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: pnpm exec playwright install --with-deps
|
||||
working-directory: packages/create-llama
|
||||
working-directory: .
|
||||
|
||||
- name: Build create-llama
|
||||
run: pnpm run build
|
||||
working-directory: packages/create-llama
|
||||
working-directory: .
|
||||
|
||||
- name: Install
|
||||
run: pnpm run pack-install
|
||||
working-directory: packages/create-llama
|
||||
working-directory: .
|
||||
|
||||
- name: Run Playwright tests for TypeScript
|
||||
run: pnpm run e2e:typescript
|
||||
@@ -138,12 +135,12 @@ jobs:
|
||||
LLAMA_CLOUD_API_KEY: ${{ secrets.LLAMA_CLOUD_API_KEY }}
|
||||
FRAMEWORK: ${{ matrix.frameworks }}
|
||||
DATASOURCE: ${{ matrix.datasources }}
|
||||
working-directory: packages/create-llama
|
||||
working-directory: .
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report-typescript-${{ matrix.os }}-${{ matrix.frameworks }}-${{ matrix.datasources }}-node${{ matrix.node-version }}
|
||||
path: packages/create-llama/playwright-report/
|
||||
path: ./playwright-report/
|
||||
overwrite: true
|
||||
retention-days: 30
|
||||
|
||||
@@ -35,10 +35,8 @@ jobs:
|
||||
uses: chartboost/ruff-action@v1
|
||||
with:
|
||||
args: "format --check"
|
||||
src: "python/llama-index-server"
|
||||
|
||||
- name: Run Python lint
|
||||
uses: chartboost/ruff-action@v1
|
||||
with:
|
||||
args: "check"
|
||||
src: "python/llama-index-server"
|
||||
|
||||
@@ -5,7 +5,7 @@ on:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "python/llama-index-server/**"
|
||||
- "llama-index-server/**"
|
||||
- ".github/workflows/release_llama_index_server.yml"
|
||||
pull_request:
|
||||
types:
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./python/llama-index-server
|
||||
working-directory: ./llama-index-server
|
||||
if: |
|
||||
github.event_name == 'push' &&
|
||||
!startsWith(github.ref, 'refs/heads/release/llama-index-server-v')
|
||||
@@ -80,7 +80,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./python/llama-index-server
|
||||
working-directory: ./llama-index-server
|
||||
if: |
|
||||
github.event_name == 'pull_request' &&
|
||||
github.event.pull_request.merged == true &&
|
||||
@@ -114,7 +114,7 @@ jobs:
|
||||
with:
|
||||
python_version: "3.11"
|
||||
pypi_token: ${{ secrets.PYPI_TOKEN }}
|
||||
package_directory: "python/llama-index-server"
|
||||
package_directory: "llama-index-server"
|
||||
poetry_install_options: "--without dev"
|
||||
|
||||
- name: Create GitHub Release
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
working-directory: python/llama-index-server
|
||||
working-directory: llama-index-server
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: python/llama-index-server
|
||||
working-directory: llama-index-server
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: python/llama-index-server
|
||||
working-directory: llama-index-server
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Poetry
|
||||
@@ -108,4 +108,4 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: llama-index-server
|
||||
path: python/llama-index-server/dist/
|
||||
path: llama-index-server/dist/
|
||||
|
||||
+26
@@ -6,6 +6,10 @@ node_modules
|
||||
.pnpm-store
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
coverage
|
||||
.coverage
|
||||
|
||||
# next.js
|
||||
.next/
|
||||
out/
|
||||
@@ -31,9 +35,31 @@ yarn-error.log*
|
||||
dist/
|
||||
lib/
|
||||
|
||||
# e2e
|
||||
.cache
|
||||
test-results/
|
||||
playwright-report/
|
||||
blob-report/
|
||||
playwright/.cache/
|
||||
.tsbuildinfo
|
||||
e2e/cache
|
||||
|
||||
# intellij
|
||||
**/.idea
|
||||
|
||||
# Python
|
||||
.mypy_cache/
|
||||
venv/
|
||||
.venv/
|
||||
dist/
|
||||
.__pycache__
|
||||
__pycache__
|
||||
.python-version
|
||||
.ui
|
||||
|
||||
# build artifacts
|
||||
create-llama-*.tgz
|
||||
|
||||
# vscode
|
||||
.vscode
|
||||
!.vscode/settings.json
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
pnpm format
|
||||
pnpm lint
|
||||
uvx ruff format --check packages/create-llama/templates/
|
||||
uvx ruff format --check templates/
|
||||
|
||||
@@ -1,84 +1,5 @@
|
||||
# create-llama
|
||||
|
||||
## 0.5.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 3960618: chore: create-llama monorepo
|
||||
- 8fe5fc2: chore: add llamaindex server package
|
||||
|
||||
## 0.5.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 0a2e12a: Use uv as the default package manager
|
||||
|
||||
## 0.5.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 4bc53ac: Bump new chat ui and update deep research component
|
||||
- 4bc53ac: Support generate UI for deep research use case (Typescript)
|
||||
|
||||
## 0.5.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 765181a: chore: test typescript e2e with node 20 and 22
|
||||
|
||||
## 0.5.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 5988657: chore: bump llmaindex
|
||||
|
||||
## 0.5.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- d363ced: Bump llamaindex server packages
|
||||
|
||||
## 0.5.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ee85320: The default custom deep research component does not work.
|
||||
|
||||
## 0.5.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 7c3b279: Support code generation of event components using an LLM (Python)
|
||||
|
||||
## 0.5.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 76ec360: Update templates to use new chat ui config
|
||||
|
||||
## 0.5.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- c9f8f8d: Use custom component for deep research use case
|
||||
|
||||
## 0.5.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 08b3e07: Simplify the local index code.
|
||||
|
||||
## 0.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 54c9e2f: Simplified generated code using LlamaIndexServer
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 0e4ecfa: fix: add trycatch for generating error
|
||||
- ee69ce7: bump: chat-ui and tailwind v4
|
||||
|
||||
## 0.4.0
|
||||
|
||||
### Minor Changes
|
||||
@@ -55,7 +55,7 @@ Then re-start your app. Remember you'll need to re-run `generate` if you add new
|
||||
If you're using the Python backend, you can trigger indexing of your data by calling:
|
||||
|
||||
```bash
|
||||
uv run generate
|
||||
poetry run generate
|
||||
```
|
||||
|
||||
## Customizing the AI models
|
||||
@@ -130,11 +130,4 @@ Pro mode is ideal for developers who want fine-grained control over their projec
|
||||
- [TS/JS docs](https://ts.llamaindex.ai/)
|
||||
- [Python docs](https://docs.llamaindex.ai/en/stable/)
|
||||
|
||||
## LlamaIndex Server
|
||||
|
||||
The generated code is using the LlamaIndex Server, which serves LlamaIndex Workflows and Agent Workflows via an API server. See the following docs for more information:
|
||||
|
||||
- [LlamaIndex Server For TypeScript](./packages/server/README.md)
|
||||
- [LlamaIndex Server For Python](./python/llama-index-server/README.md)
|
||||
|
||||
Inspired by and adapted from [create-next-app](https://github.com/vercel/next.js/tree/canary/packages/create-next-app)
|
||||
|
||||
@@ -90,7 +90,7 @@ export async function createApp({
|
||||
// Install backend
|
||||
await installTemplate({ ...args, backend: true });
|
||||
|
||||
if (frontend && framework === "fastapi" && template !== "llamaindexserver") {
|
||||
if (frontend && framework === "fastapi") {
|
||||
// install frontend
|
||||
const frontendRoot = path.join(root, ".frontend");
|
||||
await makeDir(frontendRoot);
|
||||
@@ -110,7 +110,7 @@ export async function createApp({
|
||||
console.log();
|
||||
}
|
||||
|
||||
if (toolsRequireConfig(tools) && template !== "llamaindexserver") {
|
||||
if (toolsRequireConfig(tools)) {
|
||||
const configFile =
|
||||
framework === "fastapi" ? "config/tools.yaml" : "config/tools.json";
|
||||
console.log(
|
||||
+15
-30
@@ -195,47 +195,32 @@ async function createAndCheckLlamaProject({
|
||||
const pyprojectPath = path.join(projectPath, "pyproject.toml");
|
||||
expect(fs.existsSync(pyprojectPath)).toBeTruthy();
|
||||
|
||||
// Modify environment for the command
|
||||
const commandEnv = {
|
||||
const env = {
|
||||
...process.env,
|
||||
POETRY_VIRTUALENVS_IN_PROJECT: "true",
|
||||
};
|
||||
|
||||
console.log("Running uv venv...");
|
||||
// Run poetry install
|
||||
try {
|
||||
const { stdout: venvStdout, stderr: venvStderr } = await execAsync(
|
||||
"uv venv",
|
||||
{ cwd: projectPath, env: commandEnv },
|
||||
const { stdout: installStdout, stderr: installStderr } = await execAsync(
|
||||
"poetry install",
|
||||
{ cwd: projectPath, env },
|
||||
);
|
||||
console.log("uv venv stdout:", venvStdout);
|
||||
console.error("uv venv stderr:", venvStderr);
|
||||
console.log("poetry install stdout:", installStdout);
|
||||
console.error("poetry install stderr:", installStderr);
|
||||
} catch (error) {
|
||||
console.error("Error running uv venv:", error);
|
||||
throw error; // Re-throw error to fail the test
|
||||
console.error("Error running poetry install:", error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
console.log("Running uv sync...");
|
||||
try {
|
||||
const { stdout: syncStdout, stderr: syncStderr } = await execAsync(
|
||||
"uv sync --all-extras",
|
||||
{ cwd: projectPath, env: commandEnv },
|
||||
);
|
||||
console.log("uv sync stdout:", syncStdout);
|
||||
console.error("uv sync stderr:", syncStderr);
|
||||
} catch (error) {
|
||||
console.error("Error running uv sync:", error);
|
||||
throw error; // Re-throw error to fail the test
|
||||
}
|
||||
|
||||
console.log("Running uv run mypy ....");
|
||||
// Run poetry run mypy
|
||||
try {
|
||||
const { stdout: mypyStdout, stderr: mypyStderr } = await execAsync(
|
||||
"uv run mypy .",
|
||||
{ cwd: projectPath, env: commandEnv },
|
||||
"poetry run mypy .",
|
||||
{ cwd: projectPath, env },
|
||||
);
|
||||
console.log("uv run mypy stdout:", mypyStdout);
|
||||
console.error("uv run mypy stderr:", mypyStderr);
|
||||
// Assuming mypy success means no output or specific success message
|
||||
// Adjust checks based on actual expected mypy output
|
||||
console.log("poetry run mypy stdout:", mypyStdout);
|
||||
console.error("poetry run mypy stderr:", mypyStderr);
|
||||
} catch (error) {
|
||||
console.error("Error running mypy:", error);
|
||||
throw error;
|
||||
+9
-19
@@ -16,17 +16,15 @@ const templateFramework: TemplateFramework = process.env.FRAMEWORK
|
||||
const dataSource: string = "--example-file";
|
||||
const templateUI: TemplateUI = "shadcn";
|
||||
const templatePostInstallAction: TemplatePostInstallAction = "runApp";
|
||||
const appType: AppType = "--frontend";
|
||||
const appType: AppType = templateFramework === "fastapi" ? "--frontend" : "";
|
||||
const userMessage = "Write a blog post about physical standards for letters";
|
||||
const templateUseCases = ["financial_report", "agentic_rag", "deep_research"];
|
||||
const templateUseCases = ["financial_report", "blog", "form_filling"];
|
||||
|
||||
for (const useCase of templateUseCases) {
|
||||
test.describe(`Test use case ${useCase} ${templateFramework} ${dataSource} ${templateUI} ${appType} ${templatePostInstallAction}`, async () => {
|
||||
test.describe(`Test multiagent template ${useCase} ${templateFramework} ${dataSource} ${templateUI} ${appType} ${templatePostInstallAction}`, async () => {
|
||||
test.skip(
|
||||
process.platform !== "linux" ||
|
||||
process.env.DATASOURCE === "--no-files" ||
|
||||
templateFramework === "express",
|
||||
"The llamaindexserver template currently only works with nextjs, fastapi. We also only run on Linux to speed up tests.",
|
||||
process.platform !== "linux" || process.env.DATASOURCE === "--no-files",
|
||||
"The multiagent template currently only works with files. We also only run on Linux to speed up tests.",
|
||||
);
|
||||
let port: number;
|
||||
let cwd: string;
|
||||
@@ -40,7 +38,7 @@ for (const useCase of templateUseCases) {
|
||||
cwd = await createTestDir();
|
||||
const result = await runCreateLlama({
|
||||
cwd,
|
||||
templateType: "llamaindexserver",
|
||||
templateType: "multiagent",
|
||||
templateFramework,
|
||||
dataSource,
|
||||
vectorDb,
|
||||
@@ -65,9 +63,7 @@ for (const useCase of templateUseCases) {
|
||||
templateFramework === "express",
|
||||
);
|
||||
await page.goto(`http://localhost:${port}`);
|
||||
await expect(page.getByText("Built by LlamaIndex")).toBeVisible({
|
||||
timeout: 5 * 60 * 1000,
|
||||
});
|
||||
await expect(page.getByText("Built by LlamaIndex")).toBeVisible();
|
||||
});
|
||||
|
||||
test("Frontend should be able to submit a message and receive the start of a streamed response", async ({
|
||||
@@ -76,9 +72,9 @@ for (const useCase of templateUseCases) {
|
||||
test.skip(
|
||||
templatePostInstallAction !== "runApp" ||
|
||||
useCase === "financial_report" ||
|
||||
useCase === "deep_research" ||
|
||||
useCase === "form_filling" ||
|
||||
templateFramework === "express",
|
||||
"Skip chat tests for financial report and deep research.",
|
||||
"Skip chat tests for financial report and form filling.",
|
||||
);
|
||||
await page.goto(`http://localhost:${port}`);
|
||||
await page.fill("form textarea", userMessage);
|
||||
@@ -90,12 +86,6 @@ for (const useCase of templateUseCases) {
|
||||
await page.click("form button[type=submit]");
|
||||
|
||||
const response = await responsePromise;
|
||||
console.log(`Response status: ${response.status()}`);
|
||||
const responseBody = await response
|
||||
.text()
|
||||
.catch((e) => `Error reading body: ${e}`);
|
||||
console.log(`Response body: ${responseBody}`);
|
||||
|
||||
expect(response.ok()).toBeTruthy();
|
||||
});
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ test.describe("Test resolve TS dependencies", () => {
|
||||
// Install dependencies using pnpm
|
||||
try {
|
||||
const { stderr: installStderr } = await execAsync(
|
||||
"pnpm install --prefer-offline --ignore-workspace",
|
||||
"pnpm install --prefer-offline",
|
||||
{
|
||||
cwd: appDir,
|
||||
},
|
||||
@@ -113,12 +113,7 @@ export async function runCreateLlama({
|
||||
if (observability) {
|
||||
commandArgs.push("--observability", observability);
|
||||
}
|
||||
if (
|
||||
(templateType === "multiagent" ||
|
||||
templateType === "reflex" ||
|
||||
templateType === "llamaindexserver") &&
|
||||
useCase
|
||||
) {
|
||||
if ((templateType === "multiagent" || templateType === "reflex") && useCase) {
|
||||
commandArgs.push("--use-case", useCase);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ const renderEnvVar = (envVars: EnvVar[]): string => {
|
||||
const getVectorDBEnvs = (
|
||||
vectorDb?: TemplateVectorDB,
|
||||
framework?: TemplateFramework,
|
||||
template?: TemplateType,
|
||||
): EnvVar[] => {
|
||||
if (!vectorDb || !framework) {
|
||||
return [];
|
||||
@@ -169,7 +168,7 @@ const getVectorDBEnvs = (
|
||||
description:
|
||||
"The organization ID for the LlamaCloud project (uses default organization if not specified)",
|
||||
},
|
||||
...(framework === "nextjs" && template !== "llamaindexserver"
|
||||
...(framework === "nextjs"
|
||||
? // activate index selector per default (not needed for non-NextJS backends as it's handled by createFrontendEnvFile)
|
||||
[
|
||||
{
|
||||
@@ -224,15 +223,13 @@ Otherwise, use CHROMA_HOST and CHROMA_PORT config above`,
|
||||
},
|
||||
];
|
||||
default:
|
||||
return template !== "llamaindexserver"
|
||||
? [
|
||||
{
|
||||
name: "STORAGE_CACHE_DIR",
|
||||
description: "The directory to store the local storage cache.",
|
||||
value: ".cache",
|
||||
},
|
||||
]
|
||||
: [];
|
||||
return [
|
||||
{
|
||||
name: "STORAGE_CACHE_DIR",
|
||||
description: "The directory to store the local storage cache.",
|
||||
value: ".cache",
|
||||
},
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -385,42 +382,38 @@ const getModelEnvs = (modelConfig: ModelConfig): EnvVar[] => {
|
||||
|
||||
const getFrameworkEnvs = (
|
||||
framework: TemplateFramework,
|
||||
template: TemplateType,
|
||||
port?: number,
|
||||
): EnvVar[] => {
|
||||
const sPort = port?.toString() || "8000";
|
||||
const result: EnvVar[] =
|
||||
template !== "llamaindexserver"
|
||||
? [
|
||||
{
|
||||
name: "FILESERVER_URL_PREFIX",
|
||||
description:
|
||||
"FILESERVER_URL_PREFIX is the URL prefix of the server storing the images generated by the interpreter.",
|
||||
value:
|
||||
framework === "nextjs"
|
||||
? // FIXME: if we are using nextjs, port should be 3000
|
||||
"http://localhost:3000/api/files"
|
||||
: `http://localhost:${sPort}/api/files`,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
const result: EnvVar[] = [
|
||||
{
|
||||
name: "FILESERVER_URL_PREFIX",
|
||||
description:
|
||||
"FILESERVER_URL_PREFIX is the URL prefix of the server storing the images generated by the interpreter.",
|
||||
value:
|
||||
framework === "nextjs"
|
||||
? // FIXME: if we are using nextjs, port should be 3000
|
||||
"http://localhost:3000/api/files"
|
||||
: `http://localhost:${sPort}/api/files`,
|
||||
},
|
||||
];
|
||||
if (framework === "fastapi") {
|
||||
result.push(
|
||||
...[
|
||||
{
|
||||
name: "APP_HOST",
|
||||
description: "The address to start the FastAPI app.",
|
||||
description: "The address to start the backend app.",
|
||||
value: "0.0.0.0",
|
||||
},
|
||||
{
|
||||
name: "APP_PORT",
|
||||
description: "The port to start the FastAPI app.",
|
||||
description: "The port to start the backend app.",
|
||||
value: sPort,
|
||||
},
|
||||
],
|
||||
);
|
||||
}
|
||||
if (framework === "nextjs" && template !== "llamaindexserver") {
|
||||
if (framework === "nextjs") {
|
||||
result.push({
|
||||
name: "NEXT_PUBLIC_CHAT_API",
|
||||
description:
|
||||
@@ -576,41 +569,25 @@ export const createBackendEnvFile = async (
|
||||
| "port"
|
||||
| "tools"
|
||||
| "observability"
|
||||
| "useLlamaParse"
|
||||
>,
|
||||
) => {
|
||||
// Init env values
|
||||
const envFileName = ".env";
|
||||
const envVars: EnvVar[] = [
|
||||
...(opts.useLlamaParse
|
||||
? [
|
||||
{
|
||||
name: "LLAMA_CLOUD_API_KEY",
|
||||
description: `The Llama Cloud API key.`,
|
||||
value: opts.llamaCloudKey,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...getVectorDBEnvs(opts.vectorDb, opts.framework, opts.template),
|
||||
...getToolEnvs(opts.tools),
|
||||
...getFrameworkEnvs(opts.framework, opts.template, opts.port),
|
||||
{
|
||||
name: "LLAMA_CLOUD_API_KEY",
|
||||
description: `The Llama Cloud API key.`,
|
||||
value: opts.llamaCloudKey,
|
||||
},
|
||||
// Add environment variables of each component
|
||||
...(opts.template === "llamaindexserver"
|
||||
? [
|
||||
{
|
||||
name: "OPENAI_API_KEY",
|
||||
description: "The OpenAI API key to use.",
|
||||
value: opts.modelConfig.apiKey,
|
||||
},
|
||||
]
|
||||
: [
|
||||
// don't use this stuff for llama-indexserver
|
||||
...getModelEnvs(opts.modelConfig),
|
||||
...getEngineEnvs(),
|
||||
...getTemplateEnvs(opts.template),
|
||||
...getObservabilityEnvs(opts.observability),
|
||||
...getSystemPromptEnv(opts.tools, opts.dataSources, opts.template),
|
||||
]),
|
||||
...getModelEnvs(opts.modelConfig),
|
||||
...getEngineEnvs(),
|
||||
...getVectorDBEnvs(opts.vectorDb, opts.framework),
|
||||
...getFrameworkEnvs(opts.framework, opts.port),
|
||||
...getToolEnvs(opts.tools),
|
||||
...getTemplateEnvs(opts.template),
|
||||
...getObservabilityEnvs(opts.observability),
|
||||
...getSystemPromptEnv(opts.tools, opts.dataSources, opts.template),
|
||||
];
|
||||
// Render and write env file
|
||||
const content = renderEnvVar(envVars);
|
||||
@@ -1,7 +1,7 @@
|
||||
import { callPackageManager } from "./install";
|
||||
|
||||
import path from "path";
|
||||
import picocolors, { cyan } from "picocolors";
|
||||
import { cyan } from "picocolors";
|
||||
|
||||
import fsExtra from "fs-extra";
|
||||
import { writeLoadersConfig } from "./datasources";
|
||||
@@ -9,6 +9,7 @@ import { createBackendEnvFile, createFrontendEnvFile } from "./env-variables";
|
||||
import { PackageManager } from "./get-pkg-manager";
|
||||
import { installLlamapackProject } from "./llama-pack";
|
||||
import { makeDir } from "./make-dir";
|
||||
import { isHavingPoetryLockFile, tryPoetryRun } from "./poetry";
|
||||
import { installPythonTemplate } from "./python";
|
||||
import { downloadAndExtractRepo } from "./repo";
|
||||
import { ConfigFileType, writeToolsConfig } from "./tools";
|
||||
@@ -21,7 +22,6 @@ import {
|
||||
TemplateVectorDB,
|
||||
} from "./types";
|
||||
import { installTSTemplate } from "./typescript";
|
||||
import { isHavingUvLockFile, tryUvRun } from "./uv";
|
||||
|
||||
const checkForGenerateScript = (
|
||||
modelConfig: ModelConfig,
|
||||
@@ -41,11 +41,7 @@ const checkForGenerateScript = (
|
||||
missingSettings.push("your LLAMA_CLOUD_API_KEY");
|
||||
}
|
||||
|
||||
if (
|
||||
vectorDb !== undefined &&
|
||||
vectorDb !== "none" &&
|
||||
vectorDb !== "llamacloud"
|
||||
) {
|
||||
if (vectorDb !== "none" && vectorDb !== "llamacloud") {
|
||||
missingSettings.push("your Vector DB environment variables");
|
||||
}
|
||||
|
||||
@@ -64,7 +60,7 @@ async function generateContextData(
|
||||
if (packageManager) {
|
||||
const runGenerate = `${cyan(
|
||||
framework === "fastapi"
|
||||
? "uv run generate"
|
||||
? "poetry run generate"
|
||||
: `${packageManager} run generate`,
|
||||
)}`;
|
||||
|
||||
@@ -78,21 +74,15 @@ async function generateContextData(
|
||||
if (!missingSettings.length) {
|
||||
// If all the required environment variables are set, run the generate script
|
||||
if (framework === "fastapi") {
|
||||
if (isHavingUvLockFile()) {
|
||||
if (isHavingPoetryLockFile()) {
|
||||
console.log(`Running ${runGenerate} to generate the context data.`);
|
||||
const result = tryUvRun("generate");
|
||||
const result = tryPoetryRun("poetry run generate");
|
||||
if (!result) {
|
||||
console.log(`Failed to run ${runGenerate}.`);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(`Generated context data`);
|
||||
return;
|
||||
} else {
|
||||
console.log(
|
||||
picocolors.yellow(
|
||||
`\nWarning: uv.lock not found. Dependency installation might be incomplete. Skipping context generation.\nIf dependencies were installed, try running '${runGenerate}' manually.\n`,
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
console.log(`Running ${runGenerate} to generate the context data.`);
|
||||
@@ -102,14 +92,14 @@ async function generateContextData(
|
||||
}
|
||||
|
||||
const settingsMessage = `After setting ${missingSettings.join(" and ")}, run ${runGenerate} to generate the context data.`;
|
||||
console.log(picocolors.yellow(`\n${settingsMessage}\n\n`));
|
||||
console.log(`\n${settingsMessage}\n\n`);
|
||||
}
|
||||
}
|
||||
|
||||
const downloadFile = async (url: string, destPath: string) => {
|
||||
const response = await fetch(url);
|
||||
const fileBuffer = await response.arrayBuffer();
|
||||
await fsExtra.writeFile(destPath, new Uint8Array(fileBuffer));
|
||||
await fsExtra.writeFile(destPath, Buffer.from(fileBuffer));
|
||||
};
|
||||
|
||||
const prepareContextData = async (
|
||||
@@ -176,17 +166,6 @@ export const installTemplate = async (
|
||||
|
||||
if (props.framework === "fastapi") {
|
||||
await installPythonTemplate(props);
|
||||
} else {
|
||||
await installTSTemplate(props);
|
||||
}
|
||||
|
||||
// write configurations
|
||||
if (props.template !== "llamaindexserver") {
|
||||
await writeToolsConfig(
|
||||
props.root,
|
||||
props.tools,
|
||||
props.framework === "fastapi" ? ConfigFileType.YAML : ConfigFileType.JSON,
|
||||
);
|
||||
if (props.vectorDb !== "llamacloud") {
|
||||
// write loaders configuration (currently Python only)
|
||||
// not needed for LlamaCloud as it has its own loaders
|
||||
@@ -196,13 +175,26 @@ export const installTemplate = async (
|
||||
props.useLlamaParse,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
await installTSTemplate(props);
|
||||
}
|
||||
|
||||
// write tools configuration
|
||||
await writeToolsConfig(
|
||||
props.root,
|
||||
props.tools,
|
||||
props.framework === "fastapi" ? ConfigFileType.YAML : ConfigFileType.JSON,
|
||||
);
|
||||
|
||||
if (props.backend) {
|
||||
// This is a backend, so we need to copy the test data and create the env file.
|
||||
|
||||
// Copy the environment file to the target directory.
|
||||
if (props.template !== "community" && props.template !== "llamapack") {
|
||||
if (
|
||||
props.template === "streaming" ||
|
||||
props.template === "multiagent" ||
|
||||
props.template === "reflex"
|
||||
) {
|
||||
await createBackendEnvFile(props.root, props);
|
||||
}
|
||||
|
||||
@@ -143,6 +143,6 @@ export const installLlamapackProject = async ({
|
||||
await copyData({ root });
|
||||
await installLlamapackExample({ root, llamapack });
|
||||
if (postInstallAction === "runApp" || postInstallAction === "dependencies") {
|
||||
installPythonDependencies();
|
||||
installPythonDependencies({ noRoot: true });
|
||||
}
|
||||
};
|
||||
@@ -3,16 +3,15 @@ import path from "path";
|
||||
import { cyan, red } from "picocolors";
|
||||
import { parse, stringify } from "smol-toml";
|
||||
import terminalLink from "terminal-link";
|
||||
import { isUvAvailable, tryUvSync } from "./uv";
|
||||
|
||||
import { assetRelocator, copy } from "./copy";
|
||||
import { templatesDir } from "./dir";
|
||||
import { isPoetryAvailable, tryPoetryInstall } from "./poetry";
|
||||
import { Tool } from "./tools";
|
||||
import {
|
||||
InstallTemplateArgs,
|
||||
ModelConfig,
|
||||
TemplateDataSource,
|
||||
TemplateObservability,
|
||||
TemplateType,
|
||||
TemplateVectorDB,
|
||||
} from "./types";
|
||||
@@ -30,7 +29,6 @@ const getAdditionalDependencies = (
|
||||
dataSources?: TemplateDataSource[],
|
||||
tools?: Tool[],
|
||||
templateType?: TemplateType,
|
||||
observability?: TemplateObservability,
|
||||
) => {
|
||||
const dependencies: Dependency[] = [];
|
||||
|
||||
@@ -39,21 +37,21 @@ const getAdditionalDependencies = (
|
||||
case "mongo": {
|
||||
dependencies.push({
|
||||
name: "llama-index-vector-stores-mongodb",
|
||||
version: ">=0.3.2,<0.4.0",
|
||||
version: "^0.6.0",
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "pg": {
|
||||
dependencies.push({
|
||||
name: "llama-index-vector-stores-postgres",
|
||||
version: ">=0.3.2,<0.4.0",
|
||||
version: "^0.3.2",
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "pinecone": {
|
||||
dependencies.push({
|
||||
name: "llama-index-vector-stores-pinecone",
|
||||
version: ">=0.4.1,<0.5.0",
|
||||
version: "^0.4.1",
|
||||
constraints: {
|
||||
python: ">=3.11,<3.13",
|
||||
},
|
||||
@@ -63,25 +61,25 @@ const getAdditionalDependencies = (
|
||||
case "milvus": {
|
||||
dependencies.push({
|
||||
name: "llama-index-vector-stores-milvus",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
version: "^0.3.0",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "pymilvus",
|
||||
version: ">=2.4.4,<3.0.0",
|
||||
version: "2.4.4",
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "astra": {
|
||||
dependencies.push({
|
||||
name: "llama-index-vector-stores-astra-db",
|
||||
version: ">=0.4.0,<0.5.0",
|
||||
version: "^0.4.0",
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "qdrant": {
|
||||
dependencies.push({
|
||||
name: "llama-index-vector-stores-qdrant",
|
||||
version: ">=0.4.0,<0.5.0",
|
||||
version: "^0.4.0",
|
||||
constraints: {
|
||||
python: ">=3.11,<3.13",
|
||||
},
|
||||
@@ -91,21 +89,21 @@ const getAdditionalDependencies = (
|
||||
case "chroma": {
|
||||
dependencies.push({
|
||||
name: "llama-index-vector-stores-chroma",
|
||||
version: ">=0.4.0,<0.5.0",
|
||||
version: "^0.4.0",
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "weaviate": {
|
||||
dependencies.push({
|
||||
name: "llama-index-vector-stores-weaviate",
|
||||
version: ">=1.2.3,<2.0.0",
|
||||
version: "^1.2.3",
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "llamacloud":
|
||||
dependencies.push({
|
||||
name: "llama-index-indices-managed-llama-cloud",
|
||||
version: ">=0.6.3,<0.7.0",
|
||||
version: "^0.6.3",
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -118,28 +116,28 @@ const getAdditionalDependencies = (
|
||||
case "file":
|
||||
dependencies.push({
|
||||
name: "docx2txt",
|
||||
version: ">=0.8,<0.9",
|
||||
version: "^0.8",
|
||||
});
|
||||
break;
|
||||
case "web":
|
||||
dependencies.push({
|
||||
name: "llama-index-readers-web",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
version: "^0.3.0",
|
||||
});
|
||||
break;
|
||||
case "db":
|
||||
dependencies.push({
|
||||
name: "llama-index-readers-database",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
version: "^0.3.0",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "pymysql",
|
||||
version: ">=1.1.0,<2.0.0",
|
||||
version: "^1.1.0",
|
||||
extras: ["rsa"],
|
||||
});
|
||||
dependencies.push({
|
||||
name: "psycopg2-binary",
|
||||
version: ">=2.9.9,<3.0.0",
|
||||
version: "^2.9.9",
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -158,122 +156,155 @@ const getAdditionalDependencies = (
|
||||
case "ollama":
|
||||
dependencies.push({
|
||||
name: "llama-index-llms-ollama",
|
||||
version: ">=0.5.0,<0.6.0",
|
||||
version: "0.3.0",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "llama-index-embeddings-ollama",
|
||||
version: ">=0.6.0,<0.7.0",
|
||||
version: "0.3.0",
|
||||
});
|
||||
break;
|
||||
case "openai":
|
||||
if (templateType !== "multiagent") {
|
||||
dependencies.push({
|
||||
name: "llama-index-llms-openai",
|
||||
version: ">=0.3.2,<0.4.0",
|
||||
version: "^0.3.2",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "llama-index-embeddings-openai",
|
||||
version: ">=0.3.1,<0.4.0",
|
||||
version: "^0.3.1",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "llama-index-agent-openai",
|
||||
version: ">=0.4.0,<0.5.0",
|
||||
version: "^0.4.0",
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "groq":
|
||||
// Fastembed==0.2.0 does not support python3.13 at the moment
|
||||
// Fixed the python version less than 3.13
|
||||
dependencies.push({
|
||||
name: "python",
|
||||
version: "^3.11,<3.13",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "llama-index-llms-groq",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
version: "0.2.0",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "llama-index-embeddings-fastembed",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
version: "^0.2.0",
|
||||
});
|
||||
break;
|
||||
case "anthropic":
|
||||
// Fastembed==0.2.0 does not support python3.13 at the moment
|
||||
// Fixed the python version less than 3.13
|
||||
dependencies.push({
|
||||
name: "python",
|
||||
version: "^3.11,<3.13",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "llama-index-llms-anthropic",
|
||||
version: ">=0.6.0,<0.7.0",
|
||||
version: "0.3.0",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "llama-index-embeddings-fastembed",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
version: "^0.2.0",
|
||||
});
|
||||
break;
|
||||
case "gemini":
|
||||
dependencies.push({
|
||||
name: "llama-index-llms-gemini",
|
||||
version: ">=0.4.0,<0.5.0",
|
||||
version: "0.3.4",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "llama-index-embeddings-gemini",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
version: "^0.2.0",
|
||||
});
|
||||
break;
|
||||
case "mistral":
|
||||
dependencies.push({
|
||||
name: "llama-index-llms-mistralai",
|
||||
version: ">=0.4.0,<0.5.0",
|
||||
version: "0.2.1",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "llama-index-embeddings-mistralai",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
version: "0.2.0",
|
||||
});
|
||||
break;
|
||||
case "azure-openai":
|
||||
dependencies.push({
|
||||
name: "llama-index-llms-azure-openai",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
version: "0.2.0",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "llama-index-embeddings-azure-openai",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
version: "0.2.4",
|
||||
});
|
||||
break;
|
||||
case "huggingface":
|
||||
dependencies.push({
|
||||
name: "llama-index-llms-huggingface",
|
||||
version: ">=0.5.0,<0.6.0",
|
||||
version: "^0.3.5",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "llama-index-embeddings-huggingface",
|
||||
version: ">=0.5.0,<0.6.0",
|
||||
version: "^0.3.1",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "optimum",
|
||||
version: ">=1.23.3,<2.0.0",
|
||||
version: "^1.23.3",
|
||||
extras: ["onnxruntime"],
|
||||
});
|
||||
break;
|
||||
case "t-systems":
|
||||
dependencies.push({
|
||||
name: "llama-index-agent-openai",
|
||||
version: ">=0.4.0,<0.5.0",
|
||||
version: "0.3.0",
|
||||
});
|
||||
dependencies.push({
|
||||
name: "llama-index-llms-openai-like",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
version: "0.2.0",
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
if (observability && observability !== "none") {
|
||||
if (observability === "traceloop") {
|
||||
dependencies.push({
|
||||
name: "traceloop-sdk",
|
||||
version: ">=0.15.11,<0.16.0",
|
||||
});
|
||||
return dependencies;
|
||||
};
|
||||
|
||||
const mergePoetryDependencies = (
|
||||
dependencies: Dependency[],
|
||||
existingDependencies: Record<string, Omit<Dependency, "name"> | string>,
|
||||
) => {
|
||||
for (const dependency of dependencies) {
|
||||
let value = existingDependencies[dependency.name] ?? {};
|
||||
|
||||
// default string value is equal to attribute "version"
|
||||
if (typeof value === "string") {
|
||||
value = { version: value };
|
||||
}
|
||||
if (observability === "llamatrace") {
|
||||
dependencies.push({
|
||||
name: "llama-index-callbacks-arize-phoenix",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
});
|
||||
|
||||
value.version = dependency.version ?? value.version;
|
||||
value.extras = dependency.extras ?? value.extras;
|
||||
|
||||
// Merge constraints if they exist
|
||||
if (dependency.constraints) {
|
||||
value = { ...value, ...dependency.constraints };
|
||||
}
|
||||
|
||||
if (value.version === undefined) {
|
||||
throw new Error(
|
||||
`Dependency "${dependency.name}" is missing attribute "version"!`,
|
||||
);
|
||||
}
|
||||
|
||||
// Serialize as object if there are any additional properties
|
||||
if (Object.keys(value).length > 1) {
|
||||
existingDependencies[dependency.name] = value;
|
||||
} else {
|
||||
// Otherwise, serialize just the version string
|
||||
existingDependencies[dependency.name] = value.version;
|
||||
}
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
};
|
||||
|
||||
const copyRouterCode = async (root: string, tools: Tool[]) => {
|
||||
@@ -298,100 +329,19 @@ export const addDependencies = async (
|
||||
// Parse toml file
|
||||
const file = path.join(projectDir, FILENAME);
|
||||
const fileContent = await fs.readFile(file, "utf8");
|
||||
let fileParsed: any;
|
||||
try {
|
||||
fileParsed = parse(fileContent);
|
||||
} catch (parseError) {
|
||||
console.error(`Error parsing ${FILENAME}:`, parseError);
|
||||
throw new Error(
|
||||
`Failed to parse ${FILENAME}. Please ensure it's valid TOML.`,
|
||||
);
|
||||
}
|
||||
const fileParsed = parse(fileContent);
|
||||
|
||||
// Ensure [project] and [project.dependencies] exist
|
||||
if (!fileParsed.project) {
|
||||
fileParsed.project = {};
|
||||
}
|
||||
if (
|
||||
!fileParsed.project.dependencies ||
|
||||
!Array.isArray(fileParsed.project.dependencies)
|
||||
) {
|
||||
// If dependencies exist but aren't an array, log a warning or error.
|
||||
// For now, we'll overwrite it, assuming the intent is to use the standard array format.
|
||||
console.warn(
|
||||
`[project.dependencies] in ${FILENAME} is not an array. It will be overwritten.`,
|
||||
);
|
||||
fileParsed.project.dependencies = [];
|
||||
}
|
||||
|
||||
const existingDependencies: string[] = fileParsed.project.dependencies;
|
||||
const addedDeps: string[] = [];
|
||||
const updatedDeps: string[] = [];
|
||||
|
||||
// Add or update dependencies
|
||||
for (const newDep of dependencies) {
|
||||
let depString = newDep.name;
|
||||
if (newDep.extras && newDep.extras.length > 0) {
|
||||
depString += `[${newDep.extras.join(",")}]`;
|
||||
}
|
||||
if (newDep.version) {
|
||||
depString += newDep.version;
|
||||
}
|
||||
|
||||
let found = false;
|
||||
for (let i = 0; i < existingDependencies.length; i++) {
|
||||
const existingDepNameMatch =
|
||||
existingDependencies[i].match(/^([a-zA-Z0-9._-]+)/);
|
||||
if (
|
||||
existingDepNameMatch &&
|
||||
existingDepNameMatch[1].toLowerCase() === depString.toLowerCase()
|
||||
) {
|
||||
// Found existing dependency, update it
|
||||
if (existingDependencies[i] !== depString) {
|
||||
updatedDeps.push(`${existingDependencies[i]} -> ${depString}`);
|
||||
existingDependencies[i] = depString;
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
// Add new dependency
|
||||
existingDependencies.push(depString);
|
||||
addedDeps.push(depString);
|
||||
}
|
||||
// Handle python version constraints separately (if any)
|
||||
if (newDep.constraints?.python) {
|
||||
if (
|
||||
!fileParsed.project["requires-python"] ||
|
||||
fileParsed.project["requires-python"] !== newDep.constraints.python
|
||||
) {
|
||||
// This simple overwrite might not be ideal; merging constraints is complex.
|
||||
// For now, let's just set it if the new dependency has one.
|
||||
console.log(
|
||||
`Setting requires-python = "${newDep.constraints.python}" from dependency ${newDep.name}`,
|
||||
);
|
||||
fileParsed.project["requires-python"] = newDep.constraints.python;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Modify toml dependencies
|
||||
const tool = fileParsed.tool as any;
|
||||
const existingDependencies = tool.poetry.dependencies;
|
||||
mergePoetryDependencies(dependencies, existingDependencies);
|
||||
|
||||
// Write toml file
|
||||
const newFileContent = stringify(fileParsed);
|
||||
await fs.writeFile(file, newFileContent);
|
||||
|
||||
if (addedDeps.length > 0) {
|
||||
console.log(`\nAdded dependencies to ${cyan(FILENAME)}:`);
|
||||
addedDeps.forEach((dep) => console.log(` ${dep}`));
|
||||
}
|
||||
if (updatedDeps.length > 0) {
|
||||
console.log(`\nUpdated dependencies in ${cyan(FILENAME)}:`);
|
||||
updatedDeps.forEach((dep) => console.log(` ${dep}`));
|
||||
}
|
||||
if (addedDeps.length > 0 || updatedDeps.length > 0) {
|
||||
console.log(""); // Newline for spacing
|
||||
}
|
||||
const dependenciesString = dependencies.map((d) => d.name).join(", ");
|
||||
console.log(`\nAdded ${dependenciesString} to ${cyan(FILENAME)}\n`);
|
||||
} catch (error) {
|
||||
console.log(
|
||||
`Error while updating dependencies for Poetry project file ${FILENAME}\n`,
|
||||
@@ -400,16 +350,18 @@ export const addDependencies = async (
|
||||
}
|
||||
};
|
||||
|
||||
export const installPythonDependencies = () => {
|
||||
if (isUvAvailable()) {
|
||||
export const installPythonDependencies = (
|
||||
{ noRoot }: { noRoot: boolean } = { noRoot: false },
|
||||
) => {
|
||||
if (isPoetryAvailable()) {
|
||||
console.log(
|
||||
`Installing Python dependencies using uv. This may take a while...`,
|
||||
`Installing python dependencies using poetry. This may take a while...`,
|
||||
);
|
||||
const installSuccessful = tryUvSync();
|
||||
const installSuccessful = tryPoetryInstall(noRoot);
|
||||
if (!installSuccessful) {
|
||||
console.error(
|
||||
red(
|
||||
"Installing dependencies using uv failed. Please check the error log above and ensure uv is installed correctly.",
|
||||
"Installing dependencies using poetry failed. Please check error log above and try running create-llama again.",
|
||||
),
|
||||
);
|
||||
process.exit(1);
|
||||
@@ -417,34 +369,57 @@ export const installPythonDependencies = () => {
|
||||
} else {
|
||||
console.error(
|
||||
red(
|
||||
`uv is not available in the current environment. Please check ${terminalLink(
|
||||
"uv Installation",
|
||||
`https://github.com/astral-sh/uv#installation`,
|
||||
)} to install uv first, then run create-llama again.`,
|
||||
`Poetry is not available in the current environment. Please check ${terminalLink(
|
||||
"Poetry Installation",
|
||||
`https://python-poetry.org/docs/#installation`,
|
||||
)} to install poetry first, then run create-llama again.`,
|
||||
),
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
const installLegacyPythonTemplate = async ({
|
||||
export const installPythonTemplate = async ({
|
||||
appName,
|
||||
root,
|
||||
template,
|
||||
framework,
|
||||
vectorDb,
|
||||
postInstallAction,
|
||||
modelConfig,
|
||||
dataSources,
|
||||
tools,
|
||||
useLlamaParse,
|
||||
useCase,
|
||||
observability,
|
||||
}: Pick<
|
||||
InstallTemplateArgs,
|
||||
| "appName"
|
||||
| "root"
|
||||
| "template"
|
||||
| "framework"
|
||||
| "vectorDb"
|
||||
| "postInstallAction"
|
||||
| "modelConfig"
|
||||
| "dataSources"
|
||||
| "tools"
|
||||
| "useLlamaParse"
|
||||
| "useCase"
|
||||
| "observability"
|
||||
>) => {
|
||||
console.log("\nInitializing Python project with template:", template, "\n");
|
||||
let templatePath;
|
||||
if (template === "reflex") {
|
||||
templatePath = path.join(templatesDir, "types", "reflex");
|
||||
} else {
|
||||
templatePath = path.join(templatesDir, "types", "streaming", framework);
|
||||
}
|
||||
await copy("**", root, {
|
||||
parents: true,
|
||||
cwd: templatePath,
|
||||
rename: assetRelocator,
|
||||
});
|
||||
|
||||
const compPath = path.join(templatesDir, "components");
|
||||
const enginePath = path.join(root, "app", "engine");
|
||||
|
||||
@@ -534,7 +509,34 @@ const installLegacyPythonTemplate = async ({
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Adding additional dependencies");
|
||||
|
||||
const addOnDependencies = getAdditionalDependencies(
|
||||
modelConfig,
|
||||
vectorDb,
|
||||
dataSources,
|
||||
tools,
|
||||
template,
|
||||
);
|
||||
|
||||
if (observability && observability !== "none") {
|
||||
if (observability === "traceloop") {
|
||||
addOnDependencies.push({
|
||||
name: "traceloop-sdk",
|
||||
version: "^0.15.11",
|
||||
});
|
||||
}
|
||||
|
||||
if (observability === "llamatrace") {
|
||||
addOnDependencies.push({
|
||||
name: "llama-index-callbacks-arize-phoenix",
|
||||
version: "^0.3.0",
|
||||
constraints: {
|
||||
python: ">=3.11,<3.13",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const templateObservabilityPath = path.join(
|
||||
templatesDir,
|
||||
"components",
|
||||
@@ -546,133 +548,6 @@ const installLegacyPythonTemplate = async ({
|
||||
cwd: templateObservabilityPath,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const installLlamaIndexServerTemplate = async ({
|
||||
root,
|
||||
useCase,
|
||||
useLlamaParse,
|
||||
}: Pick<InstallTemplateArgs, "root" | "useCase" | "useLlamaParse">) => {
|
||||
if (!useCase) {
|
||||
console.log(
|
||||
red(
|
||||
`There is no use case selected. Please pick a use case to use via --use-case flag.`,
|
||||
),
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await copy("workflow.py", path.join(root, "app"), {
|
||||
parents: true,
|
||||
cwd: path.join(templatesDir, "components", "workflows", "python", useCase),
|
||||
});
|
||||
|
||||
// Copy custom UI component code
|
||||
await copy(`*`, path.join(root, "components"), {
|
||||
parents: true,
|
||||
cwd: path.join(templatesDir, "components", "ui", "workflows", useCase),
|
||||
});
|
||||
|
||||
if (useLlamaParse) {
|
||||
await copy("index.py", path.join(root, "app"), {
|
||||
parents: true,
|
||||
cwd: path.join(
|
||||
templatesDir,
|
||||
"components",
|
||||
"vectordbs",
|
||||
"llamaindexserver",
|
||||
"llamacloud",
|
||||
"python",
|
||||
),
|
||||
});
|
||||
// TODO: Consider moving generate.py to app folder.
|
||||
await copy("generate.py", path.join(root), {
|
||||
parents: true,
|
||||
cwd: path.join(
|
||||
templatesDir,
|
||||
"components",
|
||||
"vectordbs",
|
||||
"llamaindexserver",
|
||||
"llamacloud",
|
||||
"python",
|
||||
),
|
||||
});
|
||||
}
|
||||
// Copy README.md
|
||||
await copy("README-template.md", path.join(root), {
|
||||
parents: true,
|
||||
cwd: path.join(templatesDir, "components", "workflows", "python", useCase),
|
||||
rename: assetRelocator,
|
||||
});
|
||||
};
|
||||
|
||||
export const installPythonTemplate = async ({
|
||||
appName,
|
||||
root,
|
||||
template,
|
||||
framework,
|
||||
vectorDb,
|
||||
postInstallAction,
|
||||
modelConfig,
|
||||
dataSources,
|
||||
tools,
|
||||
useLlamaParse,
|
||||
useCase,
|
||||
observability,
|
||||
}: Pick<
|
||||
InstallTemplateArgs,
|
||||
| "appName"
|
||||
| "root"
|
||||
| "template"
|
||||
| "framework"
|
||||
| "vectorDb"
|
||||
| "postInstallAction"
|
||||
| "modelConfig"
|
||||
| "dataSources"
|
||||
| "tools"
|
||||
| "useLlamaParse"
|
||||
| "useCase"
|
||||
| "observability"
|
||||
>) => {
|
||||
console.log("\nInitializing Python project with template:", template, "\n");
|
||||
let templatePath;
|
||||
if (template === "reflex") {
|
||||
templatePath = path.join(templatesDir, "types", "reflex");
|
||||
} else {
|
||||
templatePath = path.join(templatesDir, "types", template, framework);
|
||||
}
|
||||
await copy("**", root, {
|
||||
parents: true,
|
||||
cwd: templatePath,
|
||||
rename: assetRelocator,
|
||||
});
|
||||
|
||||
if (template === "llamaindexserver") {
|
||||
await installLlamaIndexServerTemplate({
|
||||
root,
|
||||
useCase,
|
||||
useLlamaParse,
|
||||
});
|
||||
} else {
|
||||
await installLegacyPythonTemplate({
|
||||
root,
|
||||
template,
|
||||
vectorDb,
|
||||
dataSources,
|
||||
tools,
|
||||
useCase,
|
||||
observability,
|
||||
});
|
||||
}
|
||||
|
||||
console.log("Adding additional dependencies");
|
||||
const addOnDependencies = getAdditionalDependencies(
|
||||
modelConfig,
|
||||
vectorDb,
|
||||
dataSources,
|
||||
tools,
|
||||
template,
|
||||
);
|
||||
|
||||
await addDependencies(root, addOnDependencies);
|
||||
|
||||
@@ -34,24 +34,14 @@ export function runReflexApp(appPath: string, port: number) {
|
||||
"--frontend-port",
|
||||
port.toString(),
|
||||
];
|
||||
return createProcess("uv", commandArgs, {
|
||||
return createProcess("poetry", commandArgs, {
|
||||
stdio: "inherit",
|
||||
cwd: appPath,
|
||||
});
|
||||
}
|
||||
|
||||
export function runFastAPIApp(
|
||||
appPath: string,
|
||||
port: number,
|
||||
template: TemplateType,
|
||||
) {
|
||||
let commandArgs: string[];
|
||||
if (template === "streaming") {
|
||||
commandArgs = ["run", "dev"];
|
||||
} else {
|
||||
commandArgs = ["run", "fastapi", "dev", "--port", `${port}`];
|
||||
}
|
||||
return createProcess("uv", commandArgs, {
|
||||
export function runFastAPIApp(appPath: string, port: number) {
|
||||
return createProcess("poetry", ["run", "dev"], {
|
||||
stdio: "inherit",
|
||||
cwd: appPath,
|
||||
env: { ...process.env, APP_PORT: `${port}` },
|
||||
@@ -83,7 +73,7 @@ export async function runApp(
|
||||
: framework === "fastapi"
|
||||
? runFastAPIApp
|
||||
: runTSApp;
|
||||
await appRunner(appPath, port || defaultPort, template);
|
||||
await appRunner(appPath, port || defaultPort);
|
||||
} catch (error) {
|
||||
console.error("Failed to run app:", error);
|
||||
throw error;
|
||||
@@ -41,7 +41,7 @@ export const supportedTools: Tool[] = [
|
||||
dependencies: [
|
||||
{
|
||||
name: "llama-index-tools-google",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
version: "^0.3.0",
|
||||
},
|
||||
],
|
||||
supportedFrameworks: ["fastapi"],
|
||||
@@ -62,7 +62,7 @@ export const supportedTools: Tool[] = [
|
||||
dependencies: [
|
||||
{
|
||||
name: "duckduckgo-search",
|
||||
version: ">=6.3.5,<7.0.0",
|
||||
version: "^6.3.5",
|
||||
},
|
||||
],
|
||||
supportedFrameworks: ["fastapi"], // TODO: Re-enable this tool once the duck-duck-scrape TypeScript library works again
|
||||
@@ -82,7 +82,7 @@ For better results, you can specify the region parameter to get results from a s
|
||||
dependencies: [
|
||||
{
|
||||
name: "llama-index-tools-wikipedia",
|
||||
version: ">=0.3.0,<0.4.0",
|
||||
version: "^0.3.0",
|
||||
},
|
||||
],
|
||||
supportedFrameworks: ["fastapi", "express", "nextjs"],
|
||||
@@ -102,11 +102,11 @@ For better results, you can specify the region parameter to get results from a s
|
||||
dependencies: [
|
||||
{
|
||||
name: "xhtml2pdf",
|
||||
version: ">=0.2.14,<0.3.0",
|
||||
version: "^0.2.14",
|
||||
},
|
||||
{
|
||||
name: "markdown",
|
||||
version: ">=3.7.0,<4.0.0",
|
||||
version: "^3.7",
|
||||
},
|
||||
],
|
||||
type: ToolType.LOCAL,
|
||||
@@ -124,7 +124,7 @@ For better results, you can specify the region parameter to get results from a s
|
||||
dependencies: [
|
||||
{
|
||||
name: "e2b_code_interpreter",
|
||||
version: ">=1.1.1,<1.2.0",
|
||||
version: "1.0.3",
|
||||
},
|
||||
],
|
||||
supportedFrameworks: ["fastapi", "express", "nextjs"],
|
||||
@@ -155,7 +155,7 @@ For better results, you can specify the region parameter to get results from a s
|
||||
dependencies: [
|
||||
{
|
||||
name: "e2b_code_interpreter",
|
||||
version: ">=1.1.1,<1.2.0",
|
||||
version: "1.0.3",
|
||||
},
|
||||
],
|
||||
supportedFrameworks: ["fastapi", "express", "nextjs"],
|
||||
@@ -184,7 +184,7 @@ For better results, you can specify the region parameter to get results from a s
|
||||
},
|
||||
{
|
||||
name: "jsonschema",
|
||||
version: ">=4.22.0,<5.0.0",
|
||||
version: "^4.22.0",
|
||||
},
|
||||
{
|
||||
name: "llama-index-tools-requests",
|
||||
@@ -247,11 +247,11 @@ For better results, you can specify the region parameter to get results from a s
|
||||
dependencies: [
|
||||
{
|
||||
name: "pandas",
|
||||
version: ">=2.2.3,<3.0.0",
|
||||
version: "^2.2.3",
|
||||
},
|
||||
{
|
||||
name: "tabulate",
|
||||
version: ">=0.9.0,<1.0.0",
|
||||
version: "^0.9.0",
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -24,8 +24,7 @@ export type TemplateType =
|
||||
| "community"
|
||||
| "llamapack"
|
||||
| "multiagent"
|
||||
| "reflex"
|
||||
| "llamaindexserver";
|
||||
| "reflex";
|
||||
export type TemplateFramework = "nextjs" | "express" | "fastapi";
|
||||
export type TemplateUI = "html" | "shadcn";
|
||||
export type TemplateVectorDB =
|
||||
@@ -56,8 +55,7 @@ export type TemplateUseCase =
|
||||
| "deep_research"
|
||||
| "form_filling"
|
||||
| "extractor"
|
||||
| "contract_review"
|
||||
| "agentic_rag";
|
||||
| "contract_review";
|
||||
// Config for both file and folder
|
||||
export type FileSourceConfig =
|
||||
| {
|
||||
@@ -8,104 +8,42 @@ import { templatesDir } from "./dir";
|
||||
import { PackageManager } from "./get-pkg-manager";
|
||||
import { InstallTemplateArgs, ModelProvider, TemplateVectorDB } from "./types";
|
||||
|
||||
const installLlamaIndexServerTemplate = async ({
|
||||
root,
|
||||
useCase,
|
||||
vectorDb,
|
||||
}: Pick<InstallTemplateArgs, "root" | "useCase" | "vectorDb">) => {
|
||||
if (!useCase) {
|
||||
console.log(
|
||||
red(
|
||||
`There is no use case selected. Please pick a use case to use via --use-case flag.`,
|
||||
),
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!vectorDb) {
|
||||
console.log(
|
||||
red(
|
||||
`There is no vector db selected. Please pick a vector db to use via --vector-db flag.`,
|
||||
),
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await copy("workflow.ts", path.join(root, "src", "app"), {
|
||||
parents: true,
|
||||
cwd: path.join(
|
||||
templatesDir,
|
||||
"components",
|
||||
"workflows",
|
||||
"typescript",
|
||||
useCase,
|
||||
),
|
||||
});
|
||||
|
||||
// copy workflow UI components to output/components folder
|
||||
await copy("*", path.join(root, "components"), {
|
||||
parents: true,
|
||||
cwd: path.join(templatesDir, "components", "ui", "workflows", useCase),
|
||||
});
|
||||
|
||||
if (vectorDb === "llamacloud") {
|
||||
await copy("generate.ts", path.join(root, "src"), {
|
||||
parents: true,
|
||||
cwd: path.join(
|
||||
templatesDir,
|
||||
"components",
|
||||
"vectordbs",
|
||||
"llamaindexserver",
|
||||
"llamacloud",
|
||||
"typescript",
|
||||
),
|
||||
});
|
||||
|
||||
await copy("index.ts", path.join(root, "src", "app"), {
|
||||
parents: true,
|
||||
cwd: path.join(
|
||||
templatesDir,
|
||||
"components",
|
||||
"vectordbs",
|
||||
"llamaindexserver",
|
||||
"llamacloud",
|
||||
"typescript",
|
||||
),
|
||||
rename: () => "data.ts",
|
||||
});
|
||||
}
|
||||
// Copy README.md
|
||||
await copy("README-template.md", path.join(root), {
|
||||
parents: true,
|
||||
cwd: path.join(
|
||||
templatesDir,
|
||||
"components",
|
||||
"workflows",
|
||||
"typescript",
|
||||
useCase,
|
||||
),
|
||||
rename: assetRelocator,
|
||||
});
|
||||
};
|
||||
|
||||
const installLegacyTSTemplate = async ({
|
||||
/**
|
||||
* Install a LlamaIndex internal template to a given `root` directory.
|
||||
*/
|
||||
export const installTSTemplate = async ({
|
||||
appName,
|
||||
root,
|
||||
packageManager,
|
||||
isOnline,
|
||||
template,
|
||||
backend,
|
||||
framework,
|
||||
ui,
|
||||
vectorDb,
|
||||
postInstallAction,
|
||||
backend,
|
||||
observability,
|
||||
tools,
|
||||
dataSources,
|
||||
useLlamaParse,
|
||||
useCase,
|
||||
modelConfig,
|
||||
relativeEngineDestPath,
|
||||
}: InstallTemplateArgs & {
|
||||
backend: boolean;
|
||||
relativeEngineDestPath: string;
|
||||
}) => {
|
||||
}: InstallTemplateArgs & { backend: boolean }) => {
|
||||
console.log(bold(`Using ${packageManager}.`));
|
||||
|
||||
/**
|
||||
* Copy the template files to the target directory.
|
||||
*/
|
||||
console.log("\nInitializing project with template:", template, "\n");
|
||||
const templatePath = path.join(templatesDir, "types", "streaming", framework);
|
||||
const copySource = ["**"];
|
||||
|
||||
await copy(copySource, root, {
|
||||
parents: true,
|
||||
cwd: templatePath,
|
||||
rename: assetRelocator,
|
||||
});
|
||||
|
||||
/**
|
||||
* If next.js is used, update its configuration if necessary
|
||||
*/
|
||||
@@ -160,6 +98,10 @@ const installLegacyTSTemplate = async ({
|
||||
}
|
||||
|
||||
const compPath = path.join(templatesDir, "components");
|
||||
const relativeEngineDestPath =
|
||||
framework === "nextjs"
|
||||
? path.join("app", "api", "chat")
|
||||
: path.join("src", "controllers");
|
||||
const enginePath = path.join(root, relativeEngineDestPath, "engine");
|
||||
|
||||
// copy llamaindex code for TS templates
|
||||
@@ -294,75 +236,6 @@ const installLegacyTSTemplate = async ({
|
||||
await fs.rm(path.join(root, "app", "api"), { recursive: true });
|
||||
await fs.rm(path.join(root, "config"), { recursive: true, force: true });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Install a LlamaIndex internal template to a given `root` directory.
|
||||
*/
|
||||
export const installTSTemplate = async ({
|
||||
appName,
|
||||
root,
|
||||
packageManager,
|
||||
isOnline,
|
||||
template,
|
||||
framework,
|
||||
ui,
|
||||
vectorDb,
|
||||
postInstallAction,
|
||||
backend,
|
||||
observability,
|
||||
tools,
|
||||
dataSources,
|
||||
useLlamaParse,
|
||||
useCase,
|
||||
modelConfig,
|
||||
}: InstallTemplateArgs & { backend: boolean }) => {
|
||||
console.log(bold(`Using ${packageManager}.`));
|
||||
|
||||
/**
|
||||
* Copy the template files to the target directory.
|
||||
*/
|
||||
console.log("\nInitializing project with template:", template, "\n");
|
||||
const templatePath = path.join(templatesDir, "types", template, framework);
|
||||
const copySource = ["**"];
|
||||
|
||||
await copy(copySource, root, {
|
||||
parents: true,
|
||||
cwd: templatePath,
|
||||
rename: assetRelocator,
|
||||
});
|
||||
|
||||
const relativeEngineDestPath =
|
||||
framework === "nextjs"
|
||||
? path.join("app", "api", "chat")
|
||||
: path.join("src", "controllers");
|
||||
|
||||
if (template === "llamaindexserver") {
|
||||
await installLlamaIndexServerTemplate({
|
||||
root,
|
||||
useCase,
|
||||
vectorDb,
|
||||
});
|
||||
} else {
|
||||
await installLegacyTSTemplate({
|
||||
appName,
|
||||
root,
|
||||
packageManager,
|
||||
isOnline,
|
||||
template,
|
||||
backend,
|
||||
framework,
|
||||
ui,
|
||||
vectorDb,
|
||||
observability,
|
||||
tools,
|
||||
dataSources,
|
||||
useLlamaParse,
|
||||
useCase,
|
||||
modelConfig,
|
||||
relativeEngineDestPath,
|
||||
});
|
||||
}
|
||||
|
||||
const packageJson = await updatePackageJson({
|
||||
root,
|
||||
@@ -375,7 +248,6 @@ export const installTSTemplate = async ({
|
||||
vectorDb,
|
||||
backend,
|
||||
modelConfig,
|
||||
template,
|
||||
});
|
||||
|
||||
if (
|
||||
@@ -390,27 +262,27 @@ const providerDependencies: {
|
||||
[key in ModelProvider]?: Record<string, string>;
|
||||
} = {
|
||||
openai: {
|
||||
"@llamaindex/openai": "^0.2.0",
|
||||
"@llamaindex/openai": "^0.1.52",
|
||||
},
|
||||
gemini: {
|
||||
"@llamaindex/google": "^0.2.0",
|
||||
"@llamaindex/google": "^0.0.7",
|
||||
},
|
||||
ollama: {
|
||||
"@llamaindex/ollama": "^0.1.0",
|
||||
"@llamaindex/ollama": "^0.0.40",
|
||||
},
|
||||
mistral: {
|
||||
"@llamaindex/mistral": "^0.2.0",
|
||||
"@llamaindex/mistral": "^0.0.5",
|
||||
},
|
||||
"azure-openai": {
|
||||
"@llamaindex/openai": "^0.2.0",
|
||||
"@llamaindex/openai": "^0.1.52",
|
||||
},
|
||||
groq: {
|
||||
"@llamaindex/groq": "^0.0.61",
|
||||
"@llamaindex/huggingface": "^0.1.0", // groq uses huggingface as default embedding model
|
||||
"@llamaindex/groq": "^0.0.51",
|
||||
"@llamaindex/huggingface": "^0.0.36", // groq uses huggingface as default embedding model
|
||||
},
|
||||
anthropic: {
|
||||
"@llamaindex/anthropic": "^0.3.0",
|
||||
"@llamaindex/huggingface": "^0.1.0", // anthropic uses huggingface as default embedding model
|
||||
"@llamaindex/anthropic": "^0.1.0",
|
||||
"@llamaindex/huggingface": "^0.0.36", // anthropic uses huggingface as default embedding model
|
||||
},
|
||||
};
|
||||
|
||||
@@ -459,7 +331,6 @@ async function updatePackageJson({
|
||||
vectorDb,
|
||||
backend,
|
||||
modelConfig,
|
||||
template,
|
||||
}: Pick<
|
||||
InstallTemplateArgs,
|
||||
| "root"
|
||||
@@ -470,7 +341,6 @@ async function updatePackageJson({
|
||||
| "observability"
|
||||
| "vectorDb"
|
||||
| "modelConfig"
|
||||
| "template"
|
||||
> & {
|
||||
relativeEngineDestPath: string;
|
||||
backend: boolean;
|
||||
@@ -482,7 +352,7 @@ async function updatePackageJson({
|
||||
packageJson.name = appName;
|
||||
packageJson.version = "0.1.0";
|
||||
|
||||
if (relativeEngineDestPath && template !== "llamaindexserver") {
|
||||
if (relativeEngineDestPath) {
|
||||
// TODO: move script to {root}/scripts for all frameworks
|
||||
// add generate script if using context engine
|
||||
packageJson.scripts = {
|
||||
@@ -6,7 +6,7 @@ LlamaIndexServer is a FastAPI-based application that allows you to quickly launc
|
||||
|
||||
- Serving a workflow as a chatbot
|
||||
- Built on FastAPI for high performance and easy API development
|
||||
- Optional built-in chat UI with extendable UI components
|
||||
- Optional built-in chat UI
|
||||
- Prebuilt development code
|
||||
|
||||
## Installation
|
||||
@@ -43,10 +43,8 @@ def create_workflow() -> Workflow:
|
||||
app = LlamaIndexServer(
|
||||
workflow_factory=create_workflow, # Supports Workflow or AgentWorkflow
|
||||
env="dev", # Enable development mode
|
||||
ui_config={ # Configure the chat UI, optional
|
||||
"app_title": "Weather Bot",
|
||||
"starter_questions": ["What is the weather in LA?", "Will it rain in SF?"],
|
||||
},
|
||||
include_ui=True, # Include chat UI
|
||||
starter_questions=["What can you do?", "How do I use this?"],
|
||||
verbose=True
|
||||
)
|
||||
```
|
||||
@@ -76,16 +74,12 @@ The LlamaIndexServer accepts the following configuration parameters:
|
||||
- `logger`: Optional logger instance (defaults to uvicorn logger)
|
||||
- `use_default_routers`: Whether to include default routers (chat, static file serving)
|
||||
- `env`: Environment setting ('dev' enables CORS and UI by default)
|
||||
- `ui_config`: UI configuration as a dictionary or UIConfig object with options:
|
||||
- `enabled`: Whether to enable the chat UI (default: True)
|
||||
- `app_title`: The title of the chat application (default: "LlamaIndex Server")
|
||||
- `starter_questions`: List of starter questions for the chat UI (default: None)
|
||||
- `ui_path`: Path for downloaded UI static files (default: ".ui")
|
||||
- `component_dir`: The directory for custom UI components rendering events emitted by the workflow. The default is None, which does not render custom UI components.
|
||||
- `llamacloud_index_selector`: Whether to show the LlamaCloud index selector in the chat UI (default: False). Requires `LLAMA_CLOUD_API_KEY` to be set.
|
||||
- `include_ui`: Whether to include the chat UI
|
||||
- `starter_questions`: List of starter questions for the chat UI
|
||||
- `verbose`: Enable verbose logging
|
||||
- `api_prefix`: API route prefix (default: "/api")
|
||||
- `server_url`: The deployment URL of the server (default is None)
|
||||
- `ui_path`: Path for downloaded UI static files (default: ".ui")
|
||||
|
||||
## Default Routers and Features
|
||||
|
||||
@@ -107,11 +101,6 @@ When enabled, the server provides a chat interface at the root path (`/`) with:
|
||||
- Real-time chat interface
|
||||
- API endpoint integration
|
||||
|
||||
### Custom UI Components
|
||||
|
||||
You can add custom UI components for your workflow by providing `component_dir` config and adding custom .jsx or .tsx files to the directory.
|
||||
See [Custom UI Components](https://github.com/run-llama/create-llama/blob/main/llama-index-server/docs/custom_ui_component.md) for more details.
|
||||
|
||||
## Development Mode
|
||||
|
||||
In development mode (`env="dev"`), the server:
|
||||
@@ -0,0 +1,3 @@
|
||||
from .server import LlamaIndexServer
|
||||
|
||||
__all__ = ["LlamaIndexServer"]
|
||||
-17
@@ -134,20 +134,3 @@ class SourceNodes(BaseModel):
|
||||
cls, source_nodes: List[NodeWithScore]
|
||||
) -> List["SourceNodes"]:
|
||||
return [cls.from_source_node(node) for node in source_nodes]
|
||||
|
||||
|
||||
class ComponentDefinition(BaseModel):
|
||||
type: str
|
||||
code: str
|
||||
filename: str
|
||||
|
||||
|
||||
class UIEvent(Event):
|
||||
type: str
|
||||
data: BaseModel
|
||||
|
||||
def to_response(self) -> dict:
|
||||
return {
|
||||
"type": self.type,
|
||||
"data": self.data.model_dump(),
|
||||
}
|
||||
+1
-5
@@ -6,7 +6,6 @@ from typing import AsyncGenerator, Callable, Union
|
||||
|
||||
from fastapi import APIRouter, BackgroundTasks, HTTPException
|
||||
from fastapi.responses import StreamingResponse
|
||||
|
||||
from llama_index.core.agent.workflow.workflow_events import AgentStream
|
||||
from llama_index.core.workflow import StopEvent, Workflow
|
||||
from llama_index.server.api.callbacks import (
|
||||
@@ -100,10 +99,7 @@ async def _stream_content(
|
||||
event: Union[AgentStream, StopEvent],
|
||||
) -> AsyncGenerator[str, None]:
|
||||
if isinstance(event, AgentStream):
|
||||
# Normally, if the stream is a tool call, the delta is always empty
|
||||
# so it's not a text stream.
|
||||
if len(event.tool_calls) == 0:
|
||||
yield event.delta
|
||||
yield event.delta
|
||||
elif isinstance(event, StopEvent):
|
||||
if isinstance(event.result, str):
|
||||
yield event.result
|
||||
+1
-1
@@ -5,7 +5,7 @@ from typing import Optional
|
||||
|
||||
import requests
|
||||
|
||||
CHAT_UI_VERSION = "0.1.5"
|
||||
CHAT_UI_VERSION = "0.0.6"
|
||||
|
||||
|
||||
def download_chat_ui(
|
||||
+36
-82
@@ -1,58 +1,23 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from typing import Any, Callable, Optional, Union
|
||||
from typing import Any, Callable, Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from llama_index.core.workflow import Workflow
|
||||
from llama_index.server.api.routers import chat_router, custom_components_router
|
||||
from llama_index.server.api.routers.chat import chat_router
|
||||
from llama_index.server.chat_ui import download_chat_ui
|
||||
from llama_index.server.settings import server_settings
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class UIConfig(BaseModel):
|
||||
enabled: bool = Field(default=True, description="Whether to enable the chat UI")
|
||||
app_title: str = Field(
|
||||
default="LlamaIndex Server", description="The title of the chat UI"
|
||||
)
|
||||
starter_questions: Optional[list[str]] = Field(
|
||||
default=None, description="The starter questions for the chat UI"
|
||||
)
|
||||
llamacloud_index_selector: bool = Field(
|
||||
default=False,
|
||||
description="Whether to show the LlamaCloud index selector in the chat UI (need to set the LLAMA_CLOUD_API_KEY environment variable)",
|
||||
)
|
||||
ui_path: str = Field(
|
||||
default=".ui", description="The path that stores static files for the chat UI"
|
||||
)
|
||||
component_dir: Optional[str] = Field(
|
||||
default=None, description="The directory to custom UI components code"
|
||||
)
|
||||
|
||||
def get_config_content(self) -> str:
|
||||
return json.dumps(
|
||||
{
|
||||
"CHAT_API": f"{server_settings.api_url}/chat",
|
||||
"STARTER_QUESTIONS": self.starter_questions or [],
|
||||
"LLAMA_CLOUD_API": f"{server_settings.api_url}/chat/config/llamacloud"
|
||||
if self.llamacloud_index_selector and os.getenv("LLAMA_CLOUD_API_KEY")
|
||||
else None,
|
||||
"APP_TITLE": self.app_title,
|
||||
"COMPONENTS_API": f"{server_settings.api_url}/components"
|
||||
if self.component_dir
|
||||
else None,
|
||||
},
|
||||
indent=2,
|
||||
)
|
||||
|
||||
|
||||
class LlamaIndexServer(FastAPI):
|
||||
workflow_factory: Callable[..., Workflow]
|
||||
include_ui: Optional[bool]
|
||||
starter_questions: Optional[list[str]]
|
||||
verbose: bool = False
|
||||
ui_config: UIConfig
|
||||
ui_path: str = ".ui"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -60,7 +25,8 @@ class LlamaIndexServer(FastAPI):
|
||||
logger: Optional[logging.Logger] = None,
|
||||
use_default_routers: Optional[bool] = True,
|
||||
env: Optional[str] = None,
|
||||
ui_config: Optional[Union[UIConfig, dict]] = None,
|
||||
include_ui: Optional[bool] = None,
|
||||
starter_questions: Optional[list[str]] = None,
|
||||
server_url: Optional[str] = None,
|
||||
api_prefix: Optional[str] = None,
|
||||
verbose: bool = False,
|
||||
@@ -75,7 +41,8 @@ class LlamaIndexServer(FastAPI):
|
||||
logger: The logger to use.
|
||||
use_default_routers: Whether to use the default routers (chat, mount `data` and `output` directories).
|
||||
env: The environment to run the server in.
|
||||
ui_config: The configuration for the chat UI.
|
||||
include_ui: Whether to show an chat UI in the root path.
|
||||
starter_questions: A list of starter questions to display in the chat UI.
|
||||
server_url: The URL of the server.
|
||||
api_prefix: The prefix for the API endpoints.
|
||||
verbose: Whether to show verbose logs.
|
||||
@@ -85,13 +52,9 @@ class LlamaIndexServer(FastAPI):
|
||||
self.workflow_factory = workflow_factory
|
||||
self.logger = logger or logging.getLogger("uvicorn")
|
||||
self.verbose = verbose
|
||||
self.include_ui = include_ui # Store the explicitly passed value first
|
||||
self.starter_questions = starter_questions
|
||||
self.use_default_routers = use_default_routers or True
|
||||
if ui_config is None:
|
||||
self.ui_config = UIConfig()
|
||||
elif isinstance(ui_config, dict):
|
||||
self.ui_config = UIConfig(**ui_config)
|
||||
else:
|
||||
self.ui_config = ui_config
|
||||
|
||||
# Update the settings
|
||||
if server_url:
|
||||
@@ -104,15 +67,27 @@ class LlamaIndexServer(FastAPI):
|
||||
|
||||
if str(env).lower() == "dev":
|
||||
self.allow_cors("*")
|
||||
if self.ui_config.enabled is None:
|
||||
self.ui_config.enabled = True
|
||||
if self.include_ui is None:
|
||||
self.include_ui = True
|
||||
if self.include_ui is None:
|
||||
self.include_ui = False
|
||||
|
||||
if self.ui_config.enabled is None:
|
||||
self.ui_config.enabled = False
|
||||
|
||||
if self.ui_config.enabled:
|
||||
if self.include_ui:
|
||||
self.mount_ui()
|
||||
|
||||
@property
|
||||
def _ui_config(self) -> dict:
|
||||
config = {
|
||||
"CHAT_API": f"{server_settings.api_url}/chat",
|
||||
"STARTER_QUESTIONS": self.starter_questions,
|
||||
}
|
||||
is_llamacloud_configured = os.getenv("LLAMA_CLOUD_API_KEY") is not None
|
||||
if is_llamacloud_configured:
|
||||
config["LLAMA_CLOUD_API"] = (
|
||||
f"{server_settings.api_url}/chat/config/llamacloud"
|
||||
)
|
||||
return config
|
||||
|
||||
# Default routers
|
||||
def add_default_routers(self) -> None:
|
||||
self.add_chat_router()
|
||||
@@ -131,39 +106,18 @@ class LlamaIndexServer(FastAPI):
|
||||
prefix=server_settings.api_prefix,
|
||||
)
|
||||
|
||||
def add_components_router(self) -> None:
|
||||
"""
|
||||
Add the UI router.
|
||||
"""
|
||||
if self.ui_config.component_dir is None:
|
||||
raise ValueError("component_dir must be specified to add components router")
|
||||
|
||||
self.include_router(
|
||||
custom_components_router(self.ui_config.component_dir, self.logger),
|
||||
prefix=server_settings.api_prefix,
|
||||
)
|
||||
|
||||
def mount_ui(self) -> None:
|
||||
"""
|
||||
Mount the UI.
|
||||
"""
|
||||
# Check if the static folder exists
|
||||
if self.ui_config.enabled:
|
||||
# Component dir
|
||||
if self.ui_config.component_dir:
|
||||
if not os.path.exists(self.ui_config.component_dir):
|
||||
os.makedirs(self.ui_config.component_dir)
|
||||
self.add_components_router()
|
||||
# UI static files
|
||||
if not os.path.exists(self.ui_config.ui_path):
|
||||
os.makedirs(self.ui_config.ui_path)
|
||||
if self.include_ui:
|
||||
if not os.path.exists(self.ui_path):
|
||||
self.logger.warning(
|
||||
f"UI files not found, downloading UI to {self.ui_config.ui_path}"
|
||||
f"UI files not found, downloading UI to {self.ui_path}"
|
||||
)
|
||||
download_chat_ui(logger=self.logger, target_path=self.ui_config.ui_path)
|
||||
self._mount_static_files(
|
||||
directory=self.ui_config.ui_path, path="/", html=True
|
||||
)
|
||||
download_chat_ui(logger=self.logger, target_path=self.ui_path)
|
||||
self._mount_static_files(directory=self.ui_path, path="/", html=True)
|
||||
self._override_ui_config()
|
||||
|
||||
def _override_ui_config(self) -> None:
|
||||
@@ -171,12 +125,12 @@ class LlamaIndexServer(FastAPI):
|
||||
Override the UI config by writing a complete configuration file.
|
||||
"""
|
||||
try:
|
||||
config_path = os.path.join(self.ui_config.ui_path, "config.js")
|
||||
config_path = os.path.join(self.ui_path, "config.js")
|
||||
if not os.path.exists(config_path):
|
||||
self.logger.error("Config file not found")
|
||||
return
|
||||
config_content = (
|
||||
f"window.LLAMAINDEX = {self.ui_config.get_config_content()};"
|
||||
f"window.LLAMAINDEX = {json.dumps(self._ui_config, indent=2)};"
|
||||
)
|
||||
with open(config_path, "w") as f:
|
||||
f.write(config_content)
|
||||
+1
-2
@@ -149,8 +149,7 @@ def _create_index(
|
||||
"type": "OPENAI_EMBEDDING",
|
||||
"component": {
|
||||
"api_key": os.getenv("OPENAI_API_KEY"), # editable
|
||||
"model_name": Settings.embed_model.model_name
|
||||
or "text-embedding-3-small",
|
||||
"model_name": os.getenv("EMBEDDING_MODEL"),
|
||||
},
|
||||
},
|
||||
"transform_config": {
|
||||
+750
-815
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,7 @@ license = "MIT"
|
||||
name = "llama-index-server"
|
||||
packages = [{include = "llama_index/"}]
|
||||
readme = "README.md"
|
||||
version = "0.1.14"
|
||||
version = "0.1.6"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.9,<4.0"
|
||||
@@ -34,7 +34,7 @@ fastapi = {extras = ["standard"], version = "^0.115.11"}
|
||||
cachetools = "^5.5.2"
|
||||
requests = "^2.32.3"
|
||||
pydantic-settings = "^2.8.1"
|
||||
llama-index-core = "^0.12.28"
|
||||
llama-index-core = "0.12.25"
|
||||
llama-index-readers-file = "^0.4.6"
|
||||
llama-index-indices-managed-llama-cloud = "0.6.3"
|
||||
|
||||
@@ -62,4 +62,3 @@ types-setuptools = "67.1.0.0"
|
||||
xhtml2pdf = "^0.2.17"
|
||||
pytest-cov = "^6.0.0"
|
||||
llama-cloud = "^0.1.17"
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
import pytest
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
|
||||
from llama_index.core.agent.workflow import AgentWorkflow
|
||||
from llama_index.core.llms import MockLLM
|
||||
from llama_index.server import LlamaIndexServer
|
||||
|
||||
|
||||
def fetch_weather(city: str) -> str:
|
||||
"""Fetch the weather for a given city."""
|
||||
return f"The weather in {city} is sunny."
|
||||
|
||||
|
||||
def _agent_workflow() -> AgentWorkflow:
|
||||
# Use MockLLM instead of default OpenAI
|
||||
mock_llm = MockLLM()
|
||||
return AgentWorkflow.from_tools_or_functions(
|
||||
tools_or_functions=[fetch_weather],
|
||||
verbose=True,
|
||||
llm=mock_llm,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def server() -> LlamaIndexServer:
|
||||
"""Fixture to create a LlamaIndexServer instance."""
|
||||
return LlamaIndexServer(
|
||||
workflow_factory=_agent_workflow,
|
||||
verbose=True,
|
||||
use_default_routers=True,
|
||||
mount_ui=False,
|
||||
env="dev",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio()
|
||||
async def test_server_has_chat_route(server: LlamaIndexServer) -> None:
|
||||
"""Test that the server has the chat API route."""
|
||||
chat_route_exists = any(route.path == "/api/chat" for route in server.routes)
|
||||
assert chat_route_exists, "Chat API route not found in server routes"
|
||||
|
||||
|
||||
@pytest.mark.asyncio()
|
||||
async def test_server_swagger_docs(server: LlamaIndexServer) -> None:
|
||||
"""Test that the server serves Swagger UI docs."""
|
||||
async with AsyncClient(
|
||||
transport=ASGITransport(app=server), base_url="http://test"
|
||||
) as ac:
|
||||
response = await ac.get("/docs")
|
||||
assert response.status_code == 200
|
||||
assert "text/html" in response.headers["content-type"]
|
||||
assert "Swagger UI" in response.text
|
||||
|
||||
|
||||
@pytest.mark.asyncio()
|
||||
async def test_ui_is_downloaded(server: LlamaIndexServer) -> None:
|
||||
"""
|
||||
Test if the UI is downloaded and mounted correctly.
|
||||
"""
|
||||
import os
|
||||
import shutil
|
||||
|
||||
# Clean up any existing static directory first
|
||||
if os.path.exists(".ui"):
|
||||
shutil.rmtree(".ui")
|
||||
|
||||
# Create a new server with UI enabled
|
||||
ui_server = LlamaIndexServer(
|
||||
workflow_factory=_agent_workflow,
|
||||
verbose=True,
|
||||
use_default_routers=True,
|
||||
env="dev",
|
||||
include_ui=True,
|
||||
)
|
||||
|
||||
# Verify that static directory was created with index.html
|
||||
assert os.path.exists("./.ui"), "Static directory was not created"
|
||||
assert os.path.isdir("./.ui"), "Static path is not a directory"
|
||||
assert os.path.exists("./.ui/index.html"), "index.html was not downloaded"
|
||||
|
||||
# Check if the UI is mounted and accessible
|
||||
async with AsyncClient(
|
||||
transport=ASGITransport(app=ui_server), base_url="http://test"
|
||||
) as ac:
|
||||
response = await ac.get("/")
|
||||
assert response.status_code == 200
|
||||
assert "text/html" in response.headers["content-type"]
|
||||
|
||||
# Clean up after test
|
||||
shutil.rmtree("./.ui")
|
||||
|
||||
|
||||
@pytest.mark.asyncio()
|
||||
async def test_ui_is_accessible(server: LlamaIndexServer) -> None:
|
||||
"""
|
||||
Test if the UI is accessible.
|
||||
"""
|
||||
# Manually trigger UI mounting
|
||||
server.mount_ui()
|
||||
|
||||
async with AsyncClient(
|
||||
transport=ASGITransport(app=server), base_url="http://test"
|
||||
) as ac:
|
||||
response = await ac.get("/")
|
||||
assert response.status_code == 200
|
||||
assert "text/html" in response.headers["content-type"]
|
||||
+84
-37
@@ -1,39 +1,86 @@
|
||||
{
|
||||
"name": "create-llama-monorepo",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Monorepo for create-llama",
|
||||
"keywords": [
|
||||
"rag",
|
||||
"llamaindex"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/run-llama/create-llama"
|
||||
},
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"scripts": {
|
||||
"prepare": "husky",
|
||||
"new-snapshot": "pnpm -r build && changeset version --snapshot",
|
||||
"new-version": "pnpm -r build && changeset version",
|
||||
"release": "pnpm -r build && changeset publish",
|
||||
"release-snapshot": "pnpm -r build && changeset publish --tag snapshot",
|
||||
"build": "pnpm -r build",
|
||||
"e2e": "pnpm -r e2e",
|
||||
"dev": "pnpm -r dev",
|
||||
"format": "pnpm -r format",
|
||||
"format:write": "pnpm -r format:write",
|
||||
"lint": "pnpm -r lint"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.27.1",
|
||||
"husky": "^9.0.10"
|
||||
},
|
||||
"packageManager": "pnpm@9.0.5",
|
||||
"engines": {
|
||||
"node": ">=16.14.0"
|
||||
}
|
||||
"name": "create-llama",
|
||||
"version": "0.4.0",
|
||||
"description": "Create LlamaIndex-powered apps with one command",
|
||||
"keywords": [
|
||||
"rag",
|
||||
"llamaindex",
|
||||
"next.js"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/run-llama/create-llama",
|
||||
"directory": "packages/create-llama"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"create-llama": "./dist/index.js"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "bash ./scripts/build.sh",
|
||||
"build:ncc": "pnpm run clean && ncc build ./index.ts -o ./dist/ --minify --no-cache --no-source-map-register",
|
||||
"clean": "rimraf --glob ./dist ./templates/**/__pycache__ ./templates/**/node_modules ./templates/**/poetry.lock",
|
||||
"dev": "ncc build ./index.ts -w -o dist/",
|
||||
"e2e": "playwright test",
|
||||
"e2e:python": "playwright test e2e/shared e2e/python",
|
||||
"e2e:typescript": "playwright test e2e/shared e2e/typescript",
|
||||
"format": "prettier --ignore-unknown --cache --check .",
|
||||
"format:write": "prettier --ignore-unknown --write .",
|
||||
"lint": "eslint . --ignore-pattern dist --ignore-pattern e2e/cache",
|
||||
"new-snapshot": "pnpm run build && changeset version --snapshot",
|
||||
"new-version": "pnpm run build && changeset version",
|
||||
"pack-install": "bash ./scripts/pack.sh",
|
||||
"prepare": "husky",
|
||||
"release": "pnpm run build && changeset publish",
|
||||
"release-snapshot": "pnpm run build && changeset publish --tag snapshot"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/async-retry": "1.4.2",
|
||||
"@types/ci-info": "2.0.0",
|
||||
"@types/cross-spawn": "6.0.0",
|
||||
"@types/fs-extra": "11.0.4",
|
||||
"@types/node": "^20.11.7",
|
||||
"@types/prompts": "2.4.2",
|
||||
"@types/tar": "6.1.5",
|
||||
"@types/validate-npm-package-name": "3.0.0",
|
||||
"async-retry": "1.3.1",
|
||||
"async-sema": "3.0.1",
|
||||
"ci-info": "github:watson/ci-info#f43f6a1cefff47fb361c88cf4b943fdbcaafe540",
|
||||
"commander": "12.1.0",
|
||||
"cross-spawn": "7.0.3",
|
||||
"fast-glob": "3.3.1",
|
||||
"fs-extra": "11.2.0",
|
||||
"global-agent": "^3.0.0",
|
||||
"got": "10.7.0",
|
||||
"ollama": "^0.5.0",
|
||||
"ora": "^8.0.1",
|
||||
"picocolors": "1.0.0",
|
||||
"prompts": "2.4.2",
|
||||
"smol-toml": "^1.1.4",
|
||||
"tar": "6.1.15",
|
||||
"terminal-link": "^3.0.0",
|
||||
"update-check": "1.5.4",
|
||||
"validate-npm-package-name": "3.0.0",
|
||||
"yaml": "2.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.27.1",
|
||||
"@playwright/test": "^1.41.1",
|
||||
"@vercel/ncc": "0.38.1",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^8.10.0",
|
||||
"husky": "^9.0.10",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-organize-imports": "^3.2.4",
|
||||
"rimraf": "^5.0.5",
|
||||
"typescript": "^5.3.3",
|
||||
"wait-port": "^1.1.0"
|
||||
},
|
||||
"packageManager": "pnpm@9.0.5",
|
||||
"engines": {
|
||||
"node": ">=16.14.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
.pnp
|
||||
.pnpm-store
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
coverage
|
||||
.coverage
|
||||
|
||||
# next.js
|
||||
.next/
|
||||
out/
|
||||
build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# build
|
||||
dist/
|
||||
lib/
|
||||
|
||||
# e2e
|
||||
.cache
|
||||
test-results/
|
||||
playwright-report/
|
||||
blob-report/
|
||||
playwright/.cache/
|
||||
.tsbuildinfo
|
||||
e2e/cache
|
||||
|
||||
# intellij
|
||||
**/.idea
|
||||
|
||||
# Python
|
||||
.mypy_cache/
|
||||
venv/
|
||||
.venv/
|
||||
dist/
|
||||
.__pycache__
|
||||
__pycache__
|
||||
.python-version
|
||||
.ui
|
||||
|
||||
# build artifacts
|
||||
create-llama-*.tgz
|
||||
|
||||
# copied from root
|
||||
README.md
|
||||
LICENSE.md
|
||||
@@ -1,42 +0,0 @@
|
||||
// Migrate poetry to uv
|
||||
import { execSync } from "child_process";
|
||||
import fs from "fs";
|
||||
import { red } from "picocolors";
|
||||
|
||||
export function isUvAvailable(): boolean {
|
||||
try {
|
||||
execSync("uv --version", { stdio: "ignore" });
|
||||
return true;
|
||||
} catch (_) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function tryUvSync(): boolean {
|
||||
try {
|
||||
console.log("Syncing environment with pyproject.toml...");
|
||||
execSync(`uv sync`, {
|
||||
stdio: "inherit",
|
||||
});
|
||||
return true;
|
||||
} catch (_) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function tryUvRun(command: string): boolean {
|
||||
try {
|
||||
// Use uv run <command>
|
||||
execSync(`uv run ${command}`, { stdio: "inherit" });
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(red(`Failed to run ${command}. Error: ${error}`));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function isHavingUvLockFile(): boolean {
|
||||
try {
|
||||
// Check if uv.lock exists in the current directory
|
||||
return fs.existsSync("uv.lock");
|
||||
} catch (_) {}
|
||||
return false;
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
{
|
||||
"name": "create-llama",
|
||||
"version": "0.5.11",
|
||||
"description": "Create LlamaIndex-powered apps with one command",
|
||||
"keywords": [
|
||||
"rag",
|
||||
"llamaindex",
|
||||
"next.js"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/run-llama/create-llama",
|
||||
"directory": "packages/create-llama"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"create-llama": "./dist/index.js"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md",
|
||||
"LICENSE.md"
|
||||
],
|
||||
"scripts": {
|
||||
"copy": "cp -r ../../README.md ../../LICENSE.md .",
|
||||
"build": "bash ./scripts/build.sh",
|
||||
"build:ncc": "pnpm run clean && ncc build ./index.ts -o ./dist/ --minify --no-cache --no-source-map-register",
|
||||
"postbuild": "pnpm run copy",
|
||||
"clean": "rimraf --glob ./dist ./templates/**/__pycache__ ./templates/**/node_modules ./templates/**/poetry.lock",
|
||||
"dev": "ncc build ./index.ts -w -o dist/",
|
||||
"e2e": "playwright test",
|
||||
"e2e:python": "playwright test e2e/shared e2e/python",
|
||||
"e2e:typescript": "playwright test e2e/shared e2e/typescript",
|
||||
"format": "prettier --ignore-unknown --cache --check .",
|
||||
"format:write": "prettier --ignore-unknown --write .",
|
||||
"lint": "eslint . --ignore-pattern dist --ignore-pattern e2e/cache",
|
||||
"pack-install": "bash ./scripts/pack.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/async-retry": "1.4.2",
|
||||
"@types/ci-info": "2.0.0",
|
||||
"@types/cross-spawn": "6.0.0",
|
||||
"@types/fs-extra": "11.0.4",
|
||||
"@types/node": "^20.11.7",
|
||||
"@types/prompts": "2.4.2",
|
||||
"@types/tar": "6.1.5",
|
||||
"@types/validate-npm-package-name": "3.0.0",
|
||||
"async-retry": "1.3.1",
|
||||
"async-sema": "3.0.1",
|
||||
"ci-info": "github:watson/ci-info#f43f6a1cefff47fb361c88cf4b943fdbcaafe540",
|
||||
"commander": "12.1.0",
|
||||
"cross-spawn": "7.0.3",
|
||||
"fast-glob": "3.3.1",
|
||||
"fs-extra": "11.2.0",
|
||||
"global-agent": "^3.0.0",
|
||||
"got": "10.7.0",
|
||||
"ollama": "^0.5.0",
|
||||
"ora": "^8.0.1",
|
||||
"picocolors": "1.0.0",
|
||||
"prompts": "2.4.2",
|
||||
"smol-toml": "^1.1.4",
|
||||
"tar": "6.1.15",
|
||||
"terminal-link": "^3.0.0",
|
||||
"update-check": "1.5.4",
|
||||
"validate-npm-package-name": "3.0.0",
|
||||
"yaml": "2.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^8.10.0",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-organize-imports": "^3.2.4",
|
||||
"@playwright/test": "^1.41.1",
|
||||
"@vercel/ncc": "0.38.1",
|
||||
"rimraf": "^5.0.5",
|
||||
"typescript": "^5.3.3",
|
||||
"wait-port": "^1.1.0"
|
||||
},
|
||||
"packageManager": "pnpm@9.0.5",
|
||||
"engines": {
|
||||
"node": ">=16.14.0"
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
[project]
|
||||
name = "app"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = [ { name = "Marcus Schiesser", email = "mail@marcusschiesser.de" } ]
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11,<4.0"
|
||||
dependencies = [
|
||||
"fastapi>=0.109.1",
|
||||
"python-dotenv>=1.0.0",
|
||||
"pydantic<2.10",
|
||||
"llama-index>=0.12.1",
|
||||
"cachetools>=5.3.3",
|
||||
"reflex>=0.6.2.post1",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
generate = "app.engine.generate:generate_datasource"
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"mypy>=1.8.0",
|
||||
"pytest>=8.3.5",
|
||||
"pytest-asyncio>=0.25.3",
|
||||
"docx2txt>=0.8",
|
||||
"llama-index-llms-openai>=0.3.2",
|
||||
"llama-index-embeddings-openai>=0.3.1",
|
||||
"llama-index-agent-openai>=0.4.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = [ "hatchling>=1.24" ]
|
||||
build-backend = "hatchling.build"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user