mirror of
https://github.com/run-llama/create-llama.git
synced 2026-07-19 23:13:36 -04:00
Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bbae802bed | |||
| 25fba4381b | |||
| d0618fa2fa | |||
| f3fe3ffc9b | |||
| 6f75d4ab6e | |||
| 3242738fe4 | |||
| 17538eb0dd | |||
| d3772cb4a2 | |||
| 527075c086 | |||
| fb7d4da149 | |||
| 5c35b194bb | |||
| 85e5e7e662 | |||
| 58362542c0 | |||
| 6f44185f68 | |||
| afe9e9fc16 | |||
| 1b5a519f13 | |||
| f072308d03 | |||
| 1df8cfbdc2 | |||
| 24515393a6 | |||
| b3eb0ba7d4 | |||
| 556f33c0ab | |||
| 7a70390b00 | |||
| ad5912b41f | |||
| 76502d28e7 | |||
| f4ca602da5 | |||
| d304554f33 | |||
| 8dce9f913d | |||
| c62096c516 | |||
| 0384268543 | |||
| d9f9e3c1c3 | |||
| 1357c423a3 | |||
| 8105aa70b6 | |||
| 23a90625d1 | |||
| ac789bcb8d | |||
| 241d82a87d | |||
| b16cfd873b | |||
| 3130cdf18d | |||
| 7711216134 | |||
| 93d601972e | |||
| 8fe5fc24c1 | |||
| 3960618454 | |||
| 53e1cd56e7 | |||
| 0a2e12a2bb | |||
| 2e536dca36 | |||
| 4bc53ac24e | |||
| 2deb63a6cc | |||
| 2ffa057f77 | |||
| 64f151dd66 | |||
| 765181adb0 | |||
| 95c35e8a5c | |||
| 598865768a | |||
| 05453d55bf | |||
| d363ced4d8 | |||
| 293c6f97c1 | |||
| 44b4d89ac1 | |||
| 60f10c5b5d | |||
| ee85320701 | |||
| b12dc6f1e8 | |||
| 7c3b279417 | |||
| 1514a555d5 | |||
| cddb4f6bcc | |||
| c82e4f5791 | |||
| 1f7e0e3c69 | |||
| 7997cdeb70 | |||
| 76ec3605e5 | |||
| 5cfdec7d75 | |||
| 3d1b15d515 | |||
| 392393af9e | |||
| 920beda8ad | |||
| e6f8add778 | |||
| c9f8f8d5f2 | |||
| 24eb7736ee | |||
| 5fb27220f7 | |||
| 5caa3813f8 | |||
| bc95789a8d | |||
| 08b3e079e4 | |||
| 1876950f89 | |||
| c7349b44c4 | |||
| 4068618b2d | |||
| 54c9e2f95e | |||
| aec1173b71 | |||
| 481663dd63 | |||
| 1ca7dd2e48 | |||
| 3d20990713 | |||
| 8fb69cf807 | |||
| 61af56dac6 | |||
| 4b66039a96 | |||
| ee88f681a6 | |||
| 992c3a95e9 | |||
| 2a4fb702d1 | |||
| 24b9337096 | |||
| fceec69a3a | |||
| 03e5e0a16e | |||
| fe3cd36d3a | |||
| d5d10e9ead | |||
| 5ed925d75f | |||
| ca5df14d41 | |||
| ee69ce7cc1 | |||
| 0e4ecfaf8b |
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": [
|
|
||||||
"prettier"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"max-params": [
|
|
||||||
"error",
|
|
||||||
4
|
|
||||||
],
|
|
||||||
"prefer-const": "error",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
+51
-26
@@ -1,12 +1,15 @@
|
|||||||
name: E2E Tests
|
name: E2E Tests for create-llama package
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
paths-ignore:
|
||||||
|
- "python/llama-index-server/**"
|
||||||
|
- ".github/workflows/*llama_index_server.yml"
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
paths-ignore:
|
||||||
env:
|
- "python/llama-index-server/**"
|
||||||
POETRY_VERSION: "1.6.1"
|
- ".github/workflows/*llama_index_server.yml"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
e2e-python:
|
e2e-python:
|
||||||
@@ -20,6 +23,7 @@ jobs:
|
|||||||
os: [macos-latest, windows-latest, ubuntu-22.04]
|
os: [macos-latest, windows-latest, ubuntu-22.04]
|
||||||
frameworks: ["fastapi"]
|
frameworks: ["fastapi"]
|
||||||
datasources: ["--no-files", "--example-file", "--llamacloud"]
|
datasources: ["--no-files", "--example-file", "--llamacloud"]
|
||||||
|
template-types: ["streaming", "llamaindexserver"]
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -32,10 +36,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
- name: Install Poetry
|
- name: Install uv
|
||||||
uses: snok/install-poetry@v1
|
run: curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||||
with:
|
- name: Add uv to PATH # Ensure uv is available in subsequent steps
|
||||||
version: ${{ env.POETRY_VERSION }}
|
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v3
|
- uses: pnpm/action-setup@v3
|
||||||
|
|
||||||
@@ -50,15 +54,15 @@ jobs:
|
|||||||
|
|
||||||
- name: Install Playwright Browsers
|
- name: Install Playwright Browsers
|
||||||
run: pnpm exec playwright install --with-deps
|
run: pnpm exec playwright install --with-deps
|
||||||
working-directory: .
|
working-directory: packages/create-llama
|
||||||
|
|
||||||
- name: Build create-llama
|
- name: Build create-llama
|
||||||
run: pnpm run build
|
run: pnpm run build
|
||||||
working-directory: .
|
working-directory: packages/create-llama
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: pnpm run pack-install
|
run: pnpm run pack-install
|
||||||
working-directory: .
|
working-directory: packages/create-llama
|
||||||
|
|
||||||
- name: Run Playwright tests for Python
|
- name: Run Playwright tests for Python
|
||||||
run: pnpm run e2e:python
|
run: pnpm run e2e:python
|
||||||
@@ -67,13 +71,16 @@ jobs:
|
|||||||
LLAMA_CLOUD_API_KEY: ${{ secrets.LLAMA_CLOUD_API_KEY }}
|
LLAMA_CLOUD_API_KEY: ${{ secrets.LLAMA_CLOUD_API_KEY }}
|
||||||
FRAMEWORK: ${{ matrix.frameworks }}
|
FRAMEWORK: ${{ matrix.frameworks }}
|
||||||
DATASOURCE: ${{ matrix.datasources }}
|
DATASOURCE: ${{ matrix.datasources }}
|
||||||
working-directory: .
|
TEMPLATE_TYPE: ${{ matrix.template-types }}
|
||||||
|
PYTHONIOENCODING: utf-8
|
||||||
|
PYTHONLEGACYWINDOWSSTDIO: utf-8
|
||||||
|
working-directory: packages/create-llama
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: playwright-report-python-${{ matrix.os }}-${{ matrix.frameworks }}-${{ matrix.datasources }}
|
name: playwright-report-python-${{ matrix.os }}-${{ matrix.frameworks }}-${{ matrix.datasources }}-${{ matrix.template-types }}
|
||||||
path: ./playwright-report/
|
path: packages/create-llama/playwright-report/
|
||||||
overwrite: true
|
overwrite: true
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
@@ -83,11 +90,12 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [18, 20]
|
node-version: [20, 22]
|
||||||
python-version: ["3.11"]
|
python-version: ["3.11"]
|
||||||
os: [macos-latest, windows-latest, ubuntu-22.04]
|
os: [macos-latest, windows-latest, ubuntu-22.04]
|
||||||
frameworks: ["nextjs", "express"]
|
frameworks: ["nextjs"]
|
||||||
datasources: ["--no-files", "--example-file", "--llamacloud"]
|
datasources: ["--no-files", "--example-file", "--llamacloud"]
|
||||||
|
template-types: ["streaming", "llamaindexserver"]
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -100,10 +108,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
- name: Install Poetry
|
- name: Install uv
|
||||||
uses: snok/install-poetry@v1
|
run: curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||||
with:
|
- name: Add uv to PATH # Ensure uv is available in subsequent steps
|
||||||
version: ${{ env.POETRY_VERSION }}
|
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v3
|
- uses: pnpm/action-setup@v3
|
||||||
|
|
||||||
@@ -118,15 +126,30 @@ jobs:
|
|||||||
|
|
||||||
- name: Install Playwright Browsers
|
- name: Install Playwright Browsers
|
||||||
run: pnpm exec playwright install --with-deps
|
run: pnpm exec playwright install --with-deps
|
||||||
working-directory: .
|
working-directory: packages/create-llama
|
||||||
|
|
||||||
- name: Build create-llama
|
- name: Build create-llama
|
||||||
run: pnpm run build
|
run: pnpm run build
|
||||||
working-directory: .
|
working-directory: packages/create-llama
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: pnpm run pack-install
|
run: pnpm run pack-install
|
||||||
working-directory: .
|
working-directory: packages/create-llama
|
||||||
|
|
||||||
|
- name: Build server
|
||||||
|
run: pnpm run build
|
||||||
|
working-directory: packages/server
|
||||||
|
|
||||||
|
- name: Pack @llamaindex/server package
|
||||||
|
run: |
|
||||||
|
pnpm pack --pack-destination "${{ runner.temp }}"
|
||||||
|
if [ "${{ runner.os }}" == "Windows" ]; then
|
||||||
|
file=$(find "${{ runner.temp }}" -name "llamaindex-server-*.tgz" | head -n 1)
|
||||||
|
mv "$file" "${{ runner.temp }}/llamaindex-server.tgz"
|
||||||
|
else
|
||||||
|
mv ${{ runner.temp }}/llamaindex-server-*.tgz ${{ runner.temp }}/llamaindex-server.tgz
|
||||||
|
fi
|
||||||
|
working-directory: packages/server
|
||||||
|
|
||||||
- name: Run Playwright tests for TypeScript
|
- name: Run Playwright tests for TypeScript
|
||||||
run: pnpm run e2e:typescript
|
run: pnpm run e2e:typescript
|
||||||
@@ -135,12 +158,14 @@ jobs:
|
|||||||
LLAMA_CLOUD_API_KEY: ${{ secrets.LLAMA_CLOUD_API_KEY }}
|
LLAMA_CLOUD_API_KEY: ${{ secrets.LLAMA_CLOUD_API_KEY }}
|
||||||
FRAMEWORK: ${{ matrix.frameworks }}
|
FRAMEWORK: ${{ matrix.frameworks }}
|
||||||
DATASOURCE: ${{ matrix.datasources }}
|
DATASOURCE: ${{ matrix.datasources }}
|
||||||
working-directory: .
|
TEMPLATE_TYPE: ${{ matrix.template-types }}
|
||||||
|
SERVER_PACKAGE_PATH: ${{ runner.temp }}/llamaindex-server.tgz
|
||||||
|
working-directory: packages/create-llama
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: playwright-report-typescript-${{ matrix.os }}-${{ matrix.frameworks }}-${{ matrix.datasources }}-node${{ matrix.node-version }}
|
name: playwright-report-typescript-${{ matrix.os }}-${{ matrix.frameworks }}-${{ matrix.datasources }}-node${{ matrix.node-version }}-${{ matrix.template-types }}
|
||||||
path: ./playwright-report/
|
path: packages/create-llama/playwright-report/
|
||||||
overwrite: true
|
overwrite: true
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|||||||
@@ -31,12 +31,21 @@ jobs:
|
|||||||
- name: Run Prettier
|
- name: Run Prettier
|
||||||
run: pnpm run format
|
run: pnpm run format
|
||||||
|
|
||||||
|
- name: Run build
|
||||||
|
run: pnpm run build
|
||||||
|
|
||||||
|
- name: Run Typecheck for examples
|
||||||
|
run: pnpm run typecheck
|
||||||
|
working-directory: packages/server/examples
|
||||||
|
|
||||||
- name: Run Python format check
|
- name: Run Python format check
|
||||||
uses: chartboost/ruff-action@v1
|
uses: chartboost/ruff-action@v1
|
||||||
with:
|
with:
|
||||||
args: "format --check"
|
args: "format --check"
|
||||||
|
src: "python/llama-index-server"
|
||||||
|
|
||||||
- name: Run Python lint
|
- name: Run Python lint
|
||||||
uses: chartboost/ruff-action@v1
|
uses: chartboost/ruff-action@v1
|
||||||
with:
|
with:
|
||||||
args: "check"
|
args: "check"
|
||||||
|
src: "python/llama-index-server"
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
name: Release llama-index-server
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- "python/llama-index-server/**"
|
||||||
|
- ".github/workflows/release_llama_index_server.yml"
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- closed
|
||||||
|
|
||||||
|
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Create Release PR
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ./python/llama-index-server
|
||||||
|
if: |
|
||||||
|
github.event_name == 'push' &&
|
||||||
|
!startsWith(github.ref, 'refs/heads/release/llama-index-server-v') &&
|
||||||
|
!contains(github.event.head_commit.message, 'Release: llama-index-server v')
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v5
|
||||||
|
with:
|
||||||
|
enable-cache: true
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.11"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
shell: bash
|
||||||
|
run: uv sync --all-extras --dev
|
||||||
|
|
||||||
|
- name: Setup Git
|
||||||
|
run: |
|
||||||
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git config --global user.name "github-actions[bot]"
|
||||||
|
|
||||||
|
- name: Bump patch version
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
uvx --from=toml-cli toml set --toml-path=pyproject.toml project.version $(uvx --from=toml-cli toml get --toml-path=pyproject.toml project.version | awk -F. '{$NF = $NF + 1;}1' OFS=.)
|
||||||
|
git add pyproject.toml
|
||||||
|
git commit -m "chore(release): bump llama-index-server version to $(uvx --from=toml-cli toml get --toml-path=pyproject.toml project.version)"
|
||||||
|
|
||||||
|
- name: Get current version
|
||||||
|
id: get_version
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
version=$(uvx --from=toml-cli toml get --toml-path=pyproject.toml project.version)
|
||||||
|
echo "current_version=${version}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Create Release PR
|
||||||
|
uses: peter-evans/create-pull-request@v6
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
commit-message: "Release: llama-index-server v${{ steps.get_version.outputs.current_version }}"
|
||||||
|
title: "Release: llama-index-server v${{ steps.get_version.outputs.current_version }}"
|
||||||
|
body: |
|
||||||
|
This PR was automatically created to release a new version of the llama-index-server package.
|
||||||
|
|
||||||
|
Version: ${{ steps.get_version.outputs.current_version }}
|
||||||
|
|
||||||
|
Please review the changes and merge to trigger the release.
|
||||||
|
branch: release/llama-index-server-v${{ steps.get_version.outputs.current_version }}
|
||||||
|
base: main
|
||||||
|
labels: release, llama-index-server
|
||||||
|
|
||||||
|
publish:
|
||||||
|
name: Publish to PyPI
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ./python/llama-index-server
|
||||||
|
if: |
|
||||||
|
github.event_name == 'pull_request' &&
|
||||||
|
github.event.pull_request.merged == true &&
|
||||||
|
startsWith(github.event.pull_request.title, 'Release: llama-index-server') &&
|
||||||
|
startsWith(github.event.pull_request.head.ref, 'release/llama-index-server-v')
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v5
|
||||||
|
with:
|
||||||
|
enable-cache: true
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.11"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
shell: bash
|
||||||
|
run: uv sync --all-extras
|
||||||
|
|
||||||
|
- name: Get current version
|
||||||
|
id: get_version
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
version=$(uvx --from=toml-cli toml get --toml-path=pyproject.toml project.version)
|
||||||
|
echo "current_version=${version}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Build package
|
||||||
|
shell: bash
|
||||||
|
run: uv build --no-sources
|
||||||
|
|
||||||
|
- name: Publish to PyPI
|
||||||
|
shell: bash
|
||||||
|
run: uv publish --token ${{ secrets.PYPI_TOKEN }}
|
||||||
|
|
||||||
|
- name: Create GitHub Release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
tag_name: llama-index-server-v${{ steps.get_version.outputs.current_version }}
|
||||||
|
name: "llama-index-server v${{ steps.get_version.outputs.current_version }}"
|
||||||
|
body: |
|
||||||
|
Release of llama-index-server v${{ steps.get_version.outputs.current_version }}
|
||||||
|
draft: false
|
||||||
|
prerelease: false
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
name: Build Package
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
env:
|
||||||
|
PYTHON_VERSION: "3.9"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unit-test:
|
||||||
|
name: Unit Tests
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: python/llama-index-server
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest]
|
||||||
|
python-version: ["3.9"]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v5
|
||||||
|
with:
|
||||||
|
enable-cache: true
|
||||||
|
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
shell: bash
|
||||||
|
run: uv sync --all-extras --dev
|
||||||
|
|
||||||
|
- name: Run unit tests
|
||||||
|
shell: bash
|
||||||
|
run: uv run pytest tests
|
||||||
|
|
||||||
|
type-check:
|
||||||
|
name: Type Check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: python/llama-index-server
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v5
|
||||||
|
with:
|
||||||
|
enable-cache: true
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
shell: bash
|
||||||
|
run: uv sync --all-extras --dev
|
||||||
|
|
||||||
|
- name: Run mypy
|
||||||
|
shell: bash
|
||||||
|
run: uv run mypy llama_index
|
||||||
|
|
||||||
|
build:
|
||||||
|
needs: [unit-test, type-check]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: python/llama-index-server
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v5
|
||||||
|
with:
|
||||||
|
enable-cache: true
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
|
- name: Install build package
|
||||||
|
shell: bash
|
||||||
|
run: uv sync --all-extras
|
||||||
|
|
||||||
|
- name: Test import
|
||||||
|
shell: bash
|
||||||
|
run: uv run python -c "from llama_index.server import LlamaIndexServer"
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: llama-index-server
|
||||||
|
path: python/llama-index-server/dist/
|
||||||
-18
@@ -6,9 +6,6 @@ node_modules
|
|||||||
.pnpm-store
|
.pnpm-store
|
||||||
.pnp.js
|
.pnp.js
|
||||||
|
|
||||||
# testing
|
|
||||||
coverage
|
|
||||||
|
|
||||||
# next.js
|
# next.js
|
||||||
.next/
|
.next/
|
||||||
out/
|
out/
|
||||||
@@ -34,24 +31,9 @@ yarn-error.log*
|
|||||||
dist/
|
dist/
|
||||||
lib/
|
lib/
|
||||||
|
|
||||||
# e2e
|
|
||||||
.cache
|
|
||||||
test-results/
|
|
||||||
playwright-report/
|
|
||||||
blob-report/
|
|
||||||
playwright/.cache/
|
|
||||||
.tsbuildinfo
|
|
||||||
e2e/cache
|
|
||||||
|
|
||||||
# intellij
|
# intellij
|
||||||
**/.idea
|
**/.idea
|
||||||
|
|
||||||
# Python
|
|
||||||
.mypy_cache/
|
|
||||||
|
|
||||||
# build artifacts
|
|
||||||
create-llama-*.tgz
|
|
||||||
|
|
||||||
# vscode
|
# vscode
|
||||||
.vscode
|
.vscode
|
||||||
!.vscode/settings.json
|
!.vscode/settings.json
|
||||||
|
|||||||
+2
-1
@@ -1,3 +1,4 @@
|
|||||||
pnpm format
|
pnpm format
|
||||||
pnpm lint
|
pnpm lint
|
||||||
uvx ruff format --check templates/
|
uvx ruff check .
|
||||||
|
uvx ruff format . --check
|
||||||
|
|||||||
+14
-3
@@ -1,6 +1,17 @@
|
|||||||
apps/docs/i18n
|
node_modules/
|
||||||
apps/docs/docs/api
|
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
lib/
|
lib/
|
||||||
dist/
|
dist/
|
||||||
.docusaurus/
|
cache/
|
||||||
|
build/
|
||||||
|
.next/
|
||||||
|
out/
|
||||||
|
packages/server/server/
|
||||||
|
**/playwright-report/
|
||||||
|
**/test-results/
|
||||||
|
|
||||||
|
# Python
|
||||||
|
python/
|
||||||
|
**/*.mypy_cache/**
|
||||||
|
**/*.venv/**
|
||||||
|
**/*.ruff_cache/**
|
||||||
|
|||||||
@@ -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:
|
If you're using the Python backend, you can trigger indexing of your data by calling:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
poetry run generate
|
uv run generate
|
||||||
```
|
```
|
||||||
|
|
||||||
## Customizing the AI models
|
## Customizing the AI models
|
||||||
@@ -106,28 +106,16 @@ Ok to proceed? (y) y
|
|||||||
You can also pass command line arguments to set up a new project
|
You can also pass command line arguments to set up a new project
|
||||||
non-interactively. For a list of the latest options, call `create-llama --help`.
|
non-interactively. For a list of the latest options, call `create-llama --help`.
|
||||||
|
|
||||||
### Running in pro mode
|
|
||||||
|
|
||||||
If you prefer more advanced customization options, you can run `create-llama` in pro mode using the `--pro` flag.
|
|
||||||
|
|
||||||
In pro mode, instead of selecting a predefined use case, you'll be prompted to select each technical component of your project. This allows for greater flexibility in customizing your project, including:
|
|
||||||
|
|
||||||
- **Vector Store**: Choose from a variety of vector stores for keeping your documents, including MongoDB, Pinecone, Weaviate, Qdrant and Chroma.
|
|
||||||
- **Tools**: Choose from a variety of agent tools (functions called by the LLM), such as:
|
|
||||||
- Code Interpreter: Executes Python code in a secure Jupyter notebook environment
|
|
||||||
- Artifact Code Generator: Generates code artifacts that can be run in a sandbox
|
|
||||||
- OpenAPI Action: Facilitates requests to a provided OpenAPI schema
|
|
||||||
- Image Generator: Creates images based on text descriptions
|
|
||||||
- Web Search: Performs web searches to retrieve up-to-date information
|
|
||||||
- **Data Sources**: Integrate various data sources into your chat application, including local files, websites, or database-retrieved data.
|
|
||||||
- **Backend Options**: Besides using Next.js or FastAPI, you can also select to use Express for a more traditional Node.js application.
|
|
||||||
- **Observability**: Choose from a variety of LLM observability tools, including LlamaTrace and Traceloop.
|
|
||||||
|
|
||||||
Pro mode is ideal for developers who want fine-grained control over their project's configuration and are comfortable with more technical setup options.
|
|
||||||
|
|
||||||
## LlamaIndex Documentation
|
## LlamaIndex Documentation
|
||||||
|
|
||||||
- [TS/JS docs](https://ts.llamaindex.ai/)
|
- [TS/JS docs](https://ts.llamaindex.ai/)
|
||||||
- [Python docs](https://docs.llamaindex.ai/en/stable/)
|
- [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)
|
Inspired by and adapted from [create-next-app](https://github.com/vercel/next.js/tree/canary/packages/create-next-app)
|
||||||
|
|||||||
@@ -1,233 +0,0 @@
|
|||||||
import { expect, test } from "@playwright/test";
|
|
||||||
import { exec } from "child_process";
|
|
||||||
import fs from "fs";
|
|
||||||
import path from "path";
|
|
||||||
import util from "util";
|
|
||||||
import { TemplateFramework, TemplateVectorDB } from "../../helpers/types";
|
|
||||||
import { RunCreateLlamaOptions, createTestDir, runCreateLlama } from "../utils";
|
|
||||||
|
|
||||||
const execAsync = util.promisify(exec);
|
|
||||||
|
|
||||||
const templateFramework: TemplateFramework = process.env.FRAMEWORK
|
|
||||||
? (process.env.FRAMEWORK as TemplateFramework)
|
|
||||||
: "fastapi";
|
|
||||||
const dataSource: string = process.env.DATASOURCE
|
|
||||||
? process.env.DATASOURCE
|
|
||||||
: "--example-file";
|
|
||||||
|
|
||||||
// TODO: add support for other templates
|
|
||||||
|
|
||||||
if (
|
|
||||||
dataSource === "--example-file" // XXX: this test provides its own data source - only trigger it on one data source (usually the CI matrix will trigger multiple data sources)
|
|
||||||
) {
|
|
||||||
// vectorDBs, tools, and data source combinations to test
|
|
||||||
const vectorDbs: TemplateVectorDB[] = [
|
|
||||||
"mongo",
|
|
||||||
"pg",
|
|
||||||
"pinecone",
|
|
||||||
"milvus",
|
|
||||||
"astra",
|
|
||||||
"qdrant",
|
|
||||||
"chroma",
|
|
||||||
"weaviate",
|
|
||||||
];
|
|
||||||
|
|
||||||
const toolOptions = [
|
|
||||||
"wikipedia.WikipediaToolSpec",
|
|
||||||
"google.GoogleSearchToolSpec",
|
|
||||||
"document_generator",
|
|
||||||
"artifact",
|
|
||||||
];
|
|
||||||
|
|
||||||
const dataSources = [
|
|
||||||
"--example-file",
|
|
||||||
"--web-source https://www.example.com",
|
|
||||||
"--db-source mysql+pymysql://user:pass@localhost:3306/mydb",
|
|
||||||
];
|
|
||||||
|
|
||||||
const observabilityOptions = ["llamatrace", "traceloop"];
|
|
||||||
|
|
||||||
test.describe("Mypy check", () => {
|
|
||||||
test.describe.configure({ retries: 0 });
|
|
||||||
|
|
||||||
// Test vector databases
|
|
||||||
for (const vectorDb of vectorDbs) {
|
|
||||||
test(`Mypy check for vectorDB: ${vectorDb}`, async () => {
|
|
||||||
const cwd = await createTestDir();
|
|
||||||
const { pyprojectPath } = await createAndCheckLlamaProject({
|
|
||||||
options: {
|
|
||||||
cwd,
|
|
||||||
templateType: "streaming",
|
|
||||||
templateFramework,
|
|
||||||
dataSource: "--example-file",
|
|
||||||
vectorDb,
|
|
||||||
tools: "none",
|
|
||||||
port: 3000,
|
|
||||||
postInstallAction: "none",
|
|
||||||
templateUI: undefined,
|
|
||||||
appType: "--no-frontend",
|
|
||||||
llamaCloudProjectName: undefined,
|
|
||||||
llamaCloudIndexName: undefined,
|
|
||||||
observability: undefined,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const pyprojectContent = fs.readFileSync(pyprojectPath, "utf-8");
|
|
||||||
if (vectorDb !== "none") {
|
|
||||||
if (vectorDb === "pg") {
|
|
||||||
expect(pyprojectContent).toContain(
|
|
||||||
"llama-index-vector-stores-postgres",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
expect(pyprojectContent).toContain(
|
|
||||||
`llama-index-vector-stores-${vectorDb}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test tools
|
|
||||||
for (const tool of toolOptions) {
|
|
||||||
test(`Mypy check for tool: ${tool}`, async () => {
|
|
||||||
const cwd = await createTestDir();
|
|
||||||
const { pyprojectPath } = await createAndCheckLlamaProject({
|
|
||||||
options: {
|
|
||||||
cwd,
|
|
||||||
templateType: "streaming",
|
|
||||||
templateFramework,
|
|
||||||
dataSource: "--example-file",
|
|
||||||
vectorDb: "none",
|
|
||||||
tools: tool,
|
|
||||||
port: 3000,
|
|
||||||
postInstallAction: "none",
|
|
||||||
templateUI: undefined,
|
|
||||||
appType: "--no-frontend",
|
|
||||||
llamaCloudProjectName: undefined,
|
|
||||||
llamaCloudIndexName: undefined,
|
|
||||||
observability: undefined,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const pyprojectContent = fs.readFileSync(pyprojectPath, "utf-8");
|
|
||||||
if (tool === "wikipedia.WikipediaToolSpec") {
|
|
||||||
expect(pyprojectContent).toContain("wikipedia");
|
|
||||||
}
|
|
||||||
if (tool === "google.GoogleSearchToolSpec") {
|
|
||||||
expect(pyprojectContent).toContain("google");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test data sources
|
|
||||||
for (const dataSource of dataSources) {
|
|
||||||
const dataSourceType = dataSource.split(" ")[0];
|
|
||||||
test(`Mypy check for data source: ${dataSourceType}`, async () => {
|
|
||||||
const cwd = await createTestDir();
|
|
||||||
const { pyprojectPath } = await createAndCheckLlamaProject({
|
|
||||||
options: {
|
|
||||||
cwd,
|
|
||||||
templateType: "streaming",
|
|
||||||
templateFramework,
|
|
||||||
dataSource,
|
|
||||||
vectorDb: "none",
|
|
||||||
tools: "none",
|
|
||||||
port: 3000,
|
|
||||||
postInstallAction: "none",
|
|
||||||
templateUI: undefined,
|
|
||||||
appType: "--no-frontend",
|
|
||||||
llamaCloudProjectName: undefined,
|
|
||||||
llamaCloudIndexName: undefined,
|
|
||||||
observability: undefined,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const pyprojectContent = fs.readFileSync(pyprojectPath, "utf-8");
|
|
||||||
if (dataSource.includes("--web-source")) {
|
|
||||||
expect(pyprojectContent).toContain("llama-index-readers-web");
|
|
||||||
}
|
|
||||||
if (dataSource.includes("--db-source")) {
|
|
||||||
expect(pyprojectContent).toContain("llama-index-readers-database");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test observability options
|
|
||||||
for (const observability of observabilityOptions) {
|
|
||||||
test(`Mypy check for observability: ${observability}`, async () => {
|
|
||||||
const cwd = await createTestDir();
|
|
||||||
|
|
||||||
const { pyprojectPath } = await createAndCheckLlamaProject({
|
|
||||||
options: {
|
|
||||||
cwd,
|
|
||||||
templateType: "streaming",
|
|
||||||
templateFramework,
|
|
||||||
dataSource: "--example-file",
|
|
||||||
vectorDb: "none",
|
|
||||||
tools: "none",
|
|
||||||
port: 3000,
|
|
||||||
postInstallAction: "none",
|
|
||||||
templateUI: undefined,
|
|
||||||
appType: "--no-frontend",
|
|
||||||
llamaCloudProjectName: undefined,
|
|
||||||
llamaCloudIndexName: undefined,
|
|
||||||
observability,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createAndCheckLlamaProject({
|
|
||||||
options,
|
|
||||||
}: {
|
|
||||||
options: RunCreateLlamaOptions;
|
|
||||||
}): Promise<{ pyprojectPath: string; projectPath: string }> {
|
|
||||||
const result = await runCreateLlama(options);
|
|
||||||
const name = result.projectName;
|
|
||||||
const projectPath = path.join(options.cwd, name);
|
|
||||||
|
|
||||||
// Check if the app folder exists
|
|
||||||
expect(fs.existsSync(projectPath)).toBeTruthy();
|
|
||||||
|
|
||||||
// Check if pyproject.toml exists
|
|
||||||
const pyprojectPath = path.join(projectPath, "pyproject.toml");
|
|
||||||
expect(fs.existsSync(pyprojectPath)).toBeTruthy();
|
|
||||||
|
|
||||||
const env = {
|
|
||||||
...process.env,
|
|
||||||
POETRY_VIRTUALENVS_IN_PROJECT: "true",
|
|
||||||
};
|
|
||||||
|
|
||||||
// Run poetry install
|
|
||||||
try {
|
|
||||||
const { stdout: installStdout, stderr: installStderr } = await execAsync(
|
|
||||||
"poetry install",
|
|
||||||
{ cwd: projectPath, env },
|
|
||||||
);
|
|
||||||
console.log("poetry install stdout:", installStdout);
|
|
||||||
console.error("poetry install stderr:", installStderr);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error running poetry install:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run poetry run mypy
|
|
||||||
try {
|
|
||||||
const { stdout: mypyStdout, stderr: mypyStderr } = await execAsync(
|
|
||||||
"poetry run mypy .",
|
|
||||||
{ cwd: projectPath, env },
|
|
||||||
);
|
|
||||||
console.log("poetry run mypy stdout:", mypyStdout);
|
|
||||||
console.error("poetry run mypy stderr:", mypyStderr);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error running mypy:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we reach this point without throwing an error, the test passes
|
|
||||||
expect(true).toBeTruthy();
|
|
||||||
|
|
||||||
return { pyprojectPath, projectPath };
|
|
||||||
}
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
import { expect, test } from "@playwright/test";
|
|
||||||
import { exec } from "child_process";
|
|
||||||
import fs from "fs";
|
|
||||||
import path from "path";
|
|
||||||
import util from "util";
|
|
||||||
import { TemplateFramework, TemplateVectorDB } from "../../helpers/types";
|
|
||||||
import { createTestDir, runCreateLlama } from "../utils";
|
|
||||||
|
|
||||||
const execAsync = util.promisify(exec);
|
|
||||||
|
|
||||||
const templateFramework: TemplateFramework = process.env.FRAMEWORK
|
|
||||||
? (process.env.FRAMEWORK as TemplateFramework)
|
|
||||||
: "nextjs";
|
|
||||||
const dataSource: string = process.env.DATASOURCE
|
|
||||||
? process.env.DATASOURCE
|
|
||||||
: "--example-file";
|
|
||||||
|
|
||||||
// vectorDBs combinations to test
|
|
||||||
const vectorDbs: TemplateVectorDB[] = [
|
|
||||||
"mongo",
|
|
||||||
"pg",
|
|
||||||
"qdrant",
|
|
||||||
"pinecone",
|
|
||||||
"milvus",
|
|
||||||
"astra",
|
|
||||||
"chroma",
|
|
||||||
"llamacloud",
|
|
||||||
"weaviate",
|
|
||||||
];
|
|
||||||
|
|
||||||
test.describe("Test resolve TS dependencies", () => {
|
|
||||||
// Test vector DBs without LlamaParse
|
|
||||||
for (const vectorDb of vectorDbs) {
|
|
||||||
const optionDescription = `vectorDb: ${vectorDb}, dataSource: ${dataSource}`;
|
|
||||||
|
|
||||||
test(`Vector DB test - ${optionDescription}`, async () => {
|
|
||||||
await runTest(vectorDb, false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test LlamaParse with vectorDB 'none'
|
|
||||||
test(`LlamaParse test - vectorDb: none, dataSource: ${dataSource}, llamaParse: true`, async () => {
|
|
||||||
await runTest("none", true);
|
|
||||||
});
|
|
||||||
|
|
||||||
async function runTest(
|
|
||||||
vectorDb: TemplateVectorDB | "none",
|
|
||||||
useLlamaParse: boolean,
|
|
||||||
) {
|
|
||||||
const cwd = await createTestDir();
|
|
||||||
|
|
||||||
const result = await runCreateLlama({
|
|
||||||
cwd: cwd,
|
|
||||||
templateType: "streaming",
|
|
||||||
templateFramework: templateFramework,
|
|
||||||
dataSource: dataSource,
|
|
||||||
vectorDb: vectorDb,
|
|
||||||
port: 3000,
|
|
||||||
postInstallAction: "none",
|
|
||||||
templateUI: undefined,
|
|
||||||
appType: templateFramework === "nextjs" ? "" : "--no-frontend",
|
|
||||||
llamaCloudProjectName: undefined,
|
|
||||||
llamaCloudIndexName: undefined,
|
|
||||||
tools: undefined,
|
|
||||||
useLlamaParse: useLlamaParse,
|
|
||||||
});
|
|
||||||
const name = result.projectName;
|
|
||||||
|
|
||||||
// Check if the app folder exists
|
|
||||||
const appDir = path.join(cwd, name);
|
|
||||||
const dirExists = fs.existsSync(appDir);
|
|
||||||
expect(dirExists).toBeTruthy();
|
|
||||||
|
|
||||||
// Install dependencies using pnpm
|
|
||||||
try {
|
|
||||||
const { stderr: installStderr } = await execAsync(
|
|
||||||
"pnpm install --prefer-offline",
|
|
||||||
{
|
|
||||||
cwd: appDir,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error installing dependencies:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run tsc type check and capture the output
|
|
||||||
try {
|
|
||||||
const { stdout, stderr } = await execAsync(
|
|
||||||
"pnpm exec tsc -b --diagnostics",
|
|
||||||
{
|
|
||||||
cwd: appDir,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
// Check if there's any error output
|
|
||||||
expect(stderr).toBeFalsy();
|
|
||||||
|
|
||||||
// Log the stdout for debugging purposes
|
|
||||||
console.log("TypeScript type-check output:", stdout);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error running tsc:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import eslint from "@eslint/js";
|
||||||
|
import eslintConfigPrettier from "eslint-config-prettier";
|
||||||
|
import globals from "globals";
|
||||||
|
import tseslint from "typescript-eslint";
|
||||||
|
|
||||||
|
export default tseslint.config(
|
||||||
|
eslint.configs.recommended,
|
||||||
|
...tseslint.configs.recommended,
|
||||||
|
eslintConfigPrettier,
|
||||||
|
{
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2022,
|
||||||
|
sourceType: "module",
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
...globals.node,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ["packages/create-llama/**"],
|
||||||
|
rules: {
|
||||||
|
"max-params": ["error", 4],
|
||||||
|
"prefer-const": "error",
|
||||||
|
"no-empty": "off",
|
||||||
|
"no-extra-boolean-cast": "off",
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": "off",
|
||||||
|
"@typescript-eslint/no-empty-object-type": "off",
|
||||||
|
"@typescript-eslint/no-wrapper-object-types": "off",
|
||||||
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ["packages/server/**"],
|
||||||
|
rules: {
|
||||||
|
"no-irregular-whitespace": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": "off",
|
||||||
|
"@typescript-eslint/no-explicit-any": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
ignoreRestArgs: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
"python/**",
|
||||||
|
"**/*.mypy_cache/**",
|
||||||
|
"**/*.venv/**",
|
||||||
|
"**/*.ruff_cache/**",
|
||||||
|
"**/dist/**",
|
||||||
|
"**/e2e/cache/**",
|
||||||
|
"**/lib/*",
|
||||||
|
"**/.next/**",
|
||||||
|
"**/out/**",
|
||||||
|
"**/node_modules/**",
|
||||||
|
"**/build/**",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
);
|
||||||
+32
-63
@@ -1,83 +1,52 @@
|
|||||||
{
|
{
|
||||||
"name": "create-llama",
|
"name": "create-llama-monorepo",
|
||||||
"version": "0.4.0",
|
"version": "1.0.0",
|
||||||
"description": "Create LlamaIndex-powered apps with one command",
|
"private": true,
|
||||||
|
"description": "Monorepo for create-llama",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"rag",
|
"rag",
|
||||||
"llamaindex",
|
"llamaindex"
|
||||||
"next.js"
|
|
||||||
],
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/run-llama/create-llama",
|
"url": "https://github.com/run-llama/create-llama"
|
||||||
"directory": "packages/create-llama"
|
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"workspaces": [
|
||||||
"create-llama": "./dist/index.js"
|
"packages/*"
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "bash ./scripts/build.sh",
|
"dev": "pnpm -r dev",
|
||||||
"build:ncc": "pnpm run clean && ncc build ./index.ts -o ./dist/ --minify --no-cache --no-source-map-register",
|
"build": "pnpm -r build",
|
||||||
"clean": "rimraf --glob ./dist ./templates/**/__pycache__ ./templates/**/node_modules ./templates/**/poetry.lock",
|
"e2e": "pnpm -r e2e",
|
||||||
"dev": "ncc build ./index.ts -w -o dist/",
|
"lint": "eslint .",
|
||||||
"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": "prettier --ignore-unknown --cache --check .",
|
||||||
"format:write": "prettier --ignore-unknown --write .",
|
"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",
|
"prepare": "husky",
|
||||||
"release": "pnpm run build && changeset publish",
|
"new-snapshot": "pnpm -r build && changeset version --snapshot",
|
||||||
"release-snapshot": "pnpm run build && changeset publish --tag snapshot"
|
"new-version": "pnpm -r build && changeset version",
|
||||||
},
|
"release": "pnpm -r build && changeset publish",
|
||||||
"dependencies": {
|
"release-snapshot": "pnpm -r build && changeset publish --tag snapshot"
|
||||||
"@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": {
|
"devDependencies": {
|
||||||
"@changesets/cli": "^2.27.1",
|
"@changesets/cli": "^2.27.1",
|
||||||
"@playwright/test": "^1.41.1",
|
"bunchee": "6.4.0",
|
||||||
"@vercel/ncc": "0.38.1",
|
|
||||||
"eslint": "^8.56.0",
|
|
||||||
"eslint-config-prettier": "^8.10.0",
|
|
||||||
"husky": "^9.0.10",
|
"husky": "^9.0.10",
|
||||||
"prettier": "^3.2.5",
|
"lint-staged": "^15.2.11",
|
||||||
"prettier-plugin-organize-imports": "^3.2.4",
|
"typescript-eslint": "^8.18.0",
|
||||||
"rimraf": "^5.0.5",
|
"globals": "^15.12.0",
|
||||||
"typescript": "^5.3.3",
|
"eslint": "9.22.0",
|
||||||
"wait-port": "^1.1.0"
|
"@eslint/js": "^9.25.0",
|
||||||
|
"eslint-config-next": "^15.1.0",
|
||||||
|
"eslint-config-prettier": "^9.1.0",
|
||||||
|
"eslint-plugin-react": "7.37.2",
|
||||||
|
"prettier": "^3.4.2",
|
||||||
|
"prettier-plugin-organize-imports": "^4.1.0",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||||
|
"typescript": "^5.7.3",
|
||||||
|
"@types/node": "^22.9.0",
|
||||||
|
"@types/react": "^19",
|
||||||
|
"@types/react-dom": "^19"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.0.5",
|
"packageManager": "pnpm@9.0.5",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# 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,5 +1,121 @@
|
|||||||
# create-llama
|
# create-llama
|
||||||
|
|
||||||
|
## 0.5.16
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 6f75d4a: fix: unsupported language in code gen workflow
|
||||||
|
- d0618fa: Fix LlamaCloud generate script issue
|
||||||
|
|
||||||
|
## 0.5.15
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 527075c: Enable dev mode that allows updating code directly in the UI
|
||||||
|
|
||||||
|
## 0.5.14
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 1df8cfb: Split artifacts use case to document generator and code generator
|
||||||
|
- 1b5a519: chore: improve dev experience with nodemon
|
||||||
|
- b3eb0ba: Fix typing check issue
|
||||||
|
- 556f33c: fix chromadb dependency issue
|
||||||
|
- 2451539: fix: remove dead generated ai code
|
||||||
|
- 7a70390: Deprecate pro mode
|
||||||
|
|
||||||
|
## 0.5.13
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- f4ca602: Add artifact use case for Typescript template
|
||||||
|
- f4ca602: Update typescript use cases to use the new workflow engine
|
||||||
|
|
||||||
|
## 0.5.12
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 241d82a: Add artifacts use case (python)
|
||||||
|
|
||||||
|
## 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
|
## 0.4.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable import/no-extraneous-dependencies */
|
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { green, yellow } from "picocolors";
|
import { green, yellow } from "picocolors";
|
||||||
import { tryGitInit } from "./helpers/git";
|
import { tryGitInit } from "./helpers/git";
|
||||||
@@ -90,7 +89,7 @@ export async function createApp({
|
|||||||
// Install backend
|
// Install backend
|
||||||
await installTemplate({ ...args, backend: true });
|
await installTemplate({ ...args, backend: true });
|
||||||
|
|
||||||
if (frontend && framework === "fastapi") {
|
if (frontend && framework === "fastapi" && template !== "llamaindexserver") {
|
||||||
// install frontend
|
// install frontend
|
||||||
const frontendRoot = path.join(root, ".frontend");
|
const frontendRoot = path.join(root, ".frontend");
|
||||||
await makeDir(frontendRoot);
|
await makeDir(frontendRoot);
|
||||||
@@ -110,7 +109,7 @@ export async function createApp({
|
|||||||
console.log();
|
console.log();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toolsRequireConfig(tools)) {
|
if (toolsRequireConfig(tools) && template !== "llamaindexserver") {
|
||||||
const configFile =
|
const configFile =
|
||||||
framework === "fastapi" ? "config/tools.yaml" : "config/tools.json";
|
framework === "fastapi" ? "config/tools.yaml" : "config/tools.json";
|
||||||
console.log(
|
console.log(
|
||||||
@@ -0,0 +1,285 @@
|
|||||||
|
import { expect, test } from "@playwright/test";
|
||||||
|
import { exec } from "child_process";
|
||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
import util from "util";
|
||||||
|
import { TemplateFramework, TemplateType, TemplateUseCase, TemplateVectorDB } from "../../helpers/types";
|
||||||
|
import { RunCreateLlamaOptions, createTestDir, runCreateLlama } from "../utils";
|
||||||
|
|
||||||
|
const execAsync = util.promisify(exec);
|
||||||
|
|
||||||
|
const templateFramework: TemplateFramework = process.env.FRAMEWORK
|
||||||
|
? (process.env.FRAMEWORK as TemplateFramework)
|
||||||
|
: "fastapi";
|
||||||
|
const templateType: TemplateType = process.env.TEMPLATE_TYPE
|
||||||
|
? (process.env.TEMPLATE_TYPE as TemplateType)
|
||||||
|
: "llamaindexserver";
|
||||||
|
const useCases: TemplateUseCase[] = [
|
||||||
|
"agentic_rag",
|
||||||
|
"deep_research",
|
||||||
|
"financial_report",
|
||||||
|
"code_generator",
|
||||||
|
"document_generator",
|
||||||
|
];
|
||||||
|
const dataSource: string = process.env.DATASOURCE
|
||||||
|
? process.env.DATASOURCE
|
||||||
|
: "--example-file";
|
||||||
|
|
||||||
|
test.describe("Mypy check", () => {
|
||||||
|
test.describe.configure({ retries: 0 });
|
||||||
|
|
||||||
|
// Test for streaming template
|
||||||
|
test.describe("StreamingTemplate", () => {
|
||||||
|
test.skip(templateType !== "streaming", `skipping streaming test for ${templateType}`);
|
||||||
|
if (
|
||||||
|
dataSource === "--example-file" // XXX: this test provides its own data source - only trigger it on one data source (usually the CI matrix will trigger multiple data sources)
|
||||||
|
) {
|
||||||
|
// vectorDBs, tools, and data source combinations to test
|
||||||
|
const vectorDbs: TemplateVectorDB[] = [
|
||||||
|
"mongo",
|
||||||
|
"pg",
|
||||||
|
"pinecone",
|
||||||
|
"milvus",
|
||||||
|
"astra",
|
||||||
|
"qdrant",
|
||||||
|
"chroma",
|
||||||
|
"weaviate",
|
||||||
|
];
|
||||||
|
const toolOptions = [
|
||||||
|
"wikipedia.WikipediaToolSpec",
|
||||||
|
"google.GoogleSearchToolSpec",
|
||||||
|
"document_generator",
|
||||||
|
"artifact",
|
||||||
|
];
|
||||||
|
|
||||||
|
const dataSources = [
|
||||||
|
"--example-file",
|
||||||
|
"--web-source https://www.example.com",
|
||||||
|
"--db-source mysql+pymysql://user:pass@localhost:3306/mydb",
|
||||||
|
];
|
||||||
|
|
||||||
|
const observabilityOptions = ["llamatrace", "traceloop"];
|
||||||
|
|
||||||
|
// Test vector databases
|
||||||
|
for (const vectorDb of vectorDbs) {
|
||||||
|
test(`vectorDB: ${vectorDb} ${templateType}`, async () => {
|
||||||
|
const cwd = await createTestDir();
|
||||||
|
const { pyprojectPath } = await createAndCheckLlamaProject({
|
||||||
|
options: {
|
||||||
|
cwd,
|
||||||
|
templateType: "streaming",
|
||||||
|
templateFramework,
|
||||||
|
dataSource: "--example-file",
|
||||||
|
vectorDb,
|
||||||
|
tools: "none",
|
||||||
|
port: 3000,
|
||||||
|
postInstallAction: "none",
|
||||||
|
templateUI: undefined,
|
||||||
|
appType: "--no-frontend",
|
||||||
|
llamaCloudProjectName: undefined,
|
||||||
|
llamaCloudIndexName: undefined,
|
||||||
|
observability: undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const pyprojectContent = fs.readFileSync(pyprojectPath, "utf-8");
|
||||||
|
if (vectorDb !== "none") {
|
||||||
|
if (vectorDb === "pg") {
|
||||||
|
expect(pyprojectContent).toContain(
|
||||||
|
"llama-index-vector-stores-postgres",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
expect(pyprojectContent).toContain(
|
||||||
|
`llama-index-vector-stores-${vectorDb}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Test tools
|
||||||
|
for (const tool of toolOptions) {
|
||||||
|
test(`tool: ${tool} ${templateType}`, async () => {
|
||||||
|
const cwd = await createTestDir();
|
||||||
|
const { pyprojectPath } = await createAndCheckLlamaProject({
|
||||||
|
options: {
|
||||||
|
cwd,
|
||||||
|
templateType: "streaming",
|
||||||
|
templateFramework,
|
||||||
|
dataSource: "--example-file",
|
||||||
|
vectorDb: "none",
|
||||||
|
tools: tool,
|
||||||
|
port: 3000,
|
||||||
|
postInstallAction: "none",
|
||||||
|
templateUI: undefined,
|
||||||
|
appType: "--no-frontend",
|
||||||
|
llamaCloudProjectName: undefined,
|
||||||
|
llamaCloudIndexName: undefined,
|
||||||
|
observability: undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const pyprojectContent = fs.readFileSync(pyprojectPath, "utf-8");
|
||||||
|
if (tool === "wikipedia.WikipediaToolSpec") {
|
||||||
|
expect(pyprojectContent).toContain("wikipedia");
|
||||||
|
}
|
||||||
|
if (tool === "google.GoogleSearchToolSpec") {
|
||||||
|
expect(pyprojectContent).toContain("google");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Test data sources
|
||||||
|
for (const dataSource of dataSources) {
|
||||||
|
test(`data source: ${dataSource} ${templateType}`, async () => {
|
||||||
|
const dataSourceType = dataSource.split(" ")[0];
|
||||||
|
const cwd = await createTestDir();
|
||||||
|
const { pyprojectPath } = await createAndCheckLlamaProject({
|
||||||
|
options: {
|
||||||
|
cwd,
|
||||||
|
templateType: "streaming",
|
||||||
|
templateFramework,
|
||||||
|
dataSource,
|
||||||
|
vectorDb: "none",
|
||||||
|
tools: "none",
|
||||||
|
port: 3000,
|
||||||
|
postInstallAction: "none",
|
||||||
|
templateUI: undefined,
|
||||||
|
appType: "--no-frontend",
|
||||||
|
llamaCloudProjectName: undefined,
|
||||||
|
llamaCloudIndexName: undefined,
|
||||||
|
observability: undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const pyprojectContent = fs.readFileSync(pyprojectPath, "utf-8");
|
||||||
|
if (dataSource.includes("--web-source")) {
|
||||||
|
expect(pyprojectContent).toContain("llama-index-readers-web");
|
||||||
|
}
|
||||||
|
if (dataSource.includes("--db-source")) {
|
||||||
|
expect(pyprojectContent).toContain("llama-index-readers-database");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test observability options
|
||||||
|
for (const observability of observabilityOptions) {
|
||||||
|
test.describe(`observability: ${observability} ${templateType}`, async () => {
|
||||||
|
const cwd = await createTestDir();
|
||||||
|
|
||||||
|
const { pyprojectPath } = await createAndCheckLlamaProject({
|
||||||
|
options: {
|
||||||
|
cwd,
|
||||||
|
templateType: "streaming",
|
||||||
|
templateFramework,
|
||||||
|
dataSource: "--example-file",
|
||||||
|
vectorDb: "none",
|
||||||
|
tools: "none",
|
||||||
|
port: 3000,
|
||||||
|
postInstallAction: "none",
|
||||||
|
templateUI: undefined,
|
||||||
|
appType: "--no-frontend",
|
||||||
|
llamaCloudProjectName: undefined,
|
||||||
|
llamaCloudIndexName: undefined,
|
||||||
|
observability,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe("LlamaIndexServer", async () => {
|
||||||
|
test.skip(templateType !== "llamaindexserver", `skipping llamaindexserver test for ${templateType}`);
|
||||||
|
test.skip(dataSource !== "--example-file", `skipping llamaindexserver test for ${dataSource}`);
|
||||||
|
for (const useCase of useCases) {
|
||||||
|
const cwd = await createTestDir();
|
||||||
|
await createAndCheckLlamaProject({
|
||||||
|
options: {
|
||||||
|
cwd,
|
||||||
|
templateType: "llamaindexserver",
|
||||||
|
templateFramework,
|
||||||
|
dataSource,
|
||||||
|
vectorDb: "none",
|
||||||
|
tools: "none",
|
||||||
|
port: 3000,
|
||||||
|
postInstallAction: "none",
|
||||||
|
templateUI: undefined,
|
||||||
|
appType: "--no-frontend",
|
||||||
|
llamaCloudProjectName: undefined,
|
||||||
|
llamaCloudIndexName: undefined,
|
||||||
|
observability: undefined,
|
||||||
|
useCase,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function createAndCheckLlamaProject({
|
||||||
|
options,
|
||||||
|
}: {
|
||||||
|
options: RunCreateLlamaOptions;
|
||||||
|
}): Promise<{ pyprojectPath: string; projectPath: string }> {
|
||||||
|
const result = await runCreateLlama(options);
|
||||||
|
const name = result.projectName;
|
||||||
|
const projectPath = path.join(options.cwd, name);
|
||||||
|
|
||||||
|
// Check if the app folder exists
|
||||||
|
expect(fs.existsSync(projectPath)).toBeTruthy();
|
||||||
|
|
||||||
|
// Check if pyproject.toml exists
|
||||||
|
const pyprojectPath = path.join(projectPath, "pyproject.toml");
|
||||||
|
expect(fs.existsSync(pyprojectPath)).toBeTruthy();
|
||||||
|
|
||||||
|
// Modify environment for the command
|
||||||
|
const commandEnv = {
|
||||||
|
...process.env,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log("Running uv venv...");
|
||||||
|
try {
|
||||||
|
const { stdout: venvStdout, stderr: venvStderr } = await execAsync(
|
||||||
|
"uv venv",
|
||||||
|
{ cwd: projectPath, env: commandEnv },
|
||||||
|
);
|
||||||
|
console.log("uv venv stdout:", venvStdout);
|
||||||
|
console.error("uv venv stderr:", venvStderr);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error running uv venv:", error);
|
||||||
|
throw error; // Re-throw error to fail the test
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ....");
|
||||||
|
try {
|
||||||
|
const { stdout: mypyStdout, stderr: mypyStderr } = await execAsync(
|
||||||
|
"uv run mypy .",
|
||||||
|
{ cwd: projectPath, env: commandEnv },
|
||||||
|
);
|
||||||
|
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
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error running mypy:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we reach this point without throwing an error, the test passes
|
||||||
|
expect(true).toBeTruthy();
|
||||||
|
|
||||||
|
return { pyprojectPath, projectPath };
|
||||||
|
}
|
||||||
|
});
|
||||||
+32
-11
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable turbo/no-undeclared-env-vars */
|
|
||||||
import { expect, test } from "@playwright/test";
|
import { expect, test } from "@playwright/test";
|
||||||
import { ChildProcess } from "child_process";
|
import { ChildProcess } from "child_process";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
@@ -13,19 +12,30 @@ import { createTestDir, runCreateLlama, type AppType } from "../utils";
|
|||||||
const templateFramework: TemplateFramework = process.env.FRAMEWORK
|
const templateFramework: TemplateFramework = process.env.FRAMEWORK
|
||||||
? (process.env.FRAMEWORK as TemplateFramework)
|
? (process.env.FRAMEWORK as TemplateFramework)
|
||||||
: "fastapi";
|
: "fastapi";
|
||||||
const dataSource: string = "--example-file";
|
const dataSource: string = process.env.DATASOURCE
|
||||||
|
? (process.env.DATASOURCE as string)
|
||||||
|
: "--example-file";
|
||||||
|
const llamaCloudProjectName = "create-llama";
|
||||||
|
const llamaCloudIndexName = "e2e-test";
|
||||||
|
|
||||||
const templateUI: TemplateUI = "shadcn";
|
const templateUI: TemplateUI = "shadcn";
|
||||||
const templatePostInstallAction: TemplatePostInstallAction = "runApp";
|
const templatePostInstallAction: TemplatePostInstallAction = "runApp";
|
||||||
const appType: AppType = templateFramework === "fastapi" ? "--frontend" : "";
|
const appType: AppType = "--frontend";
|
||||||
const userMessage = "Write a blog post about physical standards for letters";
|
const userMessage = "Write a blog post about physical standards for letters";
|
||||||
const templateUseCases = ["financial_report", "blog", "form_filling"];
|
const templateUseCases = [
|
||||||
|
"agentic_rag",
|
||||||
|
"financial_report",
|
||||||
|
"deep_research",
|
||||||
|
"code_generator",
|
||||||
|
];
|
||||||
|
|
||||||
for (const useCase of templateUseCases) {
|
for (const useCase of templateUseCases) {
|
||||||
test.describe(`Test multiagent template ${useCase} ${templateFramework} ${dataSource} ${templateUI} ${appType} ${templatePostInstallAction}`, async () => {
|
test.describe(`Test use case ${useCase} ${templateFramework} ${dataSource} ${templateUI} ${appType} ${templatePostInstallAction}`, async () => {
|
||||||
test.skip(
|
test.skip(
|
||||||
process.platform !== "linux" || process.env.DATASOURCE === "--no-files",
|
dataSource === "--no-files" || templateFramework === "express",
|
||||||
"The multiagent template currently only works with files. We also only run on Linux to speed up tests.",
|
"The llamaindexserver template currently only works with nextjs, fastapi. We also only run on Linux to speed up tests.",
|
||||||
);
|
);
|
||||||
|
const useLlamaParse = dataSource === "--llamacloud";
|
||||||
let port: number;
|
let port: number;
|
||||||
let cwd: string;
|
let cwd: string;
|
||||||
let name: string;
|
let name: string;
|
||||||
@@ -38,7 +48,7 @@ for (const useCase of templateUseCases) {
|
|||||||
cwd = await createTestDir();
|
cwd = await createTestDir();
|
||||||
const result = await runCreateLlama({
|
const result = await runCreateLlama({
|
||||||
cwd,
|
cwd,
|
||||||
templateType: "multiagent",
|
templateType: "llamaindexserver",
|
||||||
templateFramework,
|
templateFramework,
|
||||||
dataSource,
|
dataSource,
|
||||||
vectorDb,
|
vectorDb,
|
||||||
@@ -47,6 +57,9 @@ for (const useCase of templateUseCases) {
|
|||||||
templateUI,
|
templateUI,
|
||||||
appType,
|
appType,
|
||||||
useCase,
|
useCase,
|
||||||
|
llamaCloudProjectName,
|
||||||
|
llamaCloudIndexName,
|
||||||
|
useLlamaParse,
|
||||||
});
|
});
|
||||||
name = result.projectName;
|
name = result.projectName;
|
||||||
appProcess = result.appProcess;
|
appProcess = result.appProcess;
|
||||||
@@ -63,7 +76,9 @@ for (const useCase of templateUseCases) {
|
|||||||
templateFramework === "express",
|
templateFramework === "express",
|
||||||
);
|
);
|
||||||
await page.goto(`http://localhost:${port}`);
|
await page.goto(`http://localhost:${port}`);
|
||||||
await expect(page.getByText("Built by LlamaIndex")).toBeVisible();
|
await expect(page.getByText("Built by LlamaIndex")).toBeVisible({
|
||||||
|
timeout: 5 * 60 * 1000,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Frontend should be able to submit a message and receive the start of a streamed response", async ({
|
test("Frontend should be able to submit a message and receive the start of a streamed response", async ({
|
||||||
@@ -72,9 +87,9 @@ for (const useCase of templateUseCases) {
|
|||||||
test.skip(
|
test.skip(
|
||||||
templatePostInstallAction !== "runApp" ||
|
templatePostInstallAction !== "runApp" ||
|
||||||
useCase === "financial_report" ||
|
useCase === "financial_report" ||
|
||||||
useCase === "form_filling" ||
|
useCase === "deep_research" ||
|
||||||
templateFramework === "express",
|
templateFramework === "express",
|
||||||
"Skip chat tests for financial report and form filling.",
|
"Skip chat tests for financial report and deep research.",
|
||||||
);
|
);
|
||||||
await page.goto(`http://localhost:${port}`);
|
await page.goto(`http://localhost:${port}`);
|
||||||
await page.fill("form textarea", userMessage);
|
await page.fill("form textarea", userMessage);
|
||||||
@@ -86,6 +101,12 @@ for (const useCase of templateUseCases) {
|
|||||||
await page.click("form button[type=submit]");
|
await page.click("form button[type=submit]");
|
||||||
|
|
||||||
const response = await responsePromise;
|
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();
|
expect(response.ok()).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable turbo/no-undeclared-env-vars */
|
|
||||||
import { expect, test } from "@playwright/test";
|
import { expect, test } from "@playwright/test";
|
||||||
import { ChildProcess } from "child_process";
|
import { ChildProcess } from "child_process";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable turbo/no-undeclared-env-vars */
|
|
||||||
import { expect, test } from "@playwright/test";
|
import { expect, test } from "@playwright/test";
|
||||||
import { ChildProcess } from "child_process";
|
import { ChildProcess } from "child_process";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
import { expect, test } from "@playwright/test";
|
||||||
|
import { exec } from "child_process";
|
||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
import util from "util";
|
||||||
|
import {
|
||||||
|
TemplateFramework,
|
||||||
|
TemplateType,
|
||||||
|
TemplateUseCase,
|
||||||
|
TemplateVectorDB,
|
||||||
|
} from "../../helpers/types";
|
||||||
|
import { createTestDir, runCreateLlama } from "../utils";
|
||||||
|
|
||||||
|
const execAsync = util.promisify(exec);
|
||||||
|
|
||||||
|
const templateFramework: TemplateFramework = process.env.FRAMEWORK
|
||||||
|
? (process.env.FRAMEWORK as TemplateFramework)
|
||||||
|
: "nextjs";
|
||||||
|
const templateType: TemplateType = process.env.TEMPLATE_TYPE
|
||||||
|
? (process.env.TEMPLATE_TYPE as TemplateType)
|
||||||
|
: "llamaindexserver";
|
||||||
|
const useCases: TemplateUseCase[] = [
|
||||||
|
"agentic_rag",
|
||||||
|
"deep_research",
|
||||||
|
"financial_report",
|
||||||
|
"code_generator",
|
||||||
|
"document_generator",
|
||||||
|
];
|
||||||
|
const dataSource: string = process.env.DATASOURCE
|
||||||
|
? process.env.DATASOURCE
|
||||||
|
: "--example-file";
|
||||||
|
|
||||||
|
// vectorDBs combinations to test
|
||||||
|
const vectorDbs: TemplateVectorDB[] = [
|
||||||
|
"mongo",
|
||||||
|
"pg",
|
||||||
|
"qdrant",
|
||||||
|
"pinecone",
|
||||||
|
"milvus",
|
||||||
|
"astra",
|
||||||
|
"chroma",
|
||||||
|
"llamacloud",
|
||||||
|
"weaviate",
|
||||||
|
];
|
||||||
|
|
||||||
|
test.describe("Test resolve TS dependencies", () => {
|
||||||
|
test.describe.configure({ retries: 0 });
|
||||||
|
|
||||||
|
// Test vector DBs without LlamaParse
|
||||||
|
for (const vectorDb of vectorDbs) {
|
||||||
|
const optionDescription = `templateType: ${templateType}, vectorDb: ${vectorDb}, dataSource: ${dataSource}`;
|
||||||
|
|
||||||
|
test(`Vector DB test - ${optionDescription}`, async () => {
|
||||||
|
// skip vectordb test for llamaindexserver
|
||||||
|
test.skip(
|
||||||
|
templateType === "llamaindexserver",
|
||||||
|
"skipping vectorDB test for llamaindexserver",
|
||||||
|
);
|
||||||
|
|
||||||
|
await runTest({
|
||||||
|
templateType: templateType,
|
||||||
|
useLlamaParse: false, // Disable LlamaParse for vectorDB test
|
||||||
|
vectorDb: vectorDb,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// No vectorDB, with LlamaParse and useCase
|
||||||
|
// Only need to test use case with example data source
|
||||||
|
if (dataSource === "--example-file") {
|
||||||
|
for (const useCase of useCases) {
|
||||||
|
const optionDescription = `templateType: ${templateType}, useCase: ${useCase}`;
|
||||||
|
test.describe(`useCase test - ${optionDescription}`, () => {
|
||||||
|
test.skip(
|
||||||
|
templateType === "streaming",
|
||||||
|
"Skipping use case test for streaming template.",
|
||||||
|
);
|
||||||
|
test(`no llamaParse - ${optionDescription}`, async () => {
|
||||||
|
await runTest({
|
||||||
|
templateType: templateType,
|
||||||
|
useLlamaParse: false,
|
||||||
|
useCase: useCase,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// Skipping llamacloud for the use case doesn't use index.
|
||||||
|
if (useCase !== "code_generator" && useCase !== "document_generator") {
|
||||||
|
test(`llamaParse - ${optionDescription}`, async () => {
|
||||||
|
await runTest({
|
||||||
|
templateType: templateType,
|
||||||
|
useLlamaParse: true,
|
||||||
|
useCase: useCase,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function runTest(options: {
|
||||||
|
templateType: TemplateType;
|
||||||
|
useLlamaParse: boolean;
|
||||||
|
useCase?: TemplateUseCase;
|
||||||
|
vectorDb?: TemplateVectorDB;
|
||||||
|
}) {
|
||||||
|
const cwd = await createTestDir();
|
||||||
|
|
||||||
|
const result = await runCreateLlama({
|
||||||
|
cwd: cwd,
|
||||||
|
templateType: options.templateType,
|
||||||
|
templateFramework: templateFramework,
|
||||||
|
dataSource: dataSource,
|
||||||
|
vectorDb: options.vectorDb ?? "none",
|
||||||
|
port: 3000,
|
||||||
|
postInstallAction: "none",
|
||||||
|
templateUI: undefined,
|
||||||
|
appType: templateFramework === "nextjs" ? "" : "--no-frontend",
|
||||||
|
llamaCloudProjectName: undefined,
|
||||||
|
llamaCloudIndexName: undefined,
|
||||||
|
tools: undefined,
|
||||||
|
useLlamaParse: options.useLlamaParse,
|
||||||
|
useCase: options.useCase,
|
||||||
|
});
|
||||||
|
const name = result.projectName;
|
||||||
|
|
||||||
|
// Check if the app folder exists
|
||||||
|
const appDir = path.join(cwd, name);
|
||||||
|
const dirExists = fs.existsSync(appDir);
|
||||||
|
expect(dirExists).toBeTruthy();
|
||||||
|
|
||||||
|
// Install dependencies using pnpm
|
||||||
|
try {
|
||||||
|
const { stderr: installStderr } = await execAsync(
|
||||||
|
"pnpm install --prefer-offline --ignore-workspace",
|
||||||
|
{
|
||||||
|
cwd: appDir,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error installing dependencies:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run tsc type check and capture the output
|
||||||
|
try {
|
||||||
|
const { stdout, stderr } = await execAsync(
|
||||||
|
"pnpm exec tsc -b --diagnostics",
|
||||||
|
{
|
||||||
|
cwd: appDir,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
// Check if there's any error output
|
||||||
|
expect(stderr).toBeFalsy();
|
||||||
|
|
||||||
|
// Log the stdout for debugging purposes
|
||||||
|
console.log("TypeScript type-check output:", stdout);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error running tsc:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,8 +67,8 @@ export async function runCreateLlama({
|
|||||||
].join("-");
|
].join("-");
|
||||||
|
|
||||||
// Handle different data source types
|
// Handle different data source types
|
||||||
let dataSourceArgs = [];
|
const dataSourceArgs = [];
|
||||||
if (dataSource.includes("--web-source" || "--db-source")) {
|
if (dataSource.includes("--web-source")) {
|
||||||
const webSource = dataSource.split(" ")[1];
|
const webSource = dataSource.split(" ")[1];
|
||||||
dataSourceArgs.push("--web-source", webSource);
|
dataSourceArgs.push("--web-source", webSource);
|
||||||
} else if (dataSource.includes("--db-source")) {
|
} else if (dataSource.includes("--db-source")) {
|
||||||
@@ -113,7 +113,12 @@ export async function runCreateLlama({
|
|||||||
if (observability) {
|
if (observability) {
|
||||||
commandArgs.push("--observability", observability);
|
commandArgs.push("--observability", observability);
|
||||||
}
|
}
|
||||||
if ((templateType === "multiagent" || templateType === "reflex") && useCase) {
|
if (
|
||||||
|
(templateType === "multiagent" ||
|
||||||
|
templateType === "reflex" ||
|
||||||
|
templateType === "llamaindexserver") &&
|
||||||
|
useCase
|
||||||
|
) {
|
||||||
commandArgs.push("--use-case", useCase);
|
commandArgs.push("--use-case", useCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable import/no-extraneous-dependencies */
|
|
||||||
import { async as glob } from "fast-glob";
|
import { async as glob } from "fast-glob";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
@@ -44,6 +44,7 @@ const renderEnvVar = (envVars: EnvVar[]): string => {
|
|||||||
const getVectorDBEnvs = (
|
const getVectorDBEnvs = (
|
||||||
vectorDb?: TemplateVectorDB,
|
vectorDb?: TemplateVectorDB,
|
||||||
framework?: TemplateFramework,
|
framework?: TemplateFramework,
|
||||||
|
template?: TemplateType,
|
||||||
): EnvVar[] => {
|
): EnvVar[] => {
|
||||||
if (!vectorDb || !framework) {
|
if (!vectorDb || !framework) {
|
||||||
return [];
|
return [];
|
||||||
@@ -168,7 +169,7 @@ const getVectorDBEnvs = (
|
|||||||
description:
|
description:
|
||||||
"The organization ID for the LlamaCloud project (uses default organization if not specified)",
|
"The organization ID for the LlamaCloud project (uses default organization if not specified)",
|
||||||
},
|
},
|
||||||
...(framework === "nextjs"
|
...(framework === "nextjs" && template !== "llamaindexserver"
|
||||||
? // activate index selector per default (not needed for non-NextJS backends as it's handled by createFrontendEnvFile)
|
? // activate index selector per default (not needed for non-NextJS backends as it's handled by createFrontendEnvFile)
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -180,7 +181,7 @@ const getVectorDBEnvs = (
|
|||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
];
|
];
|
||||||
case "chroma":
|
case "chroma": {
|
||||||
const envs = [
|
const envs = [
|
||||||
{
|
{
|
||||||
name: "CHROMA_COLLECTION",
|
name: "CHROMA_COLLECTION",
|
||||||
@@ -205,6 +206,7 @@ Otherwise, use CHROMA_HOST and CHROMA_PORT config above`,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
return envs;
|
return envs;
|
||||||
|
}
|
||||||
case "weaviate":
|
case "weaviate":
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -223,13 +225,15 @@ Otherwise, use CHROMA_HOST and CHROMA_PORT config above`,
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
default:
|
default:
|
||||||
return [
|
return template !== "llamaindexserver"
|
||||||
{
|
? [
|
||||||
name: "STORAGE_CACHE_DIR",
|
{
|
||||||
description: "The directory to store the local storage cache.",
|
name: "STORAGE_CACHE_DIR",
|
||||||
value: ".cache",
|
description: "The directory to store the local storage cache.",
|
||||||
},
|
value: ".cache",
|
||||||
];
|
},
|
||||||
|
]
|
||||||
|
: [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -382,38 +386,42 @@ const getModelEnvs = (modelConfig: ModelConfig): EnvVar[] => {
|
|||||||
|
|
||||||
const getFrameworkEnvs = (
|
const getFrameworkEnvs = (
|
||||||
framework: TemplateFramework,
|
framework: TemplateFramework,
|
||||||
|
template: TemplateType,
|
||||||
port?: number,
|
port?: number,
|
||||||
): EnvVar[] => {
|
): EnvVar[] => {
|
||||||
const sPort = port?.toString() || "8000";
|
const sPort = port?.toString() || "8000";
|
||||||
const result: EnvVar[] = [
|
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.",
|
name: "FILESERVER_URL_PREFIX",
|
||||||
value:
|
description:
|
||||||
framework === "nextjs"
|
"FILESERVER_URL_PREFIX is the URL prefix of the server storing the images generated by the interpreter.",
|
||||||
? // FIXME: if we are using nextjs, port should be 3000
|
value:
|
||||||
"http://localhost:3000/api/files"
|
framework === "nextjs"
|
||||||
: `http://localhost:${sPort}/api/files`,
|
? // FIXME: if we are using nextjs, port should be 3000
|
||||||
},
|
"http://localhost:3000/api/files"
|
||||||
];
|
: `http://localhost:${sPort}/api/files`,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: [];
|
||||||
if (framework === "fastapi") {
|
if (framework === "fastapi") {
|
||||||
result.push(
|
result.push(
|
||||||
...[
|
...[
|
||||||
{
|
{
|
||||||
name: "APP_HOST",
|
name: "APP_HOST",
|
||||||
description: "The address to start the backend app.",
|
description: "The address to start the FastAPI app.",
|
||||||
value: "0.0.0.0",
|
value: "0.0.0.0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "APP_PORT",
|
name: "APP_PORT",
|
||||||
description: "The port to start the backend app.",
|
description: "The port to start the FastAPI app.",
|
||||||
value: sPort,
|
value: sPort,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (framework === "nextjs") {
|
if (framework === "nextjs" && template !== "llamaindexserver") {
|
||||||
result.push({
|
result.push({
|
||||||
name: "NEXT_PUBLIC_CHAT_API",
|
name: "NEXT_PUBLIC_CHAT_API",
|
||||||
description:
|
description:
|
||||||
@@ -569,25 +577,41 @@ export const createBackendEnvFile = async (
|
|||||||
| "port"
|
| "port"
|
||||||
| "tools"
|
| "tools"
|
||||||
| "observability"
|
| "observability"
|
||||||
|
| "useLlamaParse"
|
||||||
>,
|
>,
|
||||||
) => {
|
) => {
|
||||||
// Init env values
|
// Init env values
|
||||||
const envFileName = ".env";
|
const envFileName = ".env";
|
||||||
const envVars: EnvVar[] = [
|
const envVars: EnvVar[] = [
|
||||||
{
|
...(opts.useLlamaParse
|
||||||
name: "LLAMA_CLOUD_API_KEY",
|
? [
|
||||||
description: `The Llama Cloud API key.`,
|
{
|
||||||
value: opts.llamaCloudKey,
|
name: "LLAMA_CLOUD_API_KEY",
|
||||||
},
|
description: `The Llama Cloud API key.`,
|
||||||
// Add environment variables of each component
|
value: opts.llamaCloudKey,
|
||||||
...getModelEnvs(opts.modelConfig),
|
},
|
||||||
...getEngineEnvs(),
|
]
|
||||||
...getVectorDBEnvs(opts.vectorDb, opts.framework),
|
: []),
|
||||||
...getFrameworkEnvs(opts.framework, opts.port),
|
...getVectorDBEnvs(opts.vectorDb, opts.framework, opts.template),
|
||||||
...getToolEnvs(opts.tools),
|
...getToolEnvs(opts.tools),
|
||||||
...getTemplateEnvs(opts.template),
|
...getFrameworkEnvs(opts.framework, opts.template, opts.port),
|
||||||
...getObservabilityEnvs(opts.observability),
|
// Add environment variables of each component
|
||||||
...getSystemPromptEnv(opts.tools, opts.dataSources, opts.template),
|
...(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),
|
||||||
|
]),
|
||||||
];
|
];
|
||||||
// Render and write env file
|
// Render and write env file
|
||||||
const content = renderEnvVar(envVars);
|
const content = renderEnvVar(envVars);
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable import/no-extraneous-dependencies */
|
|
||||||
import { execSync } from "child_process";
|
import { execSync } from "child_process";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { callPackageManager } from "./install";
|
import { callPackageManager } from "./install";
|
||||||
|
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { cyan } from "picocolors";
|
import picocolors, { cyan } from "picocolors";
|
||||||
|
|
||||||
import fsExtra from "fs-extra";
|
import fsExtra from "fs-extra";
|
||||||
import { writeLoadersConfig } from "./datasources";
|
import { writeLoadersConfig } from "./datasources";
|
||||||
@@ -9,7 +9,6 @@ import { createBackendEnvFile, createFrontendEnvFile } from "./env-variables";
|
|||||||
import { PackageManager } from "./get-pkg-manager";
|
import { PackageManager } from "./get-pkg-manager";
|
||||||
import { installLlamapackProject } from "./llama-pack";
|
import { installLlamapackProject } from "./llama-pack";
|
||||||
import { makeDir } from "./make-dir";
|
import { makeDir } from "./make-dir";
|
||||||
import { isHavingPoetryLockFile, tryPoetryRun } from "./poetry";
|
|
||||||
import { installPythonTemplate } from "./python";
|
import { installPythonTemplate } from "./python";
|
||||||
import { downloadAndExtractRepo } from "./repo";
|
import { downloadAndExtractRepo } from "./repo";
|
||||||
import { ConfigFileType, writeToolsConfig } from "./tools";
|
import { ConfigFileType, writeToolsConfig } from "./tools";
|
||||||
@@ -19,9 +18,11 @@ import {
|
|||||||
ModelConfig,
|
ModelConfig,
|
||||||
TemplateDataSource,
|
TemplateDataSource,
|
||||||
TemplateFramework,
|
TemplateFramework,
|
||||||
|
TemplateUseCase,
|
||||||
TemplateVectorDB,
|
TemplateVectorDB,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import { installTSTemplate } from "./typescript";
|
import { installTSTemplate } from "./typescript";
|
||||||
|
import { isHavingUvLockFile, tryUvRun } from "./uv";
|
||||||
|
|
||||||
const checkForGenerateScript = (
|
const checkForGenerateScript = (
|
||||||
modelConfig: ModelConfig,
|
modelConfig: ModelConfig,
|
||||||
@@ -41,7 +42,11 @@ const checkForGenerateScript = (
|
|||||||
missingSettings.push("your LLAMA_CLOUD_API_KEY");
|
missingSettings.push("your LLAMA_CLOUD_API_KEY");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vectorDb !== "none" && vectorDb !== "llamacloud") {
|
if (
|
||||||
|
vectorDb !== undefined &&
|
||||||
|
vectorDb !== "none" &&
|
||||||
|
vectorDb !== "llamacloud"
|
||||||
|
) {
|
||||||
missingSettings.push("your Vector DB environment variables");
|
missingSettings.push("your Vector DB environment variables");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,11 +61,12 @@ async function generateContextData(
|
|||||||
vectorDb?: TemplateVectorDB,
|
vectorDb?: TemplateVectorDB,
|
||||||
llamaCloudKey?: string,
|
llamaCloudKey?: string,
|
||||||
useLlamaParse?: boolean,
|
useLlamaParse?: boolean,
|
||||||
|
useCase?: TemplateUseCase,
|
||||||
) {
|
) {
|
||||||
if (packageManager) {
|
if (packageManager) {
|
||||||
const runGenerate = `${cyan(
|
const runGenerate = `${cyan(
|
||||||
framework === "fastapi"
|
framework === "fastapi"
|
||||||
? "poetry run generate"
|
? "uv run generate"
|
||||||
: `${packageManager} run generate`,
|
: `${packageManager} run generate`,
|
||||||
)}`;
|
)}`;
|
||||||
|
|
||||||
@@ -74,32 +80,43 @@ async function generateContextData(
|
|||||||
if (!missingSettings.length) {
|
if (!missingSettings.length) {
|
||||||
// If all the required environment variables are set, run the generate script
|
// If all the required environment variables are set, run the generate script
|
||||||
if (framework === "fastapi") {
|
if (framework === "fastapi") {
|
||||||
if (isHavingPoetryLockFile()) {
|
if (isHavingUvLockFile()) {
|
||||||
console.log(`Running ${runGenerate} to generate the context data.`);
|
console.log(`Running ${runGenerate} to generate the context data.`);
|
||||||
const result = tryPoetryRun("poetry run generate");
|
const result = tryUvRun("generate");
|
||||||
if (!result) {
|
if (!result) {
|
||||||
console.log(`Failed to run ${runGenerate}.`);
|
console.log(`Failed to run ${runGenerate}.`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
console.log(`Generated context data`);
|
console.log(`Generated context data`);
|
||||||
return;
|
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 {
|
} else {
|
||||||
console.log(`Running ${runGenerate} to generate the context data.`);
|
console.log(`Running ${runGenerate} to generate the context data.`);
|
||||||
await callPackageManager(packageManager, true, ["run", "generate"]);
|
const shouldRunGenerate =
|
||||||
|
useCase !== "code_generator" && useCase !== "document_generator"; // Artifact use case doesn't use index.
|
||||||
|
|
||||||
|
if (shouldRunGenerate) {
|
||||||
|
await callPackageManager(packageManager, true, ["run", "generate"]);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const settingsMessage = `After setting ${missingSettings.join(" and ")}, run ${runGenerate} to generate the context data.`;
|
const settingsMessage = `After setting ${missingSettings.join(" and ")}, run ${runGenerate} to generate the context data.`;
|
||||||
console.log(`\n${settingsMessage}\n\n`);
|
console.log(picocolors.yellow(`\n${settingsMessage}\n\n`));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const downloadFile = async (url: string, destPath: string) => {
|
const downloadFile = async (url: string, destPath: string) => {
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
const fileBuffer = await response.arrayBuffer();
|
const fileBuffer = await response.arrayBuffer();
|
||||||
await fsExtra.writeFile(destPath, Buffer.from(fileBuffer));
|
await fsExtra.writeFile(destPath, new Uint8Array(fileBuffer));
|
||||||
};
|
};
|
||||||
|
|
||||||
const prepareContextData = async (
|
const prepareContextData = async (
|
||||||
@@ -166,6 +183,17 @@ export const installTemplate = async (
|
|||||||
|
|
||||||
if (props.framework === "fastapi") {
|
if (props.framework === "fastapi") {
|
||||||
await installPythonTemplate(props);
|
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") {
|
if (props.vectorDb !== "llamacloud") {
|
||||||
// write loaders configuration (currently Python only)
|
// write loaders configuration (currently Python only)
|
||||||
// not needed for LlamaCloud as it has its own loaders
|
// not needed for LlamaCloud as it has its own loaders
|
||||||
@@ -175,26 +203,13 @@ export const installTemplate = async (
|
|||||||
props.useLlamaParse,
|
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) {
|
if (props.backend) {
|
||||||
// This is a backend, so we need to copy the test data and create the env file.
|
// 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.
|
// Copy the environment file to the target directory.
|
||||||
if (
|
if (props.template !== "community" && props.template !== "llamapack") {
|
||||||
props.template === "streaming" ||
|
|
||||||
props.template === "multiagent" ||
|
|
||||||
props.template === "reflex"
|
|
||||||
) {
|
|
||||||
await createBackendEnvFile(props.root, props);
|
await createBackendEnvFile(props.root, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,6 +231,7 @@ export const installTemplate = async (
|
|||||||
props.vectorDb,
|
props.vectorDb,
|
||||||
props.llamaCloudKey,
|
props.llamaCloudKey,
|
||||||
props.useLlamaParse,
|
props.useLlamaParse,
|
||||||
|
props.useCase,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable import/no-extraneous-dependencies */
|
|
||||||
import spawn from "cross-spawn";
|
import spawn from "cross-spawn";
|
||||||
import { yellow } from "picocolors";
|
import { yellow } from "picocolors";
|
||||||
import type { PackageManager } from "./get-pkg-manager";
|
import type { PackageManager } from "./get-pkg-manager";
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable import/no-extraneous-dependencies */
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { blue, green } from "picocolors";
|
import { blue, green } from "picocolors";
|
||||||
@@ -143,6 +143,6 @@ export const installLlamapackProject = async ({
|
|||||||
await copyData({ root });
|
await copyData({ root });
|
||||||
await installLlamapackExample({ root, llamapack });
|
await installLlamapackExample({ root, llamapack });
|
||||||
if (postInstallAction === "runApp" || postInstallAction === "dependencies") {
|
if (postInstallAction === "runApp" || postInstallAction === "dependencies") {
|
||||||
installPythonDependencies({ noRoot: true });
|
installPythonDependencies();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable import/no-extraneous-dependencies */
|
|
||||||
import { execSync } from "child_process";
|
import { execSync } from "child_process";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ export async function askModelConfig({
|
|||||||
}: ModelConfigQuestionsParams): Promise<ModelConfig> {
|
}: ModelConfigQuestionsParams): Promise<ModelConfig> {
|
||||||
let modelProvider: ModelProvider = DEFAULT_MODEL_PROVIDER;
|
let modelProvider: ModelProvider = DEFAULT_MODEL_PROVIDER;
|
||||||
if (askModels) {
|
if (askModels) {
|
||||||
let choices = [
|
const choices = [
|
||||||
{ title: "OpenAI", value: "openai" },
|
{ title: "OpenAI", value: "openai" },
|
||||||
{ title: "Groq", value: "groq" },
|
{ title: "Groq", value: "groq" },
|
||||||
{ title: "Ollama", value: "ollama" },
|
{ title: "Ollama", value: "ollama" },
|
||||||
@@ -3,15 +3,16 @@ import path from "path";
|
|||||||
import { cyan, red } from "picocolors";
|
import { cyan, red } from "picocolors";
|
||||||
import { parse, stringify } from "smol-toml";
|
import { parse, stringify } from "smol-toml";
|
||||||
import terminalLink from "terminal-link";
|
import terminalLink from "terminal-link";
|
||||||
|
import { isUvAvailable, tryUvSync } from "./uv";
|
||||||
|
|
||||||
import { assetRelocator, copy } from "./copy";
|
import { assetRelocator, copy } from "./copy";
|
||||||
import { templatesDir } from "./dir";
|
import { templatesDir } from "./dir";
|
||||||
import { isPoetryAvailable, tryPoetryInstall } from "./poetry";
|
|
||||||
import { Tool } from "./tools";
|
import { Tool } from "./tools";
|
||||||
import {
|
import {
|
||||||
InstallTemplateArgs,
|
InstallTemplateArgs,
|
||||||
ModelConfig,
|
ModelConfig,
|
||||||
TemplateDataSource,
|
TemplateDataSource,
|
||||||
|
TemplateObservability,
|
||||||
TemplateType,
|
TemplateType,
|
||||||
TemplateVectorDB,
|
TemplateVectorDB,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
@@ -29,6 +30,8 @@ const getAdditionalDependencies = (
|
|||||||
dataSources?: TemplateDataSource[],
|
dataSources?: TemplateDataSource[],
|
||||||
tools?: Tool[],
|
tools?: Tool[],
|
||||||
templateType?: TemplateType,
|
templateType?: TemplateType,
|
||||||
|
observability?: TemplateObservability,
|
||||||
|
// eslint-disable-next-line max-params
|
||||||
) => {
|
) => {
|
||||||
const dependencies: Dependency[] = [];
|
const dependencies: Dependency[] = [];
|
||||||
|
|
||||||
@@ -37,21 +40,21 @@ const getAdditionalDependencies = (
|
|||||||
case "mongo": {
|
case "mongo": {
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-vector-stores-mongodb",
|
name: "llama-index-vector-stores-mongodb",
|
||||||
version: "^0.6.0",
|
version: ">=0.3.2,<0.4.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "pg": {
|
case "pg": {
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-vector-stores-postgres",
|
name: "llama-index-vector-stores-postgres",
|
||||||
version: "^0.3.2",
|
version: ">=0.3.2,<0.4.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "pinecone": {
|
case "pinecone": {
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-vector-stores-pinecone",
|
name: "llama-index-vector-stores-pinecone",
|
||||||
version: "^0.4.1",
|
version: ">=0.4.1,<0.5.0",
|
||||||
constraints: {
|
constraints: {
|
||||||
python: ">=3.11,<3.13",
|
python: ">=3.11,<3.13",
|
||||||
},
|
},
|
||||||
@@ -61,25 +64,25 @@ const getAdditionalDependencies = (
|
|||||||
case "milvus": {
|
case "milvus": {
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-vector-stores-milvus",
|
name: "llama-index-vector-stores-milvus",
|
||||||
version: "^0.3.0",
|
version: ">=0.3.0,<0.4.0",
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "pymilvus",
|
name: "pymilvus",
|
||||||
version: "2.4.4",
|
version: ">=2.4.4,<3.0.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "astra": {
|
case "astra": {
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-vector-stores-astra-db",
|
name: "llama-index-vector-stores-astra-db",
|
||||||
version: "^0.4.0",
|
version: ">=0.4.0,<0.5.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "qdrant": {
|
case "qdrant": {
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-vector-stores-qdrant",
|
name: "llama-index-vector-stores-qdrant",
|
||||||
version: "^0.4.0",
|
version: ">=0.4.0,<0.5.0",
|
||||||
constraints: {
|
constraints: {
|
||||||
python: ">=3.11,<3.13",
|
python: ">=3.11,<3.13",
|
||||||
},
|
},
|
||||||
@@ -89,21 +92,25 @@ const getAdditionalDependencies = (
|
|||||||
case "chroma": {
|
case "chroma": {
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-vector-stores-chroma",
|
name: "llama-index-vector-stores-chroma",
|
||||||
version: "^0.4.0",
|
version: ">=0.4.0,<0.5.0",
|
||||||
|
});
|
||||||
|
dependencies.push({
|
||||||
|
name: "onnxruntime",
|
||||||
|
version: "<1.22.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "weaviate": {
|
case "weaviate": {
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-vector-stores-weaviate",
|
name: "llama-index-vector-stores-weaviate",
|
||||||
version: "^1.2.3",
|
version: ">=1.2.3,<2.0.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "llamacloud":
|
case "llamacloud":
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-indices-managed-llama-cloud",
|
name: "llama-index-indices-managed-llama-cloud",
|
||||||
version: "^0.6.3",
|
version: ">=0.6.3,<0.7.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -116,28 +123,28 @@ const getAdditionalDependencies = (
|
|||||||
case "file":
|
case "file":
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "docx2txt",
|
name: "docx2txt",
|
||||||
version: "^0.8",
|
version: ">=0.8,<0.9",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "web":
|
case "web":
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-readers-web",
|
name: "llama-index-readers-web",
|
||||||
version: "^0.3.0",
|
version: ">=0.3.0,<0.4.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "db":
|
case "db":
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-readers-database",
|
name: "llama-index-readers-database",
|
||||||
version: "^0.3.0",
|
version: ">=0.3.0,<0.4.0",
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "pymysql",
|
name: "pymysql",
|
||||||
version: "^1.1.0",
|
version: ">=1.1.0,<2.0.0",
|
||||||
extras: ["rsa"],
|
extras: ["rsa"],
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "psycopg2-binary",
|
name: "psycopg2-binary",
|
||||||
version: "^2.9.9",
|
version: ">=2.9.9,<3.0.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -156,155 +163,122 @@ const getAdditionalDependencies = (
|
|||||||
case "ollama":
|
case "ollama":
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-llms-ollama",
|
name: "llama-index-llms-ollama",
|
||||||
version: "0.3.0",
|
version: ">=0.5.0,<0.6.0",
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-embeddings-ollama",
|
name: "llama-index-embeddings-ollama",
|
||||||
version: "0.3.0",
|
version: ">=0.6.0,<0.7.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "openai":
|
case "openai":
|
||||||
if (templateType !== "multiagent") {
|
if (templateType !== "multiagent") {
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-llms-openai",
|
name: "llama-index-llms-openai",
|
||||||
version: "^0.3.2",
|
version: ">=0.3.2,<0.4.0",
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-embeddings-openai",
|
name: "llama-index-embeddings-openai",
|
||||||
version: "^0.3.1",
|
version: ">=0.3.1,<0.4.0",
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-agent-openai",
|
name: "llama-index-agent-openai",
|
||||||
version: "^0.4.0",
|
version: ">=0.4.0,<0.5.0",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "groq":
|
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({
|
dependencies.push({
|
||||||
name: "llama-index-llms-groq",
|
name: "llama-index-llms-groq",
|
||||||
version: "0.2.0",
|
version: ">=0.3.0,<0.4.0",
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-embeddings-fastembed",
|
name: "llama-index-embeddings-fastembed",
|
||||||
version: "^0.2.0",
|
version: ">=0.3.0,<0.4.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "anthropic":
|
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({
|
dependencies.push({
|
||||||
name: "llama-index-llms-anthropic",
|
name: "llama-index-llms-anthropic",
|
||||||
version: "0.3.0",
|
version: ">=0.6.0,<0.7.0",
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-embeddings-fastembed",
|
name: "llama-index-embeddings-fastembed",
|
||||||
version: "^0.2.0",
|
version: ">=0.3.0,<0.4.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "gemini":
|
case "gemini":
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-llms-gemini",
|
name: "llama-index-llms-gemini",
|
||||||
version: "0.3.4",
|
version: ">=0.4.0,<0.5.0",
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-embeddings-gemini",
|
name: "llama-index-embeddings-gemini",
|
||||||
version: "^0.2.0",
|
version: ">=0.3.0,<0.4.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "mistral":
|
case "mistral":
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-llms-mistralai",
|
name: "llama-index-llms-mistralai",
|
||||||
version: "0.2.1",
|
version: ">=0.4.0,<0.5.0",
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-embeddings-mistralai",
|
name: "llama-index-embeddings-mistralai",
|
||||||
version: "0.2.0",
|
version: ">=0.3.0,<0.4.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "azure-openai":
|
case "azure-openai":
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-llms-azure-openai",
|
name: "llama-index-llms-azure-openai",
|
||||||
version: "0.2.0",
|
version: ">=0.3.0,<0.4.0",
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-embeddings-azure-openai",
|
name: "llama-index-embeddings-azure-openai",
|
||||||
version: "0.2.4",
|
version: ">=0.3.0,<0.4.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "huggingface":
|
case "huggingface":
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-llms-huggingface",
|
name: "llama-index-llms-huggingface",
|
||||||
version: "^0.3.5",
|
version: ">=0.5.0,<0.6.0",
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-embeddings-huggingface",
|
name: "llama-index-embeddings-huggingface",
|
||||||
version: "^0.3.1",
|
version: ">=0.5.0,<0.6.0",
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "optimum",
|
name: "optimum",
|
||||||
version: "^1.23.3",
|
version: ">=1.23.3,<2.0.0",
|
||||||
extras: ["onnxruntime"],
|
extras: ["onnxruntime"],
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "t-systems":
|
case "t-systems":
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-agent-openai",
|
name: "llama-index-agent-openai",
|
||||||
version: "0.3.0",
|
version: ">=0.4.0,<0.5.0",
|
||||||
});
|
});
|
||||||
dependencies.push({
|
dependencies.push({
|
||||||
name: "llama-index-llms-openai-like",
|
name: "llama-index-llms-openai-like",
|
||||||
version: "0.2.0",
|
version: ">=0.3.0,<0.4.0",
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dependencies;
|
if (observability && observability !== "none") {
|
||||||
};
|
if (observability === "traceloop") {
|
||||||
|
dependencies.push({
|
||||||
const mergePoetryDependencies = (
|
name: "traceloop-sdk",
|
||||||
dependencies: Dependency[],
|
version: ">=0.15.11",
|
||||||
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") {
|
||||||
value.version = dependency.version ?? value.version;
|
dependencies.push({
|
||||||
value.extras = dependency.extras ?? value.extras;
|
name: "llama-index-callbacks-arize-phoenix",
|
||||||
|
version: ">=0.3.0,<0.4.0",
|
||||||
// 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[]) => {
|
const copyRouterCode = async (root: string, tools: Tool[]) => {
|
||||||
@@ -329,19 +303,100 @@ export const addDependencies = async (
|
|||||||
// Parse toml file
|
// Parse toml file
|
||||||
const file = path.join(projectDir, FILENAME);
|
const file = path.join(projectDir, FILENAME);
|
||||||
const fileContent = await fs.readFile(file, "utf8");
|
const fileContent = await fs.readFile(file, "utf8");
|
||||||
const fileParsed = parse(fileContent);
|
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.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Modify toml dependencies
|
// Ensure [project] and [project.dependencies] exist
|
||||||
const tool = fileParsed.tool as any;
|
if (!fileParsed.project) {
|
||||||
const existingDependencies = tool.poetry.dependencies;
|
fileParsed.project = {};
|
||||||
mergePoetryDependencies(dependencies, existingDependencies);
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Write toml file
|
// Write toml file
|
||||||
const newFileContent = stringify(fileParsed);
|
const newFileContent = stringify(fileParsed);
|
||||||
await fs.writeFile(file, newFileContent);
|
await fs.writeFile(file, newFileContent);
|
||||||
|
|
||||||
const dependenciesString = dependencies.map((d) => d.name).join(", ");
|
if (addedDeps.length > 0) {
|
||||||
console.log(`\nAdded ${dependenciesString} to ${cyan(FILENAME)}\n`);
|
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
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(
|
console.log(
|
||||||
`Error while updating dependencies for Poetry project file ${FILENAME}\n`,
|
`Error while updating dependencies for Poetry project file ${FILENAME}\n`,
|
||||||
@@ -350,18 +405,16 @@ export const addDependencies = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const installPythonDependencies = (
|
export const installPythonDependencies = () => {
|
||||||
{ noRoot }: { noRoot: boolean } = { noRoot: false },
|
if (isUvAvailable()) {
|
||||||
) => {
|
|
||||||
if (isPoetryAvailable()) {
|
|
||||||
console.log(
|
console.log(
|
||||||
`Installing python dependencies using poetry. This may take a while...`,
|
`Installing Python dependencies using uv. This may take a while...`,
|
||||||
);
|
);
|
||||||
const installSuccessful = tryPoetryInstall(noRoot);
|
const installSuccessful = tryUvSync();
|
||||||
if (!installSuccessful) {
|
if (!installSuccessful) {
|
||||||
console.error(
|
console.error(
|
||||||
red(
|
red(
|
||||||
"Installing dependencies using poetry failed. Please check error log above and try running create-llama again.",
|
"Installing dependencies using uv failed. Please check the error log above and ensure uv is installed correctly.",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@@ -369,57 +422,34 @@ export const installPythonDependencies = (
|
|||||||
} else {
|
} else {
|
||||||
console.error(
|
console.error(
|
||||||
red(
|
red(
|
||||||
`Poetry is not available in the current environment. Please check ${terminalLink(
|
`uv is not available in the current environment. Please check ${terminalLink(
|
||||||
"Poetry Installation",
|
"uv Installation",
|
||||||
`https://python-poetry.org/docs/#installation`,
|
`https://github.com/astral-sh/uv#installation`,
|
||||||
)} to install poetry first, then run create-llama again.`,
|
)} to install uv first, then run create-llama again.`,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const installPythonTemplate = async ({
|
const installLegacyPythonTemplate = async ({
|
||||||
appName,
|
|
||||||
root,
|
root,
|
||||||
template,
|
template,
|
||||||
framework,
|
|
||||||
vectorDb,
|
vectorDb,
|
||||||
postInstallAction,
|
|
||||||
modelConfig,
|
|
||||||
dataSources,
|
dataSources,
|
||||||
tools,
|
tools,
|
||||||
useLlamaParse,
|
|
||||||
useCase,
|
useCase,
|
||||||
observability,
|
observability,
|
||||||
}: Pick<
|
}: Pick<
|
||||||
InstallTemplateArgs,
|
InstallTemplateArgs,
|
||||||
| "appName"
|
|
||||||
| "root"
|
| "root"
|
||||||
| "template"
|
| "template"
|
||||||
| "framework"
|
|
||||||
| "vectorDb"
|
| "vectorDb"
|
||||||
| "postInstallAction"
|
|
||||||
| "modelConfig"
|
|
||||||
| "dataSources"
|
| "dataSources"
|
||||||
| "tools"
|
| "tools"
|
||||||
| "useLlamaParse"
|
|
||||||
| "useCase"
|
| "useCase"
|
||||||
| "observability"
|
| "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 compPath = path.join(templatesDir, "components");
|
||||||
const enginePath = path.join(root, "app", "engine");
|
const enginePath = path.join(root, "app", "engine");
|
||||||
|
|
||||||
@@ -509,34 +539,7 @@ export const installPythonTemplate = async ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Adding additional dependencies");
|
|
||||||
|
|
||||||
const addOnDependencies = getAdditionalDependencies(
|
|
||||||
modelConfig,
|
|
||||||
vectorDb,
|
|
||||||
dataSources,
|
|
||||||
tools,
|
|
||||||
template,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (observability && observability !== "none") {
|
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(
|
const templateObservabilityPath = path.join(
|
||||||
templatesDir,
|
templatesDir,
|
||||||
"components",
|
"components",
|
||||||
@@ -548,6 +551,134 @@ export const installPythonTemplate = async ({
|
|||||||
cwd: templateObservabilityPath,
|
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("*.py", path.join(root, "app"), {
|
||||||
|
parents: true,
|
||||||
|
cwd: path.join(templatesDir, "components", "use-cases", "python", useCase),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Copy custom UI component code
|
||||||
|
await copy(`*`, path.join(root, "components"), {
|
||||||
|
parents: true,
|
||||||
|
cwd: path.join(templatesDir, "components", "ui", "use-cases", 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", "use-cases", "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,
|
||||||
|
observability,
|
||||||
|
);
|
||||||
|
|
||||||
await addDependencies(root, addOnDependencies);
|
await addDependencies(root, addOnDependencies);
|
||||||
|
|
||||||
@@ -34,14 +34,24 @@ export function runReflexApp(appPath: string, port: number) {
|
|||||||
"--frontend-port",
|
"--frontend-port",
|
||||||
port.toString(),
|
port.toString(),
|
||||||
];
|
];
|
||||||
return createProcess("poetry", commandArgs, {
|
return createProcess("uv", commandArgs, {
|
||||||
stdio: "inherit",
|
stdio: "inherit",
|
||||||
cwd: appPath,
|
cwd: appPath,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function runFastAPIApp(appPath: string, port: number) {
|
export function runFastAPIApp(
|
||||||
return createProcess("poetry", ["run", "dev"], {
|
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, {
|
||||||
stdio: "inherit",
|
stdio: "inherit",
|
||||||
cwd: appPath,
|
cwd: appPath,
|
||||||
env: { ...process.env, APP_PORT: `${port}` },
|
env: { ...process.env, APP_PORT: `${port}` },
|
||||||
@@ -73,7 +83,7 @@ export async function runApp(
|
|||||||
: framework === "fastapi"
|
: framework === "fastapi"
|
||||||
? runFastAPIApp
|
? runFastAPIApp
|
||||||
: runTSApp;
|
: runTSApp;
|
||||||
await appRunner(appPath, port || defaultPort);
|
await appRunner(appPath, port || defaultPort, template);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to run app:", error);
|
console.error("Failed to run app:", error);
|
||||||
throw error;
|
throw error;
|
||||||
@@ -41,7 +41,7 @@ export const supportedTools: Tool[] = [
|
|||||||
dependencies: [
|
dependencies: [
|
||||||
{
|
{
|
||||||
name: "llama-index-tools-google",
|
name: "llama-index-tools-google",
|
||||||
version: "^0.3.0",
|
version: ">=0.3.0,<0.4.0",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
supportedFrameworks: ["fastapi"],
|
supportedFrameworks: ["fastapi"],
|
||||||
@@ -62,7 +62,7 @@ export const supportedTools: Tool[] = [
|
|||||||
dependencies: [
|
dependencies: [
|
||||||
{
|
{
|
||||||
name: "duckduckgo-search",
|
name: "duckduckgo-search",
|
||||||
version: "^6.3.5",
|
version: ">=6.3.5,<7.0.0",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
supportedFrameworks: ["fastapi"], // TODO: Re-enable this tool once the duck-duck-scrape TypeScript library works again
|
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: [
|
dependencies: [
|
||||||
{
|
{
|
||||||
name: "llama-index-tools-wikipedia",
|
name: "llama-index-tools-wikipedia",
|
||||||
version: "^0.3.0",
|
version: ">=0.3.0,<0.4.0",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
supportedFrameworks: ["fastapi", "express", "nextjs"],
|
supportedFrameworks: ["fastapi", "express", "nextjs"],
|
||||||
@@ -102,11 +102,11 @@ For better results, you can specify the region parameter to get results from a s
|
|||||||
dependencies: [
|
dependencies: [
|
||||||
{
|
{
|
||||||
name: "xhtml2pdf",
|
name: "xhtml2pdf",
|
||||||
version: "^0.2.14",
|
version: ">=0.2.14,<0.3.0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "markdown",
|
name: "markdown",
|
||||||
version: "^3.7",
|
version: ">=3.7.0,<4.0.0",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
type: ToolType.LOCAL,
|
type: ToolType.LOCAL,
|
||||||
@@ -124,7 +124,7 @@ For better results, you can specify the region parameter to get results from a s
|
|||||||
dependencies: [
|
dependencies: [
|
||||||
{
|
{
|
||||||
name: "e2b_code_interpreter",
|
name: "e2b_code_interpreter",
|
||||||
version: "1.0.3",
|
version: ">=1.1.1,<1.2.0",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
supportedFrameworks: ["fastapi", "express", "nextjs"],
|
supportedFrameworks: ["fastapi", "express", "nextjs"],
|
||||||
@@ -155,7 +155,7 @@ For better results, you can specify the region parameter to get results from a s
|
|||||||
dependencies: [
|
dependencies: [
|
||||||
{
|
{
|
||||||
name: "e2b_code_interpreter",
|
name: "e2b_code_interpreter",
|
||||||
version: "1.0.3",
|
version: ">=1.1.1,<1.2.0",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
supportedFrameworks: ["fastapi", "express", "nextjs"],
|
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",
|
name: "jsonschema",
|
||||||
version: "^4.22.0",
|
version: ">=4.22.0,<5.0.0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "llama-index-tools-requests",
|
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: [
|
dependencies: [
|
||||||
{
|
{
|
||||||
name: "pandas",
|
name: "pandas",
|
||||||
version: "^2.2.3",
|
version: ">=2.2.3,<3.0.0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tabulate",
|
name: "tabulate",
|
||||||
version: "^0.9.0",
|
version: ">=0.9.0,<1.0.0",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -24,7 +24,8 @@ export type TemplateType =
|
|||||||
| "community"
|
| "community"
|
||||||
| "llamapack"
|
| "llamapack"
|
||||||
| "multiagent"
|
| "multiagent"
|
||||||
| "reflex";
|
| "reflex"
|
||||||
|
| "llamaindexserver";
|
||||||
export type TemplateFramework = "nextjs" | "express" | "fastapi";
|
export type TemplateFramework = "nextjs" | "express" | "fastapi";
|
||||||
export type TemplateUI = "html" | "shadcn";
|
export type TemplateUI = "html" | "shadcn";
|
||||||
export type TemplateVectorDB =
|
export type TemplateVectorDB =
|
||||||
@@ -55,7 +56,10 @@ export type TemplateUseCase =
|
|||||||
| "deep_research"
|
| "deep_research"
|
||||||
| "form_filling"
|
| "form_filling"
|
||||||
| "extractor"
|
| "extractor"
|
||||||
| "contract_review";
|
| "contract_review"
|
||||||
|
| "agentic_rag"
|
||||||
|
| "code_generator"
|
||||||
|
| "document_generator";
|
||||||
// Config for both file and folder
|
// Config for both file and folder
|
||||||
export type FileSourceConfig =
|
export type FileSourceConfig =
|
||||||
| {
|
| {
|
||||||
@@ -8,42 +8,101 @@ import { templatesDir } from "./dir";
|
|||||||
import { PackageManager } from "./get-pkg-manager";
|
import { PackageManager } from "./get-pkg-manager";
|
||||||
import { InstallTemplateArgs, ModelProvider, TemplateVectorDB } from "./types";
|
import { InstallTemplateArgs, ModelProvider, TemplateVectorDB } from "./types";
|
||||||
|
|
||||||
/**
|
const installLlamaIndexServerTemplate = async ({
|
||||||
* Install a LlamaIndex internal template to a given `root` directory.
|
root,
|
||||||
*/
|
useCase,
|
||||||
export const installTSTemplate = async ({
|
vectorDb,
|
||||||
appName,
|
}: 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("**", path.join(root), {
|
||||||
|
cwd: path.join(
|
||||||
|
templatesDir,
|
||||||
|
"components",
|
||||||
|
"use-cases",
|
||||||
|
"typescript",
|
||||||
|
useCase,
|
||||||
|
),
|
||||||
|
rename: assetRelocator,
|
||||||
|
});
|
||||||
|
|
||||||
|
// copy workflow UI components to output/components folder
|
||||||
|
await copy("*", path.join(root, "components"), {
|
||||||
|
parents: true,
|
||||||
|
cwd: path.join(templatesDir, "components", "ui", "use-cases", useCase),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Override generate.ts if workflow use case doesn't use custom UI
|
||||||
|
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",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simplify use case code
|
||||||
|
if (useCase === "code_generator" || useCase === "document_generator") {
|
||||||
|
// Artifact use case doesn't use index.
|
||||||
|
// We don't need data.ts, generate.ts
|
||||||
|
await fs.rm(path.join(root, "src", "app", "data.ts"));
|
||||||
|
// TODO: Remove generate index in generate.ts and package.json if possible
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const installLegacyTSTemplate = async ({
|
||||||
root,
|
root,
|
||||||
packageManager,
|
|
||||||
isOnline,
|
|
||||||
template,
|
template,
|
||||||
|
backend,
|
||||||
framework,
|
framework,
|
||||||
ui,
|
ui,
|
||||||
vectorDb,
|
vectorDb,
|
||||||
postInstallAction,
|
|
||||||
backend,
|
|
||||||
observability,
|
observability,
|
||||||
tools,
|
tools,
|
||||||
dataSources,
|
dataSources,
|
||||||
useLlamaParse,
|
useLlamaParse,
|
||||||
useCase,
|
useCase,
|
||||||
modelConfig,
|
modelConfig,
|
||||||
}: InstallTemplateArgs & { backend: boolean }) => {
|
relativeEngineDestPath,
|
||||||
console.log(bold(`Using ${packageManager}.`));
|
}: InstallTemplateArgs & {
|
||||||
|
backend: boolean;
|
||||||
/**
|
relativeEngineDestPath: string;
|
||||||
* 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
|
* If next.js is used, update its configuration if necessary
|
||||||
*/
|
*/
|
||||||
@@ -98,10 +157,6 @@ export const installTSTemplate = async ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const compPath = path.join(templatesDir, "components");
|
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");
|
const enginePath = path.join(root, relativeEngineDestPath, "engine");
|
||||||
|
|
||||||
// copy llamaindex code for TS templates
|
// copy llamaindex code for TS templates
|
||||||
@@ -236,6 +291,75 @@ export const installTSTemplate = async ({
|
|||||||
await fs.rm(path.join(root, "app", "api"), { recursive: true });
|
await fs.rm(path.join(root, "app", "api"), { recursive: true });
|
||||||
await fs.rm(path.join(root, "config"), { recursive: true, force: 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({
|
const packageJson = await updatePackageJson({
|
||||||
root,
|
root,
|
||||||
@@ -248,6 +372,7 @@ export const installTSTemplate = async ({
|
|||||||
vectorDb,
|
vectorDb,
|
||||||
backend,
|
backend,
|
||||||
modelConfig,
|
modelConfig,
|
||||||
|
template,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -262,27 +387,27 @@ const providerDependencies: {
|
|||||||
[key in ModelProvider]?: Record<string, string>;
|
[key in ModelProvider]?: Record<string, string>;
|
||||||
} = {
|
} = {
|
||||||
openai: {
|
openai: {
|
||||||
"@llamaindex/openai": "^0.1.52",
|
"@llamaindex/openai": "~0.4.0",
|
||||||
},
|
},
|
||||||
gemini: {
|
gemini: {
|
||||||
"@llamaindex/google": "^0.0.7",
|
"@llamaindex/google": "^0.2.0",
|
||||||
},
|
},
|
||||||
ollama: {
|
ollama: {
|
||||||
"@llamaindex/ollama": "^0.0.40",
|
"@llamaindex/ollama": "^0.1.0",
|
||||||
},
|
},
|
||||||
mistral: {
|
mistral: {
|
||||||
"@llamaindex/mistral": "^0.0.5",
|
"@llamaindex/mistral": "^0.2.0",
|
||||||
},
|
},
|
||||||
"azure-openai": {
|
"azure-openai": {
|
||||||
"@llamaindex/openai": "^0.1.52",
|
"@llamaindex/openai": "^0.2.0",
|
||||||
},
|
},
|
||||||
groq: {
|
groq: {
|
||||||
"@llamaindex/groq": "^0.0.51",
|
"@llamaindex/groq": "^0.0.61",
|
||||||
"@llamaindex/huggingface": "^0.0.36", // groq uses huggingface as default embedding model
|
"@llamaindex/huggingface": "^0.1.0", // groq uses huggingface as default embedding model
|
||||||
},
|
},
|
||||||
anthropic: {
|
anthropic: {
|
||||||
"@llamaindex/anthropic": "^0.1.0",
|
"@llamaindex/anthropic": "^0.3.0",
|
||||||
"@llamaindex/huggingface": "^0.0.36", // anthropic uses huggingface as default embedding model
|
"@llamaindex/huggingface": "^0.1.0", // anthropic uses huggingface as default embedding model
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -331,6 +456,7 @@ async function updatePackageJson({
|
|||||||
vectorDb,
|
vectorDb,
|
||||||
backend,
|
backend,
|
||||||
modelConfig,
|
modelConfig,
|
||||||
|
template,
|
||||||
}: Pick<
|
}: Pick<
|
||||||
InstallTemplateArgs,
|
InstallTemplateArgs,
|
||||||
| "root"
|
| "root"
|
||||||
@@ -341,6 +467,7 @@ async function updatePackageJson({
|
|||||||
| "observability"
|
| "observability"
|
||||||
| "vectorDb"
|
| "vectorDb"
|
||||||
| "modelConfig"
|
| "modelConfig"
|
||||||
|
| "template"
|
||||||
> & {
|
> & {
|
||||||
relativeEngineDestPath: string;
|
relativeEngineDestPath: string;
|
||||||
backend: boolean;
|
backend: boolean;
|
||||||
@@ -352,7 +479,7 @@ async function updatePackageJson({
|
|||||||
packageJson.name = appName;
|
packageJson.name = appName;
|
||||||
packageJson.version = "0.1.0";
|
packageJson.version = "0.1.0";
|
||||||
|
|
||||||
if (relativeEngineDestPath) {
|
if (relativeEngineDestPath && template !== "llamaindexserver") {
|
||||||
// TODO: move script to {root}/scripts for all frameworks
|
// TODO: move script to {root}/scripts for all frameworks
|
||||||
// add generate script if using context engine
|
// add generate script if using context engine
|
||||||
packageJson.scripts = {
|
packageJson.scripts = {
|
||||||
@@ -386,7 +513,7 @@ async function updatePackageJson({
|
|||||||
if (backend) {
|
if (backend) {
|
||||||
packageJson.dependencies = {
|
packageJson.dependencies = {
|
||||||
...packageJson.dependencies,
|
...packageJson.dependencies,
|
||||||
"@llamaindex/readers": "^2.0.0",
|
"@llamaindex/readers": "~3.1.4",
|
||||||
};
|
};
|
||||||
|
|
||||||
if (vectorDb && vectorDb in vectorDbDependencies) {
|
if (vectorDb && vectorDb in vectorDbDependencies) {
|
||||||
@@ -416,6 +543,16 @@ async function updatePackageJson({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if having custom server package tgz file, use it for testing @llamaindex/server
|
||||||
|
const serverPackagePath = process.env.SERVER_PACKAGE_PATH;
|
||||||
|
if (serverPackagePath && template === "llamaindexserver") {
|
||||||
|
const relativePath = path.relative(process.cwd(), serverPackagePath);
|
||||||
|
packageJson.dependencies = {
|
||||||
|
...packageJson.dependencies,
|
||||||
|
"@llamaindex/server": `file:${relativePath}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
await fs.writeFile(
|
await fs.writeFile(
|
||||||
packageJsonFile,
|
packageJsonFile,
|
||||||
JSON.stringify(packageJson, null, 2) + os.EOL,
|
JSON.stringify(packageJson, null, 2) + os.EOL,
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// 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,4 +1,3 @@
|
|||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
||||||
import validateProjectName from "validate-npm-package-name";
|
import validateProjectName from "validate-npm-package-name";
|
||||||
|
|
||||||
export function validateNpmName(name: string): {
|
export function validateNpmName(name: string): {
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable import/no-extraneous-dependencies */
|
|
||||||
import { execSync } from "child_process";
|
import { execSync } from "child_process";
|
||||||
import { Command } from "commander";
|
import { Command } from "commander";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
@@ -197,7 +196,7 @@ const program = new Command(packageJson.name)
|
|||||||
"--pro",
|
"--pro",
|
||||||
`
|
`
|
||||||
|
|
||||||
Allow interactive selection of all features.
|
Deprecated: Allow interactive selection of all features.
|
||||||
`,
|
`,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"name": "create-llama",
|
||||||
|
"version": "0.5.16",
|
||||||
|
"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",
|
||||||
|
"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": {
|
||||||
|
"@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,4 +1,3 @@
|
|||||||
/* eslint-disable turbo/no-undeclared-env-vars */
|
|
||||||
import { defineConfig, devices } from "@playwright/test";
|
import { defineConfig, devices } from "@playwright/test";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@@ -6,7 +6,7 @@ const defaults: Omit<QuestionArgs, "modelConfig"> = {
|
|||||||
framework: "nextjs",
|
framework: "nextjs",
|
||||||
ui: "shadcn",
|
ui: "shadcn",
|
||||||
frontend: false,
|
frontend: false,
|
||||||
llamaCloudKey: "",
|
llamaCloudKey: undefined,
|
||||||
useLlamaParse: false,
|
useLlamaParse: false,
|
||||||
communityProjectConfig: undefined,
|
communityProjectConfig: undefined,
|
||||||
llamapack: "",
|
llamapack: "",
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import ciInfo from "ci-info";
|
import ciInfo from "ci-info";
|
||||||
|
import { bold, yellow } from "picocolors";
|
||||||
import { getCIQuestionResults } from "./ci";
|
import { getCIQuestionResults } from "./ci";
|
||||||
import { askProQuestions } from "./questions";
|
import { askProQuestions } from "./questions";
|
||||||
import { askSimpleQuestions } from "./simple";
|
import { askSimpleQuestions } from "./simple";
|
||||||
@@ -13,8 +14,15 @@ export const askQuestions = async (
|
|||||||
return await getCIQuestionResults(args);
|
return await getCIQuestionResults(args);
|
||||||
} else if (args.pro) {
|
} else if (args.pro) {
|
||||||
// TODO: refactor pro questions to return a result object
|
// TODO: refactor pro questions to return a result object
|
||||||
|
console.log(
|
||||||
|
yellow(
|
||||||
|
`Pro mode is deprecated. Please use the new templates using the ${bold("LlamaIndexServer")} by not specifying pro mode.`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
await askProQuestions(args);
|
await askProQuestions(args);
|
||||||
return args as unknown as QuestionResults;
|
return args as unknown as QuestionResults;
|
||||||
}
|
}
|
||||||
return await askSimpleQuestions(args);
|
const results = await askSimpleQuestions(args);
|
||||||
|
return results;
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
import prompts from "prompts";
|
||||||
|
import { EXAMPLE_10K_SEC_FILES, EXAMPLE_FILE } from "../helpers/datasources";
|
||||||
|
import { askModelConfig } from "../helpers/providers";
|
||||||
|
import { getTools } from "../helpers/tools";
|
||||||
|
import { ModelConfig, TemplateFramework } from "../helpers/types";
|
||||||
|
import { PureQuestionArgs, QuestionResults } from "./types";
|
||||||
|
import { askPostInstallAction, questionHandlers } from "./utils";
|
||||||
|
|
||||||
|
type AppType =
|
||||||
|
| "agentic_rag"
|
||||||
|
| "financial_report"
|
||||||
|
| "deep_research"
|
||||||
|
| "code_generator"
|
||||||
|
| "document_generator";
|
||||||
|
|
||||||
|
type SimpleAnswers = {
|
||||||
|
appType: AppType;
|
||||||
|
language: TemplateFramework;
|
||||||
|
useLlamaCloud: boolean;
|
||||||
|
llamaCloudKey?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const askSimpleQuestions = async (
|
||||||
|
args: PureQuestionArgs,
|
||||||
|
): Promise<QuestionResults> => {
|
||||||
|
const { appType } = await prompts(
|
||||||
|
{
|
||||||
|
type: "select",
|
||||||
|
name: "appType",
|
||||||
|
message: "What use case do you want to build?",
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
title: "Agentic RAG",
|
||||||
|
value: "agentic_rag",
|
||||||
|
description:
|
||||||
|
"Chatbot that answers questions based on provided documents.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Financial Report",
|
||||||
|
value: "financial_report",
|
||||||
|
description:
|
||||||
|
"Agent that analyzes data and generates visualizations by using a code interpreter.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Deep Research",
|
||||||
|
value: "deep_research",
|
||||||
|
description:
|
||||||
|
"Researches and analyzes provided documents from multiple perspectives, generating a comprehensive report with citations to support key findings and insights.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Code Generator",
|
||||||
|
value: "code_generator",
|
||||||
|
description: "Build a Vercel v0 styled code generator.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Document Generator",
|
||||||
|
value: "document_generator",
|
||||||
|
description: "Build a OpenAI canvas-styled document generator.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
questionHandlers,
|
||||||
|
);
|
||||||
|
|
||||||
|
let language: TemplateFramework = "fastapi";
|
||||||
|
let llamaCloudKey = args.llamaCloudKey;
|
||||||
|
|
||||||
|
let useLlamaCloud = false;
|
||||||
|
|
||||||
|
const { language: newLanguage } = await prompts(
|
||||||
|
{
|
||||||
|
type: "select",
|
||||||
|
name: "language",
|
||||||
|
message: "What language do you want to use?",
|
||||||
|
choices: [
|
||||||
|
{ title: "Python (FastAPI)", value: "fastapi" },
|
||||||
|
{ title: "Typescript (NextJS)", value: "nextjs" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
questionHandlers,
|
||||||
|
);
|
||||||
|
language = newLanguage;
|
||||||
|
|
||||||
|
if (appType !== "code_generator" && appType !== "document_generator") {
|
||||||
|
const { useLlamaCloud: newUseLlamaCloud } = await prompts(
|
||||||
|
{
|
||||||
|
type: "toggle",
|
||||||
|
name: "useLlamaCloud",
|
||||||
|
message: "Do you want to use LlamaCloud services?",
|
||||||
|
initial: false,
|
||||||
|
active: "Yes",
|
||||||
|
inactive: "No",
|
||||||
|
hint: "see https://www.llamaindex.ai/enterprise for more info",
|
||||||
|
},
|
||||||
|
questionHandlers,
|
||||||
|
);
|
||||||
|
useLlamaCloud = newUseLlamaCloud;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useLlamaCloud && !llamaCloudKey) {
|
||||||
|
// Ask for LlamaCloud API key, if not set
|
||||||
|
const { llamaCloudKey: newLlamaCloudKey } = await prompts(
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
name: "llamaCloudKey",
|
||||||
|
message:
|
||||||
|
"Please provide your LlamaCloud API key (leave blank to skip):",
|
||||||
|
},
|
||||||
|
questionHandlers,
|
||||||
|
);
|
||||||
|
llamaCloudKey = newLlamaCloudKey || process.env.LLAMA_CLOUD_API_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
const results = await convertAnswers(args, {
|
||||||
|
appType,
|
||||||
|
language,
|
||||||
|
useLlamaCloud,
|
||||||
|
llamaCloudKey,
|
||||||
|
});
|
||||||
|
|
||||||
|
results.postInstallAction = await askPostInstallAction(results);
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertAnswers = async (
|
||||||
|
args: PureQuestionArgs,
|
||||||
|
answers: SimpleAnswers,
|
||||||
|
): Promise<QuestionResults> => {
|
||||||
|
const MODEL_GPT41: ModelConfig = {
|
||||||
|
provider: "openai",
|
||||||
|
apiKey: args.openAiKey,
|
||||||
|
model: "gpt-4.1",
|
||||||
|
embeddingModel: "text-embedding-3-large",
|
||||||
|
dimensions: 1536,
|
||||||
|
isConfigured(): boolean {
|
||||||
|
return !!args.openAiKey;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const lookup: Record<
|
||||||
|
AppType,
|
||||||
|
Pick<QuestionResults, "template" | "tools" | "dataSources" | "useCase"> & {
|
||||||
|
modelConfig?: ModelConfig;
|
||||||
|
}
|
||||||
|
> = {
|
||||||
|
agentic_rag: {
|
||||||
|
template: "llamaindexserver",
|
||||||
|
dataSources: [EXAMPLE_FILE],
|
||||||
|
},
|
||||||
|
financial_report: {
|
||||||
|
template: "llamaindexserver",
|
||||||
|
dataSources: EXAMPLE_10K_SEC_FILES,
|
||||||
|
tools: getTools(["interpreter", "document_generator"]),
|
||||||
|
modelConfig: MODEL_GPT41,
|
||||||
|
},
|
||||||
|
deep_research: {
|
||||||
|
template: "llamaindexserver",
|
||||||
|
dataSources: EXAMPLE_10K_SEC_FILES,
|
||||||
|
tools: [],
|
||||||
|
modelConfig: MODEL_GPT41,
|
||||||
|
},
|
||||||
|
code_generator: {
|
||||||
|
template: "llamaindexserver",
|
||||||
|
dataSources: [],
|
||||||
|
tools: [],
|
||||||
|
modelConfig: MODEL_GPT41,
|
||||||
|
},
|
||||||
|
document_generator: {
|
||||||
|
template: "llamaindexserver",
|
||||||
|
dataSources: [],
|
||||||
|
tools: [],
|
||||||
|
modelConfig: MODEL_GPT41,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const results = lookup[answers.appType];
|
||||||
|
return {
|
||||||
|
framework: answers.language,
|
||||||
|
useCase: answers.appType,
|
||||||
|
ui: "shadcn",
|
||||||
|
llamaCloudKey: answers.llamaCloudKey,
|
||||||
|
useLlamaParse: answers.useLlamaCloud,
|
||||||
|
vectorDb: answers.useLlamaCloud ? "llamacloud" : "none",
|
||||||
|
...results,
|
||||||
|
modelConfig:
|
||||||
|
results.modelConfig ??
|
||||||
|
(await askModelConfig({
|
||||||
|
openAiKey: args.openAiKey,
|
||||||
|
askModels: args.askModels ?? false,
|
||||||
|
framework: answers.language,
|
||||||
|
})),
|
||||||
|
frontend: true,
|
||||||
|
};
|
||||||
|
};
|
||||||
+4
-4
@@ -19,20 +19,20 @@ First, setup the environment with poetry:
|
|||||||
> **_Note:_** This step is not needed if you are using the dev-container.
|
> **_Note:_** This step is not needed if you are using the dev-container.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
poetry install
|
uv sync
|
||||||
```
|
```
|
||||||
|
|
||||||
Then check the parameters that have been pre-configured in the `.env` file in this directory. (E.g. you might need to configure an `OPENAI_API_KEY` if you're using OpenAI as model provider).
|
Then check the parameters that have been pre-configured in the `.env` file in this directory. (E.g. you might need to configure an `OPENAI_API_KEY` if you're using OpenAI as model provider).
|
||||||
Second, generate the embeddings of the documents in the `./data` directory:
|
Second, generate the embeddings of the documents in the `./data` directory:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
poetry run generate
|
uv run generate
|
||||||
```
|
```
|
||||||
|
|
||||||
Third, run the development server:
|
Third, run the development server:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
poetry run dev
|
uv run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Per default, the example is using the explicit workflow. You can change the example by setting the `EXAMPLE_TYPE` environment variable to `choreography` or `orchestrator`.
|
Per default, the example is using the explicit workflow. You can change the example by setting the `EXAMPLE_TYPE` environment variable to `choreography` or `orchestrator`.
|
||||||
@@ -52,7 +52,7 @@ Open [http://localhost:8000](http://localhost:8000) with your browser to start t
|
|||||||
To start the app optimized for **production**, run:
|
To start the app optimized for **production**, run:
|
||||||
|
|
||||||
```
|
```
|
||||||
poetry run prod
|
uv run prod
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deployments
|
## Deployments
|
||||||
+3
-3
@@ -7,20 +7,20 @@ First, setup the environment with poetry:
|
|||||||
> **_Note:_** This step is not needed if you are using the dev-container.
|
> **_Note:_** This step is not needed if you are using the dev-container.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
poetry install
|
uv sync
|
||||||
```
|
```
|
||||||
|
|
||||||
Then check the parameters that have been pre-configured in the `.env` file in this directory. (E.g. you might need to configure an `OPENAI_API_KEY` if you're using OpenAI as model provider).
|
Then check the parameters that have been pre-configured in the `.env` file in this directory. (E.g. you might need to configure an `OPENAI_API_KEY` if you're using OpenAI as model provider).
|
||||||
Second, generate the embeddings of the documents in the `./data` directory:
|
Second, generate the embeddings of the documents in the `./data` directory:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
poetry run generate
|
uv run generate
|
||||||
```
|
```
|
||||||
|
|
||||||
Third, run the development server:
|
Third, run the development server:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
poetry run dev
|
uv run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
## Use Case: Deep Research over own documents
|
## Use Case: Deep Research over own documents
|
||||||
+4
-4
@@ -7,7 +7,7 @@ First, setup the environment with poetry:
|
|||||||
> **_Note:_** This step is not needed if you are using the dev-container.
|
> **_Note:_** This step is not needed if you are using the dev-container.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
poetry install
|
uv sync
|
||||||
```
|
```
|
||||||
|
|
||||||
Then check the parameters that have been pre-configured in the `.env` file in this directory. (E.g. you might need to configure an `OPENAI_API_KEY` if you're using OpenAI as model provider and `E2B_API_KEY` for the [E2B's code interpreter tool](https://e2b.dev/docs)).
|
Then check the parameters that have been pre-configured in the `.env` file in this directory. (E.g. you might need to configure an `OPENAI_API_KEY` if you're using OpenAI as model provider and `E2B_API_KEY` for the [E2B's code interpreter tool](https://e2b.dev/docs)).
|
||||||
@@ -15,13 +15,13 @@ Then check the parameters that have been pre-configured in the `.env` file in th
|
|||||||
Second, generate the embeddings of the documents in the `./data` directory:
|
Second, generate the embeddings of the documents in the `./data` directory:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
poetry run generate
|
uv run generate
|
||||||
```
|
```
|
||||||
|
|
||||||
Third, run the development server:
|
Third, run the development server:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
poetry run dev
|
uv run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
The example provides one streaming API endpoint `/api/chat`.
|
The example provides one streaming API endpoint `/api/chat`.
|
||||||
@@ -40,7 +40,7 @@ Open [http://localhost:8000](http://localhost:8000) with your browser to start t
|
|||||||
To start the app optimized for **production**, run:
|
To start the app optimized for **production**, run:
|
||||||
|
|
||||||
```
|
```
|
||||||
poetry run prod
|
uv run prod
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deployments
|
## Deployments
|
||||||
+3
-3
@@ -7,7 +7,7 @@ First, setup the environment with poetry:
|
|||||||
> **_Note:_** This step is not needed if you are using the dev-container.
|
> **_Note:_** This step is not needed if you are using the dev-container.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
poetry install
|
uv sync
|
||||||
```
|
```
|
||||||
|
|
||||||
Then check the parameters that have been pre-configured in the `.env` file in this directory.
|
Then check the parameters that have been pre-configured in the `.env` file in this directory.
|
||||||
@@ -16,7 +16,7 @@ Make sure you have the `OPENAI_API_KEY` set.
|
|||||||
Second, run the development server:
|
Second, run the development server:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
poetry run dev
|
uv run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
## Use Case: Filling Financial CSV Template
|
## Use Case: Filling Financial CSV Template
|
||||||
@@ -46,7 +46,7 @@ Open [http://localhost:8000](http://localhost:8000) with your browser to start t
|
|||||||
To start the app optimized for **production**, run:
|
To start the app optimized for **production**, run:
|
||||||
|
|
||||||
```
|
```
|
||||||
poetry run prod
|
uv run prod
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deployments
|
## Deployments
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user