Compare commits

..

71 Commits

Author SHA1 Message Date
github-actions[bot] 4c7b891446 Release 0.8.13 (#1480)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: himself65 <himself65@users.noreply.github.com>
2024-11-14 18:25:19 -08:00
Alex Yang a9c5b4899b docs: update docusaurus.config.js (#1489) 2024-11-14 17:36:52 -08:00
Alex Yang a7b0ac3cb7 feat(anthropic): support prompt caching (#1488) 2024-11-14 17:35:21 -08:00
Alex Yang a7540ff47b docs: update (#1486) 2024-11-14 15:46:48 -08:00
Aman Rao c69605f406 feat: add async support to BaseChatStore and BaseChatStoreMemory (#1483)
Co-authored-by: Alex Yang <himself65@outlook.com>
2024-11-14 13:45:50 -08:00
Alex Yang ee20c44d9b feat(workflow): allow send event with no output (#1479) 2024-11-14 00:17:53 -08:00
Alex Yang 1d470363df docs: add banner for legacy (#1478) 2024-11-13 18:16:13 -08:00
github-actions[bot] b39f40dbd8 Release (#1477)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: himself65 <himself65@users.noreply.github.com>
2024-11-13 01:25:40 -08:00
Alex Yang fadc8b8ea0 feat: recoverable data with error handling (#1476) 2024-11-13 01:15:50 -08:00
Alex Yang ea92b6986d chore: update changeset 2024-11-13 01:15:28 -08:00
Alex Yang 17f9022d22 fix: output event check (#1475) 2024-11-13 00:46:35 -08:00
github-actions[bot] 14792cd8b4 Release 0.8.12 (#1473)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-11-12 16:20:25 -08:00
Alex Yang 7ae6eaa0a2 chore: update changeset 2024-11-12 12:49:17 -08:00
Alex Yang dbb5bd9f23 feat: allow tool_choice for OpenAIAgent (#1472) 2024-11-12 12:46:57 -08:00
github-actions[bot] aacd606204 Release 0.8.11 (#1471)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-11-12 11:49:22 -08:00
Alex Yang f865c984d3 feat: async get message on chat store (#1470) 2024-11-12 10:59:44 -08:00
github-actions[bot] 7b10882d06 Release 0.8.10 (#1466)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: himself65 <himself65@users.noreply.github.com>
2024-11-11 14:19:46 -08:00
Alex Yang f066e50482 feat: vllm support (#1468) 2024-11-11 13:14:08 -08:00
Alex Yang fd8c882792 refactor: migrate example to new workflow API (#1467) 2024-11-11 12:03:38 -08:00
Alex Yang d89ebe0261 chore: update changeset 2024-11-11 10:11:04 -08:00
Alex Yang 968feb32cd feat: better input type for function tool with zod (#1464) 2024-11-11 10:10:03 -08:00
Alex Yang 43f6f56c5b docs(next): fix turbo.json (#1465) 2024-11-11 10:07:12 -08:00
github-actions[bot] b2364dc5ba Release 0.8.9 (#1460)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-11-10 23:32:41 -08:00
Alex Yang 67f4db8501 fix: steaming chat in ollama (#1463) 2024-11-10 23:27:09 -08:00
Alex Yang e4151a8b02 feat: support ollama agent (#1462) 2024-11-10 22:38:40 -08:00
Alex Yang 4d4cd8ac6b feat: support ollama tool call (#1461) 2024-11-10 20:46:46 -08:00
Alex Yang 4fc001c8de chore: bump @huggingface/transformers (#1459) 2024-11-10 20:14:44 -08:00
Alex Yang cf675bdc7a chore: bump version (#1458) 2024-11-10 16:43:45 -08:00
github-actions[bot] 660b831b9e Release 0.8.8 (#1457)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: himself65 <himself65@users.noreply.github.com>
2024-11-08 23:56:46 -08:00
Alex Yang ad85bd0b46 fix: agent streaming final message & async local storage (#1456) 2024-11-08 22:54:13 -08:00
Alex Yang 18ec1f2f61 chore: separate tokenizers (#1454) 2024-11-08 18:53:05 -08:00
Alex Yang b0fbd8b5c8 docs: update CONTRIBUTING.md (#1455) 2024-11-08 18:38:26 -08:00
github-actions[bot] c0dfc8c641 Release 0.8.7 (#1453)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-11-08 17:57:02 -08:00
Alex Yang a8d3fa68a1 fix: exports in package.json (#1452) 2024-11-08 16:51:21 -08:00
github-actions[bot] f9470c470a Release 0.8.6 (#1450)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-11-08 14:57:13 -08:00
Alex Yang 95a5cc6ee1 refactor: move storage into core (#1451) 2024-11-08 14:29:08 -08:00
Peter Goldstein 487782cd98 fix: add missing inference endpoints for the Haiku 3.5 models (#1448) 2024-11-07 20:12:34 -08:00
Alex Yang 58e65d399e refactor: move e2e top level (#1449) 2024-11-07 20:11:15 -08:00
github-actions[bot] fdad3d66ac Release 0.8.5 (#1446)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-11-07 15:57:54 -08:00
Rozstone a6db5dd29b feat: add baseUrl and timeout option in cohere rerank (#1445)
Co-authored-by: Alex Yang <himself65@outlook.com>
2024-11-07 15:13:13 -08:00
Laurie Voss 7b684c4480 docs: home page tweaks (#1447) 2024-11-07 15:12:54 -08:00
Alex Yang c66868a98a chore: fix turbo cache 2024-11-07 15:05:41 -08:00
Alex Yang 14cc9ebe59 chore: move multi-model into single sub module (#1443) 2024-11-07 15:01:17 -08:00
Aman Rao 396b1e1474 feat: integrate with azure cosmos db (#1444)
Co-authored-by: Wassim Chegham <github@wassim.dev>
Co-authored-by: Alex Yang <himself65@outlook.com>
2024-11-07 14:43:19 -08:00
github-actions[bot] 69f3095424 Release (#1438)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-11-07 14:30:26 -08:00
Alex Yang dc8bd5ea92 chore: delete .changeset/fresh-dancers-refuse.md 2024-11-07 09:49:54 -08:00
Marcus Schiesser 4af9a77d8b feat: add example using chat-ui components to docs (#1436)
Co-authored-by: Alex Yang <himself65@outlook.com>
2024-11-07 09:44:47 -08:00
Alex Yang 9c1d094455 docs: fix upload llamacloud script 2024-11-07 09:35:30 -08:00
Alex Yang 0a8e3fdbcd docs(next): fix build (#1441) 2024-11-06 15:23:42 -08:00
Alex Yang 1c0e0e1e1d chore: bump version (#1439) 2024-11-06 10:16:18 -08:00
Parham Saidi 47a7c3ea15 feat: added Haiku 3.5 support via Bedrock (#1437) 2024-11-05 13:03:10 -08:00
Alex Yang 898cff0d6a chore: bump pnpm (#1435) 2024-11-04 20:50:15 -08:00
Alex Yang 9df37edef4 fix: remove usage of pnpx (#1434) 2024-11-04 20:38:08 -08:00
github-actions[bot] f86a7a4fa3 Release 0.8.4 (#1432)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-11-04 14:51:57 -08:00
Aman Rao 35430d3609 feat: add AzureCosmosDBNoSqlVectorStore and SimpleCosmosDBReader (#1331)
Co-authored-by: Alex Yang <himself65@outlook.com>
2024-11-04 13:39:39 -08:00
Alex Yang 3c162b2b4a docs: direct to legacy docs (#1431) 2024-11-04 09:54:54 -08:00
github-actions[bot] 5bb4531245 Release 0.8.3 (#1427)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-11-02 19:05:28 -07:00
Alex Yang 2ff0a89891 fix: expose @llamaindex/node-parser (#1426) 2024-11-02 18:57:05 -07:00
Alex Yang d57917d782 feat: add code splitter and html node parser (#1425) 2024-11-02 15:14:03 -07:00
github-actions[bot] f231e0739f Release (#1424)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: himself65 <himself65@users.noreply.github.com>
2024-11-01 16:50:36 -07:00
Alex Yang 0765742ef3 feat: revamped workflow (#1422) 2024-11-01 15:59:19 -07:00
github-actions[bot] ec7fd6be5c Release 0.8.2 (#1421)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-31 23:54:40 -07:00
Thuc Pham c7a918c3f5 fix: export postprocessors in core (#1419) 2024-10-31 23:40:37 -07:00
Marcus Schiesser 00e681d43b ci: run type-check for reader examples 2024-11-01 12:52:06 +07:00
Alex Yang c01502fb84 docs: update document (#1418) 2024-10-31 14:02:31 -07:00
github-actions[bot] 075f88dbc3 Release 0.8.1 (#1415)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-31 11:57:26 -07:00
Alex Yang cc47ee0602 docs: update README.md (#1416) 2024-10-31 11:56:54 -07:00
Alex Yang 5e6ef55a5a chore: drop nodejs 18 support (#1414) 2024-10-31 11:23:29 -07:00
Alex Yang 9c73f0a530 fix(core): async local storage in Setting.with API (#1413) 2024-10-31 11:06:14 -07:00
Alex Yang 52a4d2b83d chore: bump to eslint 9 (#1410) 2024-10-30 18:34:17 -07:00
Alex Yang 0fd78d5434 docs(next): fix update llamacloud (#1409) 2024-10-29 21:47:21 -07:00
504 changed files with 18351 additions and 8561 deletions
-84
View File
@@ -1,84 +0,0 @@
const { join } = require("node:path");
module.exports = {
root: true,
extends: [
"turbo",
"prettier",
"plugin:@typescript-eslint/recommended-type-checked-only",
],
parserOptions: {
project: join(__dirname, "tsconfig.eslint.json"),
__tsconfigRootDir: __dirname,
},
settings: {
react: {
version: "999.999.999",
},
},
rules: {
"max-params": ["error", 4],
"prefer-const": "error",
"@typescript-eslint/no-floating-promises": [
"error",
{
ignoreIIFE: true,
},
],
"no-debugger": "error",
"@typescript-eslint/await-thenable": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-types": "off",
"no-array-constructor": "off",
"@typescript-eslint/no-array-constructor": "off",
"@typescript-eslint/no-base-to-string": [
"error",
{
ignoredTypeNames: ["Error", "RegExp", "URL", "URLSearchParams"],
},
],
"@typescript-eslint/no-duplicate-enum-values": "off",
"@typescript-eslint/no-duplicate-type-constituents": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-extra-non-null-assertion": "off",
"@typescript-eslint/no-for-in-array": "off",
"no-implied-eval": "off",
"@typescript-eslint/no-implied-eval": "off",
"no-loss-of-precision": "off",
"@typescript-eslint/no-loss-of-precision": "off",
"@typescript-eslint/no-misused-new": "off",
"@typescript-eslint/no-misused-promises": "off",
"@typescript-eslint/no-namespace": "off",
"@typescript-eslint/no-non-null-asserted-optional-chain": "off",
"@typescript-eslint/no-redundant-type-constituents": "off",
"@typescript-eslint/no-this-alias": "off",
"@typescript-eslint/no-unnecessary-type-assertion": "off",
"@typescript-eslint/no-unnecessary-type-constraint": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-declaration-merging": "off",
"@typescript-eslint/no-unsafe-enum-comparison": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-return": "off",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/prefer-as-const": "off",
"require-await": "off",
"@typescript-eslint/require-await": "off",
"@typescript-eslint/restrict-plus-operands": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/triple-slash-reference": "off",
"@typescript-eslint/unbound-method": "off",
},
overrides: [
{
files: ["examples/**/*.ts"],
rules: {
"turbo/no-undeclared-env-vars": "off",
},
},
],
ignorePatterns: ["dist/", "lib/", "deps/"],
};
+6 -4
View File
@@ -23,7 +23,7 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: [18.x, 20.x, 22.x]
node-version: [20.x, 22.x, 23.x]
name: E2E on Node.js ${{ matrix.node-version }}
runs-on: ubuntu-latest
steps:
@@ -53,7 +53,7 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: [18.x, 20.x, 22.x]
node-version: [20.x, 22.x, 23.x]
name: Test on Node.js ${{ matrix.node-version }}
runs-on: ubuntu-latest
steps:
@@ -84,7 +84,9 @@ jobs:
- name: Build
run: pnpm run build
- name: Use Build For Examples
run: pnpm link ../packages/llamaindex/
run: |
pnpm link ../packages/llamaindex/
cd readers && pnpm link ../../packages/llamaindex/
working-directory: ./examples
- name: Run Type Check
run: pnpm run type-check
@@ -117,7 +119,7 @@ jobs:
run: pnpm run build
- name: Build ${{ matrix.packages }}
run: pnpm run build
working-directory: packages/llamaindex/e2e/examples/${{ matrix.packages }}
working-directory: e2e/examples/${{ matrix.packages }}
typecheck-examples:
runs-on: ubuntu-latest
+34 -62
View File
@@ -2,86 +2,58 @@
## Structure
This is a monorepo built with Turborepo
LlamaIndex.TS uses pnpm monorepo.
Right now, for first-time contributors, these three packages are of the highest importance:
We recommend you to understand the basics of Node.js, TypeScript, pnpm, and of course, LLM before contributing.
- `packages/llamaindex` which is the main NPM library `llamaindex`
- `examples` is where the demo code lives
- `apps/docs` is where the code for the documentation of https://ts.llamaindex.ai/ is located
There are some important folders in the repository:
### Turborepo docs
You can checkout how Turborepo works using the default [README-turborepo.md](/README-turborepo.md)
- `packages/*`: Contains the source code of the packages. Each package is a separate npm package.
- `llamaindex`: The starter package for LlamaIndex.TS, which contains the all sub-packages.
- `core`: The core package of LlamaIndex.TS, which contains the abstract classes and interfaces. It is designed for
all JS runtime environments.
- `env`: The environment package of LlamaIndex.TS, which contains the environment-specific classes and interfaces. It
includes compatibility layers for Node.js, Deno, Vercel Edge Runtime, Cloudflare Workers...
- `apps/*`: The applications based on LlamaIndex.TS.
- `next`: Our documentation website based on Next.js.
- `examples`: The code examples of LlamaIndex.TS using Node.js.
## Getting Started
Install NodeJS. Preferably v18 using nvm or n.
Inside the LlamaIndexTS directory:
Make sure you have Node.js LIS (Long-term Support) installed. You can check your Node.js version by running:
```shell
node -v
# v20.x.x
```
npm i -g pnpm ts-node
### Use pnpm
```shell
corepack enable
```
### Install dependencies
```shell
pnpm install
```
Note: we use pnpm in this repo, which has a lot of the same functionality and CLI options as npm but it does do some things better in a monorepo, like centralizing dependencies and caching.
### Build the packages
PNPM's has documentation on its [workspace feature](https://pnpm.io/workspaces) and Turborepo had some [useful documentation also](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks).
### Running Typescript
When we publish to NPM we will have a tsc compiled version of the library in JS. For now, the easiest thing to do is use ts-node.
### Test cases
To run them, run
```
pnpm run test
```
To write new test cases write them in [packages/llamaindex/tests](/packages/llamaindex/tests)
We use Vitest https://vitest.dev to write our test cases. Vitest comes with a bunch of built-in assertions using the expect function: https://vitest.dev/api/expect.html#expect
### Demo applications
There is an existing ["example"](/examples/README.md) demos folder with mainly NodeJS scripts. Feel free to add additional demos to that folder. If you would like to try out your changes in the `llamaindex` package with a new demo, you need to run the build command in the README.
You can create new demo applications in the apps folder. Just run pnpm init in the folder after you create it to create its own package.json
### Installing packages
To install packages for a specific package or demo application, run
```
pnpm add [NPM Package] --filter [package or application i.e. llamaindex or docs]
```
To install packages for every package or application run
```
pnpm add -w [NPM Package]
```shell
# Build all packages
turbo build --filter "./packages/*"
```
### Docs
To contribute to the docs, go to the docs website folder and run the Docusaurus instance.
```bash
cd apps/docs
pnpm install
pnpm start
```
That should start a webserver which will serve the docs on https://localhost:3000
Any changes you make should be reflected in the browser. If you need to regenerate the API docs and find that your TSDoc isn't getting the updates, feel free to remove apps/docs/api. It will automatically regenerate itself when you run pnpm start again.
See the [docs](./apps/next/README.md) for more information.
## Changeset
We use [changesets](https://github.com/changesets/changesets) for managing versions and changelogs. To create a new changeset, run in the root folder:
We use [changesets](https://github.com/changesets/changesets) for managing versions and changelogs. To create a new
changeset, run in the root folder:
```
pnpm changeset
@@ -95,6 +67,6 @@ The [Release Github Action](.github/workflows/release.yml) is automatically gene
PR called "Release {version}".
This PR will update the `package.json` and `CHANGELOG.md` files of each package according to
the current changesets in the [.changeset](.changeset/) folder.
the current changesets in the [.changeset](.changeset) folder.
If this PR is merged it will automatically add version tags to the repository and publish the updated packages to NPM.
+10 -210
View File
@@ -1,12 +1,16 @@
# LlamaIndex.TS
<p align="center">
<img height="100" width="100" alt="LlamaIndex logo" src="https://ts.llamaindex.ai/square.svg" />
</p>
<h1 align="center">LlamaIndex.TS</h1>
<h3 align="center">
Data framework for your LLM application.
</h3>
[![NPM Version](https://img.shields.io/npm/v/llamaindex)](https://www.npmjs.com/package/llamaindex)
[![NPM License](https://img.shields.io/npm/l/llamaindex)](https://www.npmjs.com/package/llamaindex)
[![NPM Downloads](https://img.shields.io/npm/dm/llamaindex)](https://www.npmjs.com/package/llamaindex)
[![Discord](https://img.shields.io/discord/1059199217496772688)](https://discord.com/invite/eN6D2HQ4aX)
LlamaIndex is a data framework for your LLM application.
Use your own data with large language models (LLMs, OpenAI ChatGPT and others) in JS runtime environments with TypeScript support.
Documentation: https://ts.llamaindex.ai/
@@ -25,7 +29,7 @@ LlamaIndex.TS aims to be a lightweight, easy to use set of libraries to help you
LlamaIndex.TS supports multiple JS environments, including:
- Node.js (18, 20, 22)
- Node.js >= 20
- Deno ✅
- Bun ✅
- Nitro ✅
@@ -57,213 +61,9 @@ pnpm install llamaindex
yarn add llamaindex
```
### Setup TypeScript
### Setup in Node.js, Deno, Bun, TypeScript...?
```json5
{
compilerOptions: {
// ⬇️ add this line to your tsconfig.json
moduleResolution: "bundler", // or "node16"
},
}
```
<details>
<summary>Why?</summary>
We are shipping both ESM and CJS module, and compatible with Vercel Edge, Cloudflare Workers, and other serverless platforms.
So we are using [conditional exports](https://nodejs.org/api/packages.html#conditional-exports) to support all environments.
This is a kind of modern way of shipping packages, but might cause TypeScript type check to fail because of legacy module resolution.
Imaging you put output file into `/dist/openai.js` but you are importing `llamaindex/openai` in your code, and set `package.json` like this:
```json
{
"exports": {
"./openai": "./dist/openai.js"
}
}
```
In old module resolution, TypeScript will not be able to find the module because it is not follow the file structure, even you run `node index.js` successfully. (on Node.js >=16)
See more about [moduleResolution](https://www.typescriptlang.org/docs/handbook/modules/theory.html#module-resolution) or
[TypeScript 5.0 blog](https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#--moduleresolution-bundler7).
</details>
### Node.js
```ts
import fs from "node:fs/promises";
import { Document, VectorStoreIndex } from "llamaindex";
async function main() {
// Load essay from abramov.txt in Node
const essay = await fs.readFile(
"node_modules/llamaindex/examples/abramov.txt",
"utf-8",
);
// Create Document object with essay
const document = new Document({ text: essay });
// Split text and create embeddings. Store them in a VectorStoreIndex
const index = await VectorStoreIndex.fromDocuments([document]);
// Query the index
const queryEngine = index.asQueryEngine();
const response = await queryEngine.query({
query: "What did the author do in college?",
});
// Output response
console.log(response.toString());
}
main();
```
```bash
# `pnpm install tsx` before running the script
node --import tsx ./main.ts
```
### Next.js
You will need to add a llamaindex plugin to your Next.js project.
```js
// next.config.js
const withLlamaIndex = require("llamaindex/next");
module.exports = withLlamaIndex({
// your next.js config
});
```
### React Server Actions
You can combine `ai` with `llamaindex` in Next.js, Waku or Redwood.js with RSC (React Server Components).
```tsx
"use client";
import { chatWithAgent } from "@/actions";
import type { JSX } from "react";
import { useActionState } from "react";
export default function Home() {
const [ui, action] = useActionState<JSX.Element | null>(async () => {
return chatWithAgent("hello!", []);
}, null);
return (
<main>
{ui}
<form action={action}>
<button>Chat</button>
</form>
</main>
);
}
```
```tsx
// src/actions/index.ts
"use server";
import { createStreamableUI } from "ai/rsc";
import { OpenAIAgent } from "llamaindex";
import type { ChatMessage } from "llamaindex/llm/types";
export async function chatWithAgent(
question: string,
prevMessages: ChatMessage[] = [],
) {
const agent = new OpenAIAgent({
tools: [
// ... adding your tools here
],
});
const responseStream = await agent.chat(
{
message: question,
chatHistory: prevMessages,
},
true,
);
const uiStream = createStreamableUI(<div>loading...</div>);
responseStream
.pipeTo(
new WritableStream({
start: () => {
uiStream.update("response:");
},
write: async (message) => {
uiStream.append(message.response.delta);
},
}),
)
.catch(console.error);
return uiStream.value;
}
```
### Cloudflare Workers
> [!TIP]
> Some modules are not supported in Cloudflare Workers which require Node.js APIs.
```ts
// add `OPENAI_API_KEY` to the `.dev.vars` file
interface Env {
OPENAI_API_KEY: string;
}
export default {
async fetch(
request: Request,
env: Env,
ctx: ExecutionContext,
): Promise<Response> {
const { OpenAIAgent, OpenAI } = await import("@llamaindex/openai");
const text = await request.text();
const agent = new OpenAIAgent({
llm: new OpenAI({
apiKey: env.OPENAI_API_KEY,
}),
tools: [],
});
const responseStream = await agent.chat({
stream: true,
message: text,
});
const textEncoder = new TextEncoder();
const response = responseStream.pipeThrough<Uint8Array>(
new TransformStream({
transform: (chunk, controller) => {
controller.enqueue(textEncoder.encode(chunk.delta));
},
}),
);
return new Response(response);
},
};
```
### Vite
We have some wasm dependencies for better performance. You can use `vite-plugin-wasm` to load them.
```ts
import wasm from "vite-plugin-wasm";
export default {
plugins: [wasm()],
ssr: {
external: ["tiktoken"],
},
};
```
See our official document: <https://ts.llamaindex.ai/docs/llamaindex/setup/getting-started>
### Tips when using in non-Node.js environments
+103
View File
@@ -1,5 +1,108 @@
# docs
## 0.0.118
### Patch Changes
- llamaindex@0.8.13
- @llamaindex/examples@0.0.16
## 0.0.117
### Patch Changes
- @llamaindex/examples@0.0.15
## 0.0.116
### Patch Changes
- llamaindex@0.8.12
## 0.0.115
### Patch Changes
- llamaindex@0.8.11
## 0.0.114
### Patch Changes
- Updated dependencies [f066e50]
- llamaindex@0.8.10
- @llamaindex/examples@0.0.14
## 0.0.113
### Patch Changes
- Updated dependencies [4fc001c]
- Updated dependencies [4d4cd8a]
- llamaindex@0.8.9
## 0.0.112
### Patch Changes
- Updated dependencies [ad85bd0]
- llamaindex@0.8.8
- @llamaindex/examples@0.0.13
## 0.0.111
### Patch Changes
- llamaindex@0.8.7
## 0.0.110
### Patch Changes
- Updated dependencies [95a5cc6]
- llamaindex@0.8.6
## 0.0.109
### Patch Changes
- Updated dependencies [14cc9eb]
- Updated dependencies [a6db5dd]
- Updated dependencies [396b1e1]
- llamaindex@0.8.5
## 0.0.108
### Patch Changes
- Updated dependencies [35430d3]
- llamaindex@0.8.4
## 0.0.107
### Patch Changes
- llamaindex@0.8.3
## 0.0.106
### Patch Changes
- @llamaindex/examples@0.0.12
## 0.0.105
### Patch Changes
- Updated dependencies [c7a918c]
- llamaindex@0.8.2
## 0.0.104
### Patch Changes
- llamaindex@0.8.1
## 0.0.103
### Patch Changes
@@ -25,6 +25,7 @@ ANTHROPIC_CLAUDE_3_SONNET = "anthropic.claude-3-sonnet-20240229-v1:0";
ANTHROPIC_CLAUDE_3_HAIKU = "anthropic.claude-3-haiku-20240307-v1:0";
ANTHROPIC_CLAUDE_3_OPUS = "anthropic.claude-3-opus-20240229-v1:0"; // available on us-west-2
ANTHROPIC_CLAUDE_3_5_SONNET = "anthropic.claude-3-5-sonnet-20240620-v1:0";
ANTHROPIC_CLAUDE_3_5_HAIKU = "anthropic.claude-3-5-haiku-20241022-v1:0";
META_LLAMA2_13B_CHAT = "meta.llama2-13b-chat-v1";
META_LLAMA2_70B_CHAT = "meta.llama2-70b-chat-v1";
META_LLAMA3_8B_INSTRUCT = "meta.llama3-8b-instruct-v1:0";
+8
View File
@@ -1,6 +1,7 @@
// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
// eslint-disable-next-line @typescript-eslint/no-require-imports
const renderer = require("prism-react-renderer");
const lightCodeTheme = renderer.themes.github;
const darkCodeTheme = renderer.themes.dracula;
@@ -39,6 +40,7 @@ const config = {
// editUrl:
// "https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/",
remarkPlugins: [
// eslint-disable-next-line @typescript-eslint/no-require-imports
[require("@docusaurus/remark-plugin-npm2yarn"), { sync: true }],
],
},
@@ -60,6 +62,12 @@ const config = {
({
// Replace with your project's social card
image: "img/favicon.png", // TODO change this
announcementBar: {
id: "migrate_to_next",
content:
'We are migrating to Next.js based documentation. Check it out <a href="https://ts.llamaindex.ai/docs/llamaindex">here</a>!',
isCloseable: false,
},
navbar: {
title: "LlamaIndex.TS",
logo: {
+18 -18
View File
@@ -1,6 +1,6 @@
{
"name": "docs",
"version": "0.0.103",
"version": "0.0.118",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
@@ -15,29 +15,29 @@
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "3.5.2",
"@docusaurus/remark-plugin-npm2yarn": "3.5.2",
"@docusaurus/core": "3.6.0",
"@docusaurus/remark-plugin-npm2yarn": "3.6.0",
"@llamaindex/examples": "workspace:*",
"@mdx-js/react": "3.0.1",
"clsx": "2.1.1",
"@mdx-js/react": "^3.1.0",
"clsx": "^2.1.1",
"llamaindex": "workspace:*",
"postcss": "8.4.41",
"prism-react-renderer": "2.4.0",
"raw-loader": "4.0.2",
"react": "18.3.1",
"postcss": "^8.4.47",
"prism-react-renderer": "^2.4.0",
"raw-loader": "^4.0.2",
"react": "^18.3.1",
"react-dom": "18.3.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.5.2",
"@docusaurus/preset-classic": "3.5.2",
"@docusaurus/theme-classic": "3.5.2",
"@docusaurus/types": "3.5.2",
"@docusaurus/module-type-aliases": "3.6.0",
"@docusaurus/preset-classic": "3.6.0",
"@docusaurus/theme-classic": "3.6.0",
"@docusaurus/types": "3.6.0",
"@tsconfig/docusaurus": "2.0.3",
"@types/node": "^22.5.1",
"@types/node": "^22.9.0",
"docusaurus-plugin-typedoc": "1.0.5",
"typedoc": "0.26.6",
"typedoc-plugin-markdown": "4.2.6",
"typescript": "^5.6.2"
"typedoc": "0.26.11",
"typedoc-plugin-markdown": "4.2.10",
"typescript": "^5.6.3"
},
"browserslist": {
"production": [
@@ -52,6 +52,6 @@
]
},
"engines": {
"node": ">=18"
"node": ">=20.0.0"
}
}
@@ -11,16 +11,19 @@ type FeatureItem = {
const FeatureList: FeatureItem[] = [
{
title: "Data Driven",
// eslint-disable-next-line @typescript-eslint/no-require-imports
Svg: require("@site/static/img/undraw_docusaurus_mountain.svg").default,
description: <>LlamaIndex.TS is all about using your data with LLMs.</>,
},
{
title: "Typescript Native",
// eslint-disable-next-line @typescript-eslint/no-require-imports
Svg: require("@site/static/img/undraw_docusaurus_tree.svg").default,
description: <>We Typescript, and so do our users.</>,
},
{
title: "Built by the Community",
// eslint-disable-next-line @typescript-eslint/no-require-imports
Svg: require("@site/static/img/undraw_docusaurus_react.svg").default,
description: (
<>
+1
View File
@@ -29,3 +29,4 @@ next-env.d.ts
# build
/src/content/docs/cloud/api
./types
+167
View File
@@ -1,5 +1,172 @@
# @llamaindex/doc
## 0.0.16
### Patch Changes
- Updated dependencies [a7b0ac3]
- Updated dependencies [ee20c44]
- Updated dependencies [c69605f]
- @llamaindex/core@0.4.10
- @llamaindex/workflow@0.0.6
- llamaindex@0.8.13
- @llamaindex/cloud@2.0.10
- @llamaindex/node-parser@0.0.11
- @llamaindex/openai@0.1.35
- @llamaindex/readers@1.0.11
## 0.0.15
### Patch Changes
- Updated dependencies [ea92b69]
- Updated dependencies [fadc8b8]
- @llamaindex/workflow@0.0.5
## 0.0.14
### Patch Changes
- Updated dependencies [7ae6eaa]
- @llamaindex/core@0.4.9
- @llamaindex/openai@0.1.34
- @llamaindex/cloud@2.0.9
- llamaindex@0.8.12
- @llamaindex/node-parser@0.0.10
- @llamaindex/readers@1.0.10
## 0.0.13
### Patch Changes
- Updated dependencies [f865c98]
- @llamaindex/core@0.4.8
- @llamaindex/cloud@2.0.8
- llamaindex@0.8.11
- @llamaindex/node-parser@0.0.9
- @llamaindex/openai@0.1.33
- @llamaindex/readers@1.0.9
## 0.0.12
### Patch Changes
- Updated dependencies [f066e50]
- Updated dependencies [d89ebe0]
- Updated dependencies [fd8c882]
- Updated dependencies [fd8c882]
- llamaindex@0.8.10
- @llamaindex/core@0.4.7
- @llamaindex/workflow@0.0.4
- @llamaindex/cloud@2.0.7
- @llamaindex/node-parser@0.0.8
- @llamaindex/openai@0.1.32
- @llamaindex/readers@1.0.8
## 0.0.11
### Patch Changes
- Updated dependencies [4fc001c]
- Updated dependencies [4d4cd8a]
- llamaindex@0.8.9
- @llamaindex/cloud@2.0.6
- @llamaindex/core@0.4.6
- @llamaindex/node-parser@0.0.7
- @llamaindex/openai@0.1.31
- @llamaindex/readers@1.0.7
## 0.0.10
### Patch Changes
- Updated dependencies [ad85bd0]
- @llamaindex/core@0.4.5
- llamaindex@0.8.8
- @llamaindex/node-parser@0.0.6
- @llamaindex/workflow@0.0.3
- @llamaindex/cloud@2.0.5
- @llamaindex/openai@0.1.30
- @llamaindex/readers@1.0.6
## 0.0.9
### Patch Changes
- @llamaindex/cloud@2.0.4
- @llamaindex/core@0.4.4
- llamaindex@0.8.7
- @llamaindex/node-parser@0.0.5
- @llamaindex/openai@0.1.29
- @llamaindex/readers@1.0.5
## 0.0.8
### Patch Changes
- Updated dependencies [95a5cc6]
- @llamaindex/core@0.4.3
- llamaindex@0.8.6
- @llamaindex/cloud@2.0.3
- @llamaindex/node-parser@0.0.4
- @llamaindex/openai@0.1.28
- @llamaindex/readers@1.0.4
## 0.0.7
### Patch Changes
- Updated dependencies [14cc9eb]
- Updated dependencies [a6db5dd]
- Updated dependencies [396b1e1]
- llamaindex@0.8.5
- @llamaindex/cloud@2.0.2
- @llamaindex/core@0.4.2
- @llamaindex/node-parser@0.0.3
- @llamaindex/openai@0.1.27
- @llamaindex/readers@1.0.3
## 0.0.6
### Patch Changes
- Updated dependencies [35430d3]
- llamaindex@0.8.4
- @llamaindex/readers@1.0.2
## 0.0.5
### Patch Changes
- Updated dependencies [2ff0a89]
- @llamaindex/node-parser@0.0.2
- llamaindex@0.8.3
## 0.0.4
### Patch Changes
- Updated dependencies [0765742]
- @llamaindex/workflow@0.0.2
## 0.0.3
### Patch Changes
- Updated dependencies [c7a918c]
- llamaindex@0.8.2
## 0.0.2
### Patch Changes
- Updated dependencies [9c73f0a]
- @llamaindex/core@0.4.1
- @llamaindex/cloud@2.0.1
- llamaindex@0.8.1
- @llamaindex/openai@0.1.26
- @llamaindex/readers@1.0.1
## 0.0.1
### Patch Changes
+3 -8
View File
@@ -1,4 +1,4 @@
# next
# Docs
This is a Next.js application generated with
[Create Fumadocs](https://github.com/fuma-nama/fumadocs).
@@ -6,15 +6,10 @@ This is a Next.js application generated with
Run development server:
```bash
npm run dev
# or
pnpm dev
# or
yarn dev
turbo run dev
# turbo will build all required packages before running the dev server
```
Open http://localhost:3000 with your browser to see the result.
## Learn More
To learn more about Next.js and Fumadocs, take a look at the following
+24 -1
View File
@@ -1,10 +1,33 @@
import { createMDX } from "fumadocs-mdx/next";
import MonacoWebpackPlugin from "monaco-editor-webpack-plugin";
const withMDX = createMDX();
/** @type {import('next').NextConfig} */
const config = {
reactStrictMode: true,
transpilePackages: ["monaco-editor"],
webpack: (config, { isServer }) => {
if (Array.isArray(config.target) && config.target.includes("web")) {
config.target = ["web", "es2020"];
}
config.resolve.alias = {
...config.resolve.alias,
sharp$: false,
"onnxruntime-node$": false,
};
config.resolve.fallback ??= {};
config.resolve.fallback.fs = false;
if (!isServer) {
config.plugins.push(
new MonacoWebpackPlugin({
languages: ["typescript"],
filename: "static/[name].worker.js",
}),
);
}
return config;
},
};
export default withMDX(config);
+38 -16
View File
@@ -1,65 +1,87 @@
{
"name": "@llamaindex/doc",
"version": "0.0.1",
"version": "0.0.16",
"private": true,
"scripts": {
"build": "pnpm run build:docs && next build",
"dev": "next dev",
"start": "next start",
"postdev": "fumadocs-mdx",
"postbuild": "fumadocs-mdx",
"postbuild": "fumadocs-mdx && tsx scripts/post-build.mts",
"build:docs": "node ./scripts/generate-docs.mjs"
},
"dependencies": {
"@icons-pack/react-simple-icons": "^10.1.0",
"@llamaindex/chat-ui": "0.0.5",
"@llamaindex/cloud": "workspace:*",
"@llamaindex/core": "workspace:*",
"@llamaindex/node-parser": "workspace:*",
"@llamaindex/openai": "workspace:*",
"@llamaindex/readers": "workspace:*",
"@llamaindex/workflow": "workspace:*",
"@mdx-js/mdx": "^3.1.0",
"@number-flow/react": "^0.3.0",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-icons": "^1.3.1",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-slider": "^1.2.1",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.3",
"ai": "^3.3.21",
"@vercel/functions": "^1.5.0",
"ai": "^3.4.31",
"class-variance-authority": "^0.7.0",
"clsx": "2.1.1",
"foxact": "^0.2.39",
"framer-motion": "^11.11.10",
"fumadocs-core": "14.0.2",
"fumadocs-docgen": "^1.3.0",
"fumadocs-mdx": "11.0.0",
"fumadocs-openapi": "^5.5.3",
"fumadocs-twoslash": "^2.0.0",
"fumadocs-ui": "14.0.2",
"foxact": "^0.2.40",
"framer-motion": "^11.11.11",
"fumadocs-core": "14.2.0",
"fumadocs-docgen": "^1.3.1",
"fumadocs-mdx": "^11.1.1",
"fumadocs-openapi": "^5.5.6",
"fumadocs-twoslash": "^2.0.1",
"fumadocs-typescript": "^3.0.1",
"fumadocs-ui": "14.2.0",
"hast-util-to-jsx-runtime": "^2.3.2",
"llamaindex": "workspace:*",
"lucide-react": "^0.436.0",
"next": "15.0.1",
"lucide-react": "^0.454.0",
"next": "15.0.2",
"next-themes": "^0.3.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
"react-monaco-editor": "^0.56.2",
"react-text-transition": "^3.1.0",
"react-use-measure": "^2.1.1",
"rehype-katex": "^7.0.1",
"remark-math": "^6.0.0",
"rimraf": "^6.0.1",
"shiki": "^1.22.0",
"shiki": "^1.22.2",
"shiki-magic-move": "^0.5.0",
"swr": "^2.2.5",
"tailwind-merge": "^2.5.2",
"tailwindcss-animate": "^1.0.7",
"tree-sitter": "^0.22.0",
"tree-sitter-typescript": "^0.23.0",
"use-stick-to-bottom": "^1.0.41",
"web-tree-sitter": "^0.24.3",
"zod": "^3.23.8"
},
"devDependencies": {
"@next/env": "^15.0.2",
"@types/mdx": "^2.0.13",
"@types/node": "22.7.8",
"@types/node": "22.9.0",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"autoprefixer": "^10.4.20",
"fast-glob": "^3.3.2",
"gray-matter": "^4.0.3",
"monaco-editor-webpack-plugin": "^7.1.0",
"postcss": "^8.4.47",
"remark": "^15.0.1",
"remark-gfm": "^4.0.0",
"remark-mdx": "^3.1.0",
"remark-stringify": "^11.0.0",
"tailwindcss": "^3.4.14",
"tsx": "^4.19.2",
"typescript": "^5.6.3"
}
}
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.
BIN
View File
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
import env from "@next/env";
import { updateLlamaCloud } from "./update-llamacloud.mjs";
env.loadEnvConfig(process.cwd());
await updateLlamaCloud();
+107
View File
@@ -0,0 +1,107 @@
import { upsertBatchPipelineDocumentsApiV1PipelinesPipelineIdDocumentsPut } from "@llamaindex/cloud/api";
import fg from "fast-glob";
import {
fileGenerator,
remarkDocGen,
remarkInstall,
typescriptGenerator,
} from "fumadocs-docgen";
import matter from "gray-matter";
import * as fs from "node:fs/promises";
import path, { relative } from "node:path";
import { fileURLToPath } from "node:url";
import { remark } from "remark";
import remarkGfm from "remark-gfm";
import remarkMdx from "remark-mdx";
import remarkStringify from "remark-stringify";
const baseDir = fileURLToPath(new URL("../src/content", import.meta.url));
async function processContent(content: string): Promise<string> {
const file = await remark()
.use(remarkMdx)
.use(remarkGfm)
.use(remarkDocGen, { generators: [typescriptGenerator(), fileGenerator()] })
.use(remarkInstall, { persist: { id: "package-manager" } })
.use(remarkStringify)
.process(content);
return String(file);
}
export async function updateLlamaCloud(): Promise<void> {
const apiKey = process.env.LLAMA_CLOUD_API_KEY;
const index = process.env.LLAMA_CLOUD_PIPELINE_ID;
if (!apiKey || !index) {
console.log("no api key for LlamaCloud found, skipping");
return;
}
const files = await fg([
"./src/content/docs/**/*.mdx",
"!./src/content/docs/cloud/api/**/*",
]);
const records: {
id: string;
title: string;
description: string;
content: string;
category: string | undefined;
}[] = [];
console.log("processing documents for AI");
const scan = files.map(async (file) => {
const fileContent = await fs.readFile(file);
const { content, data } = matter(fileContent.toString());
const dir = path.dirname(file).split(path.sep).at(3);
const category = {
cloud: "LlamaCloud",
llamaindex: "LlamaIndex.TS",
}[dir ?? ""];
if (data._mdx?.mirror) {
return;
}
const processed = await processContent(content);
const id = relative(baseDir, file);
records.push({
id,
title: data.title as string,
description: data.description as string,
content: processed,
category,
});
});
await Promise.all(scan);
console.log(`added ${records.length} records`);
await upsertBatchPipelineDocumentsApiV1PipelinesPipelineIdDocumentsPut({
baseUrl: "https://api.cloud.llamaindex.ai/",
body: records.map((record) => ({
id: record.id,
metadata: {
title: record.title,
description: record.description,
documentUrl: record.id,
category: record.category,
},
text: record.content,
})),
path: {
pipeline_id: index,
},
throwOnError: true,
headers: {
Authorization: `Bearer ${apiKey}`,
},
});
console.log("done");
}
-67
View File
@@ -1,15 +1,10 @@
import { PipelinesService } from "@llamaindex/cloud/api";
import { rehypeCodeDefaultOptions } from "fumadocs-core/mdx-plugins";
import { fileGenerator, remarkDocGen, remarkInstall } from "fumadocs-docgen";
import { defineConfig, defineDocs } from "fumadocs-mdx/config";
import { transformerTwoslash } from "fumadocs-twoslash";
import { relative } from "node:path";
import { fileURLToPath } from "node:url";
import rehypeKatex from "rehype-katex";
import remarkMath from "remark-math";
const baseDir = fileURLToPath(new URL("../src/content", import.meta.url));
export const { docs, meta } = defineDocs({
dir: "./src/content/docs",
});
@@ -49,68 +44,6 @@ export default defineConfig({
remarkMath,
[remarkInstall, { persist: { id: "package-manager" } }],
[remarkDocGen, { generators: [fileGenerator()] }],
() => {
return (_, file, next) => {
const metadata = file.data.frontmatter as Record<string, unknown>;
const title = metadata.title as string;
const description = metadata.description as string;
let content: string;
if (file.value instanceof Uint8Array) {
content = file.value.toString();
} else {
content = file.value;
}
if (file.path.includes("content/docs/cloud/api")) {
// skip cloud api docs
return next();
}
// eslint-disable-next-line turbo/no-undeclared-env-vars
if (process.env.NODE_ENV === "development") {
// skip development
return next();
}
if (!title || !description) {
throw new Error(`Missing title or description in ${file.path}`);
}
const id = relative(baseDir, file.path);
if (
// eslint-disable-next-line turbo/no-undeclared-env-vars
process.env.LLAMA_CLOUD_UPSERT_PIPELINE_DOCUMENTS === "true" &&
// eslint-disable-next-line turbo/no-undeclared-env-vars
process.env.LLAMA_CLOUD_PIPELINE_ID !== undefined
) {
PipelinesService.upsertBatchPipelineDocumentsApiV1PipelinesPipelineIdDocumentsPut(
{
baseUrl: "https://api.cloud.llamaindex.ai/",
body: [
{
metadata: {
title,
description,
documentUrl: id,
},
text: content,
id,
},
],
path: {
// eslint-disable-next-line turbo/no-undeclared-env-vars
pipeline_id: process.env.LLAMA_CLOUD_PIPELINE_ID,
},
throwOnError: true,
headers: {
// eslint-disable-next-line turbo/no-undeclared-env-vars
Authorization: `Bearer ${process.env.LLAMA_CLOUD_API_KEY}`,
},
},
).catch((error) => {
console.error(error);
});
}
return next();
};
},
],
rehypePlugins: (v) => [rehypeKatex, ...v],
},
+3 -3
View File
@@ -14,10 +14,9 @@ Settings.llm = new OpenAI({
});
const retriever = new LlamaCloudRetriever({
// eslint-disable-next-line turbo/no-undeclared-env-vars
apiKey: process.env.LLAMA_CLOUD_API_KEY!,
baseUrl: "https://api.cloud.llamaindex.ai/",
// eslint-disable-next-line turbo/no-undeclared-env-vars
pipelineId: process.env.LLAMA_CLOUD_PIPELINE_ID!,
});
@@ -27,7 +26,7 @@ const initialAIState = {
messages: ChatMessage[];
};
type UIMessage = {
export type UIMessage = {
id: number;
display: ReactNode;
};
@@ -38,6 +37,7 @@ const initialUIState = {
messages: UIMessage[];
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const runAsyncFnWithoutBlocking = (fn: (...args: any) => Promise<any>) => {
fn().catch((error) => {
console.error(error);
+18 -17
View File
@@ -11,7 +11,7 @@ import { NpmInstall } from "@/components/npm-install";
import { TextEffect } from "@/components/text-effect";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import { DOCUMENT_URL } from "@/lib/const";
import { LEGACY_DOCUMENT_URL } from "@/lib/const";
import { SiStackblitz } from "@icons-pack/react-simple-icons";
import {
CodeBlock as FumaCodeBlock,
@@ -25,20 +25,21 @@ export default function HomePage() {
return (
<main className="container mx-auto px-4 py-12">
<h1 className="text-4xl md:text-6xl font-bold text-center mb-4">
Build RAG Web App using
Build context-augmented web apps using
<br /> <span className="text-blue-500">LlamaIndex.TS</span>
</h1>
<p className="text-xl text-center text-fd-muted-foreground mb-12 ">
LlamaIndex.TS is the JS/TS library from our popular Python library
llama-index for building LLM applications
LlamaIndex.TS is the JS/TS version of{" "}
<a href="https://llamaindex.ai">LlamaIndex</a>, the framework for
building agentic generative AI applications connected to your data.
</p>
<div className="text-center text-lg text-fd-muted-foreground mb-12">
<span>Designed for building web applications under </span>
<span>Designed for building web applications in </span>
<TextEffect />
</div>
<div className="flex flex-wrap justify-center gap-4">
<Link href={DOCUMENT_URL}>
<Link href={LEGACY_DOCUMENT_URL}>
<Button variant="outline">Get Started</Button>
</Link>
<NpmInstall />
@@ -58,8 +59,8 @@ export default function HomePage() {
<Feature
icon={Footprints}
subheading="Progressive"
heading="Adding AI feature from simple to complex"
description="LlamaIndex.TS is designed to be simple to start with and can be extended to build complex AI applications."
heading="From the simplest to the most complex"
description="LlamaIndex.TS is designed to be simple to get started, but powerful enough to build complex, agentic AI applications."
>
<Suspense
fallback={
@@ -113,9 +114,9 @@ const response = await agent.chat({
</Feature>
<Feature
icon={Bot}
subheading="Agent"
heading="Build agent for RAG"
description="Build agents for RAG using LlamaIndex.TS. Agents are the core building blocks of RAG applications."
subheading="Agents"
heading="Build agentic RAG applications"
description="Truly powerful retrieval-augmented generation applications use agentic techniques, and LlamaIndex.TS makes it easy to build them."
>
<CodeBlock
code={`import { FunctionTool } from "llamaindex";
@@ -137,19 +138,19 @@ await agent.chat('...');`}
<Feature
icon={Blocks}
subheading="Providers"
heading="LLM / Data Loader / Vector Store"
description="LlamaIndex.TS provides various providers to turn your data into valuable insights."
heading="LLMs, Data Loaders, Vector Stores and more!"
description="LlamaIndex.TS has hundreds of integrations to connect to your data, index it, and query it with LLMs."
>
<div className="mt-8 flex flex-col gap-8">
<div>
<h3 className="text-lg font-semibold text-fd-muted-foreground mb-2">
LLM
LLMs
</h3>
<InfiniteLLMProviders />
</div>
<div>
<h3 className="text-lg font-semibold text-fd-muted-foreground mb-2">
Vector Store
Vector Stores
</h3>
<InfiniteVectorStoreProviders />
</div>
@@ -157,8 +158,8 @@ await agent.chat('...');`}
</Feature>
<Feature
icon={Terminal}
subheading="Create Llama CLI"
heading="CLI for starting RAG app with one line"
subheading="create-llama CLI"
heading="Build a RAG app with a single command"
description="A command line tool to generate LlamaIndex apps, the easiest way to get started with LlamaIndex."
>
<div className="my-6">
+2 -2
View File
@@ -1,4 +1,4 @@
import { DOCUMENT_URL } from "@/lib/const";
import { LEGACY_DOCUMENT_URL } from "@/lib/const";
import { redirect } from "next/navigation";
export default async function Page(props: {
@@ -7,5 +7,5 @@ export default async function Page(props: {
}>;
}) {
const path = await props.params.then(({ any }) => any.join("/"));
return redirect(new URL(path, DOCUMENT_URL).toString());
return redirect(new URL(path, LEGACY_DOCUMENT_URL).toString());
}
+30
View File
@@ -0,0 +1,30 @@
import { LlamaIndexAdapter, type Message } from "ai";
import { SimpleChatEngine, type ChatMessage } from "llamaindex";
import { NextResponse, type NextRequest } from "next/server";
export async function POST(request: NextRequest) {
try {
const { messages } = (await request.json()) as { messages: Message[] };
const userMessage = messages[messages.length - 1];
if (!userMessage || userMessage.role !== "user") {
return NextResponse.json(
{ detail: "Last message is not a user message" },
{ status: 400 },
);
}
const chatEngine = new SimpleChatEngine();
return LlamaIndexAdapter.toDataStreamResponse(
await chatEngine.chat({
message: userMessage.content,
chatHistory: messages as ChatMessage[],
stream: true,
}),
{},
);
} catch (error) {
const detail = (error as Error).message;
return NextResponse.json({ detail }, { status: 500 });
}
}
+14 -1
View File
@@ -1,6 +1,7 @@
import { createMetadata, metadataImage } from "@/lib/metadata";
import { openapi, source } from "@/lib/source";
import { Popup, PopupContent, PopupTrigger } from "fumadocs-twoslash/ui";
import { createTypeTable } from "fumadocs-typescript/ui";
import defaultMdxComponents from "fumadocs-ui/mdx";
import {
DocsBody,
@@ -10,6 +11,8 @@ import {
} from "fumadocs-ui/page";
import { notFound } from "next/navigation";
const { AutoTypeTable } = createTypeTable();
export default async function Page(props: {
params: Promise<{ slug?: string[] }>;
}) {
@@ -20,7 +23,16 @@ export default async function Page(props: {
const MDX = page.data.body;
return (
<DocsPage toc={page.data.toc} full={page.data.full}>
<DocsPage
toc={page.data.toc}
full={page.data.full}
editOnGithub={{
owner: "run-llama",
repo: "LlamaIndexTS",
sha: "main",
path: `apps/next/src/content/docs/${page.file.path}`,
}}
>
<DocsTitle>{page.data.title}</DocsTitle>
<DocsDescription>{page.data.description}</DocsDescription>
<DocsBody>
@@ -31,6 +43,7 @@ export default async function Page(props: {
Popup,
PopupContent,
PopupTrigger,
AutoTypeTable,
}}
/>
</DocsBody>
+40 -24
View File
@@ -1,38 +1,54 @@
import { baseOptions } from "@/app/layout.config";
import { AITrigger } from "@/components/ai-chat";
import { buttonVariants } from "@/components/ui/button";
import { LEGACY_DOCUMENT_URL } from "@/lib/const";
import { source } from "@/lib/source";
import { cn } from "@/lib/utils";
import "fumadocs-twoslash/twoslash.css";
import { Banner } from "fumadocs-ui/components/banner";
import { DocsLayout } from "fumadocs-ui/layouts/docs";
import { MessageCircle } from "lucide-react";
import type { ReactNode } from "react";
export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout
tree={source.pageTree}
{...baseOptions}
nav={{
...baseOptions.nav,
children: (
<AITrigger
className={cn(
buttonVariants({
variant: "secondary",
size: "xs",
className:
"md:flex-1 px-2 ms-2 gap-1.5 text-fd-muted-foreground rounded-full",
}),
)}
>
<MessageCircle className="size-3" />
Ask LlamaCloud
</AITrigger>
),
}}
>
{children}
</DocsLayout>
<>
<Banner variant="rainbow" id="welcome">
Welcome to the new LlamaIndex.TS documentation! 🎉 If you are looking
for the old documentation
<a
className="underline text-blue-500 ml-1"
target="_blank"
href={LEGACY_DOCUMENT_URL}
>
check it here
</a>
.
</Banner>
<DocsLayout
tree={source.pageTree}
{...baseOptions}
nav={{
...baseOptions.nav,
children: (
<AITrigger
className={cn(
buttonVariants({
variant: "secondary",
size: "xs",
className:
"md:flex-1 px-2 ms-2 gap-1.5 text-fd-muted-foreground rounded-full",
}),
)}
>
<MessageCircle className="size-3" />
Ask LlamaCloud
</AITrigger>
),
}}
>
{children}
</DocsLayout>
</>
);
}
+3 -3
View File
@@ -1,4 +1,4 @@
import { DOCUMENT_URL } from "@/lib/const";
import { LEGACY_DOCUMENT_URL } from "@/lib/const";
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
import Image from "next/image";
@@ -27,8 +27,8 @@ export const baseOptions: BaseLayoutProps = {
githubUrl: "https://github.com/run-llama/LlamaIndexTS",
links: [
{
text: "Documentation",
url: DOCUMENT_URL,
text: "Docs",
url: LEGACY_DOCUMENT_URL,
active: "nested-url",
},
],
+2 -2
View File
@@ -1,5 +1,5 @@
"use client";
import type { AIProvider } from "@/actions";
import type { AIProvider, UIMessage } from "@/actions";
import { UserMessage } from "@/components/message";
import { useActions, useUIState } from "ai/rsc";
import { Info } from "lucide-react";
@@ -21,7 +21,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip";
type AITriggerProps = ButtonHTMLAttributes<HTMLButtonElement>;
function ChatList({ messages }: { messages: any[] }) {
function ChatList({ messages }: { messages: UIMessage[] }) {
if (messages.length === 0) {
return null;
}
+1 -2
View File
@@ -7,9 +7,8 @@ import { ReactElement } from "react";
export function Contributing(): ReactElement {
return (
<div className="flex flex-col items-center border-x border-t px-4 py-16 text-center">
<Heart className="mb-4" />
<h2 className="mb-4 text-xl font-semibold sm:text-2xl">
Made Possible by You.
Made possible by you <Heart className="inline align-middle" />
</h2>
<p className="mb-4 text-fd-muted-foreground">
LlamaIndex.TS is powered by the open source community.
@@ -53,9 +53,6 @@ export default async function ContributorCounter({
</div>
) : null}
</div>
<div className="text-center text-sm text-fd-muted-foreground">
Some of our best contributors.
</div>
</div>
);
}
+8
View File
@@ -0,0 +1,8 @@
"use client";
import { ChatSection } from "@llamaindex/chat-ui";
import { useChat } from "ai/react";
export const ChatDemo = () => {
const handler = useChat();
return <ChatSection handler={handler} />;
};
@@ -0,0 +1,182 @@
"use client";
import { createContextState } from "foxact/context-state";
import { useIsClient } from "foxact/use-is-client";
import { useShiki } from "fumadocs-core/utils/use-shiki";
import { CodeBlock, Pre } from "fumadocs-ui/components/codeblock";
import { lazy, Suspense, use, useMemo } from "react";
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
import Parser from "web-tree-sitter";
import { Label } from "@/components/ui/label";
import { Skeleton } from "@/components/ui/skeleton";
import { Slider } from "@/components/ui/slider";
import { CodeSplitter } from "@llamaindex/node-parser/code";
let promise: Promise<CodeSplitter>;
if (typeof window !== "undefined") {
promise = Parser.init({
locateFile(scriptName: string) {
return "/" + scriptName;
},
}).then(async () => {
const parser = new Parser();
const Lang = await Parser.Language.load("/tree-sitter-typescript.wasm");
parser.setLanguage(Lang);
return new CodeSplitter({
getParser: () => parser,
maxChars: 100,
});
});
}
const [SliderProvider, useSlider, useSetSlider] = createContextState(100);
const [CodeProvider, useCode, useSetCode] =
createContextState(`interface Person {
name: string;
age: number;
}
function greet(person: Person): string {
return \`Hello, \${person.name}! You are \${person.age} years old.\`;
}
const john: Person = {
name: "John Doe",
age: 30
};
console.log(greet(john));`);
const Editor = lazy(() => import("react-monaco-editor"));
export const IDE = () => {
const codeSplitter = use(promise);
const code = useCode();
const setCode = useSetCode();
const maxChars = useSlider();
const useSetMaxChars = useSetSlider();
return (
<div className="flex flex-col p-4 border-r max-h-96 overflow-scroll">
<div>
<Label>Max Chars {maxChars}</Label>
<Slider
className="my-4"
min={10}
max={300}
step={10}
value={[maxChars]}
onValueChange={(value) => {
useSetMaxChars(value[0]);
codeSplitter.maxChars = value[0];
}}
/>
</div>
<Editor
editorWillMount={() => {}}
editorDidMount={() => {
window.MonacoEnvironment!.getWorkerUrl = (
_moduleId: string,
label: string,
) => {
if (label === "json") return "/_next/static/json.worker.js";
if (label === "css") return "/_next/static/css.worker.js";
if (label === "html") return "/_next/static/html.worker.js";
if (label === "typescript" || label === "javascript")
return "/_next/static/ts.worker.js";
return "/_next/static/editor.worker.js";
};
}}
editorWillUnmount={() => {}}
options={{
minimap: {
enabled: false,
},
}}
theme="vs-dark"
height="100%"
width="100%"
language="typescript"
onChange={setCode}
value={code}
/>
</div>
);
};
const Preview = ({ text }: { text: string }) => {
const rendered = useShiki(text, {
lang: "ts",
components: {
pre: (props) => {
return <Pre {...props}>{props.children}</Pre>;
},
},
});
return <CodeBlock className="py-0 m-2">{rendered}</CodeBlock>;
};
function ScrollToBottom() {
const { isAtBottom, scrollToBottom } = useStickToBottomContext();
return (
!isAtBottom && (
<button
className="absolute i-ph-arrow-circle-down-fill text-4xl rounded-lg left-[50%] translate-x-[-50%] bottom-0"
onClick={() => scrollToBottom()}
/>
)
);
}
export const NodePreview = () => {
const parser = use(promise);
const code = useCode();
const maxChars = useSlider();
const textChunks = useMemo(() => parser.splitText(code), [code, maxChars]);
return (
<StickToBottom
className="block relative max-h-96 overflow-scroll"
resize="smooth"
initial="smooth"
>
<StickToBottom.Content>
{textChunks.map((chunk, i) => (
<Preview key={i} text={chunk} />
))}
</StickToBottom.Content>
<ScrollToBottom />
</StickToBottom>
);
};
export const CodeNodeParserDemo = () => {
const isClient = useIsClient();
if (!isClient) {
return (
<div className="my-2 grid grid-cols-1 md:grid-cols-2 gap-2 border rounded-xl w-full max-h-96">
<Skeleton className="h-96" />
<Skeleton className="h-96" />
</div>
);
}
return (
<SliderProvider>
<CodeProvider>
<Suspense
fallback={
<div className="my-2 grid grid-cols-1 md:grid-cols-2 gap-2 border rounded-xl w-full max-h-96">
<Skeleton className="h-96" />
<Skeleton className="h-96" />
</div>
}
>
<div className="my-2 grid grid-cols-1 md:grid-cols-2 gap-2 border rounded-xl w-full max-h-96">
<IDE />
<NodePreview />
</div>
</Suspense>
</CodeProvider>
</SliderProvider>
);
};
@@ -0,0 +1,152 @@
"use client";
import FlowInput from "@/components/flow-input";
import { Button } from "@/components/ui/button";
import {
StartEvent,
StopEvent,
Workflow,
WorkflowEvent,
} from "@llamaindex/workflow";
import { ReactNode, startTransition, useState } from "react";
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
};
const workflow = new Workflow<ContextData, number, number>();
const max = 1000;
const min = 100;
workflow.addStep(
{
inputs: [StartEvent<number>],
outputs: [StopEvent<number>],
},
async (context, event) => {
const total = event.data;
for (let i = 0; i < total; i++) {
context.sendEvent(new ComputeEvent(i));
}
console.log("waiting");
const computeResults = await Promise.all(
Array.from({ length: total }).map(() =>
context.requireEvent(ComputeResultEvent),
),
);
context.data.sum = computeResults.reduce(
(acc, result) => acc + result.data,
0,
);
console.log("stop");
return new StopEvent(context.data.sum);
},
);
workflow.addStep(
{
inputs: [ComputeEvent],
outputs: [ComputeResultEvent],
},
async (context, event) => {
await new Promise((resolve) =>
setTimeout(resolve, Math.floor(Math.random() * (max - min + 1) + min)),
);
return new ComputeResultEvent(event.data);
},
);
function ScrollToBottom() {
const { isAtBottom, scrollToBottom } = useStickToBottomContext();
return (
!isAtBottom && (
<button
className="absolute i-ph-arrow-circle-down-fill text-4xl rounded-lg left-[50%] translate-x-[-50%] bottom-0"
onClick={() => scrollToBottom()}
/>
)
);
}
export function WorkflowStreamingDemo() {
const [ui, setUI] = useState<ReactNode[]>([
<div key={0} className="bg-gray-100 dark:bg-gray-800">
Waiting for workflow to start
</div>,
]);
const [total, setTotal] = useState<number>(10);
return (
<div className="flex flex-col items-start w-full gap-2">
<div className="flex flex-row justify-center items-center">
<div className="text-lg mr-2">Compute total</div>{" "}
<FlowInput value={total} onChange={(value) => setTotal(value)} />
</div>
<Button
onClick={async () => {
startTransition(() => {
setUI([]);
});
const context = workflow.run(total, {
sum: 0,
});
let i = 0;
for await (const event of context) {
console.log(event);
if (event instanceof ComputeEvent) {
setUI((ui) => [
...ui,
<div key={i++} className="bg-yellow-100 dark:bg-yellow-800">
Computing task id: {event.data}
</div>,
]);
} else if (event instanceof ComputeResultEvent) {
setUI((ui) => [
...ui,
<div key={i++} className="bg-green-100 dark:bg-green-800">
Computed task id: {event.data}
</div>,
]);
} else if (event instanceof StartEvent) {
setUI((ui) => [
...ui,
<div key={i++} className="bg-blue-100 dark:bg-blue-800">
Started workflow with total {event.data}
</div>,
]);
} else if (event instanceof StopEvent) {
setUI((ui) => [
...ui,
<div key={i++} className="bg-red-100 dark:bg-red-800">
Workflow stopped
</div>,
]);
}
}
}}
>
Start Workflow
</Button>
<StickToBottom className="w-full flex flex-col gap-2 p-2 border border-gray-200 rounded-lg max-h-96 overflow-y-auto">
<StickToBottom.Content className="flex flex-col gap-2">
{ui}
</StickToBottom.Content>
<ScrollToBottom />
</StickToBottom>
</div>
);
}
+98
View File
@@ -0,0 +1,98 @@
import NumberFlow from "@number-flow/react";
import clsx from "clsx/lite";
import { Minus, Plus } from "lucide-react";
import * as React from "react";
type Props = {
value?: number;
min?: number;
max?: number;
onChange?: (value: number) => void;
};
export default function FlowInput({
value = 0,
min = -Infinity,
max = Infinity,
onChange,
}: Props) {
const defaultValue = React.useRef(value);
const inputRef = React.useRef<HTMLInputElement>(null);
const [animated, setAnimated] = React.useState(true);
const [showCaret, setShowCaret] = React.useState(true);
const handleInput: React.ChangeEventHandler<HTMLInputElement> = ({
currentTarget: el,
}) => {
setAnimated(false);
let next = value;
if (el.value === "") {
next = defaultValue.current;
} else {
const num = parseInt(el.value);
if (!isNaN(num) && min <= num && num <= max) next = num;
}
el.value = String(next);
onChange?.(next);
};
const handlePointerDown =
(diff: number) => (event: React.PointerEvent<HTMLButtonElement>) => {
setAnimated(true);
if (event.pointerType === "mouse") {
event?.preventDefault();
inputRef.current?.focus();
}
const newVal = Math.min(Math.max(value + diff, min), max);
onChange?.(newVal);
};
return (
<div className="group flex items-stretch rounded-md text-lg font-semibold ring ring-zinc-200 transition-[box-shadow] focus-within:ring-2 focus-within:ring-blue-500 dark:ring-zinc-800">
<button
aria-hidden
tabIndex={-1}
className="flex items-center pl-[.5em] pr-[.325em]"
disabled={min != null && value <= min}
onPointerDown={handlePointerDown(-1)}
>
<Minus className="size-4" absoluteStrokeWidth strokeWidth={3.5} />
</button>
<div className="relative grid items-center justify-items-center text-center [grid-template-areas:'overlap'] *:[grid-area:overlap]">
<input
ref={inputRef}
className={clsx(
showCaret ? "caret-primary" : "caret-transparent",
"spin-hide w-[1.5em] bg-transparent py-2 text-center font-[inherit] text-transparent outline-none",
"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
)}
// Make sure to disable kerning, to match NumberFlow:
style={{ fontKerning: "none" }}
type="number"
min={min}
step={1}
autoComplete="off"
inputMode="numeric"
max={max}
value={value}
onInput={handleInput}
/>
<NumberFlow
value={value}
format={{ useGrouping: false }}
aria-hidden
animated={animated}
onAnimationsStart={() => setShowCaret(false)}
onAnimationsFinish={() => setShowCaret(true)}
className="pointer-events-none"
willChange
/>
</div>
<button
aria-hidden
tabIndex={-1}
className="flex items-center pl-[.325em] pr-[.5em]"
disabled={max != null && value >= max}
onPointerDown={handlePointerDown(1)}
>
<Plus className="size-4" absoluteStrokeWidth strokeWidth={3.5} />
</button>
</div>
);
}
+36
View File
@@ -0,0 +1,36 @@
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { cn } from "@/lib/utils";
const badgeVariants = cva(
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
},
);
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
);
}
export { Badge, badgeVariants };
+1 -2
View File
@@ -2,8 +2,7 @@ import * as React from "react";
import { cn } from "@/lib/utils";
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
+26
View File
@@ -0,0 +1,26 @@
"use client";
import * as LabelPrimitive from "@radix-ui/react-label";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { cn } from "@/lib/utils";
const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
);
const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
<LabelPrimitive.Root
ref={ref}
className={cn(labelVariants(), className)}
{...props}
/>
));
Label.displayName = LabelPrimitive.Root.displayName;
export { Label };
+28
View File
@@ -0,0 +1,28 @@
"use client";
import * as SliderPrimitive from "@radix-ui/react-slider";
import * as React from "react";
import { cn } from "@/lib/utils";
const Slider = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
>(({ className, ...props }, ref) => (
<SliderPrimitive.Root
ref={ref}
className={cn(
"relative flex w-full touch-none select-none items-center",
className,
)}
{...props}
>
<SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
<SliderPrimitive.Range className="absolute h-full bg-primary" />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb className="block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" />
</SliderPrimitive.Root>
));
Slider.displayName = SliderPrimitive.Root.displayName;
export { Slider };
+1 -2
View File
@@ -2,8 +2,7 @@ import * as React from "react";
import { cn } from "@/lib/utils";
export interface TextareaProps
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, ...props }, ref) => {
@@ -12,7 +12,9 @@ export interface TextProps {
weight?: 400 | 500 | 600;
children?: ReactNode;
className?: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
as?: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
maximumWidth?: any;
}
@@ -0,0 +1,46 @@
---
title: Chat-UI
description: Use chat-ui to add a chat interface to your LlamaIndexTS application.
---
import { ChatDemo } from '../../../../components/demo/chat';
import "@llamaindex/chat-ui/styles/code.css";
import "@llamaindex/chat-ui/styles/katex.css";
Using [chat-ui](https://github.com/run-llama/chat-ui), it's easy to add a chat interface to your LlamaIndexTS application.
You just need to create an API route that provides an `api/chat` endpoint and a chat component to consume the API.
## API route
As an example, this is an API route for the Next.js App Router. Copy the following code into your `app/api/chat/route.ts` file to get started:
```json doc-gen:file
{
"file": "./src/app/api/chat/route.ts",
"codeblock": true
}
```
## Chat UI
This is the simplest way to add a chat interface to your application. Copy the following code into your application to consume the API:
```json doc-gen:file
{
"file": "./src/components/demo/chat.tsx",
"codeblock": true
}
```
## Try it out ⬇️
Combining both, you're getting a fully functional chat interface:
<ChatDemo />
## Next Steps
The steps above are the bare minimum to get a chat interface working. From here, you can go two ways:
1. Use [create-llama](https://github.com/run-llama/create-llama) to scaffold a new LlamaIndexTS project including complex API routes and chat interfaces or
2. Learn more about [chat-ui](https://github.com/run-llama/chat-ui) and [LlamaIndexTS](https://github.com/run-llama/llamaindex-ts) to customize the chat interface and API routes to your needs.
@@ -0,0 +1,5 @@
{
"title": "Guide",
"description": "See our guide",
"pages": ["workflow", "chat"]
}
@@ -0,0 +1,226 @@
---
title: Inputs / Outputs
description: Learn how to use different inputs and outputs in your workflows.
---
Inputs and outputs are the way to communicate between steps in a workflow. In the previous example,
we used `StartEvent` and `StopEvent` to communicate between steps. However, you can use any type of event to communicate between steps.
## Multiple inputs
You can define multiple inputs for a step.
In the following example, we define a complex workflow with multiple inputs and outputs.
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
class AEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
class BEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ResultEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
```
First, let's define the events that we will use in the workflow.
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
class AEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
class BEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ResultEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
const workflow = new Workflow<never, string, string>();
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (
context,
startEvent
) => {
const input = startEvent.data;
const aEvent = await context.requireEvent(AEvent);
const bEvent = await context.requireEvent(BEvent);
const a = aEvent.data;
const b = bEvent.data;
return new StopEvent(`Hello, ${input}! A: ${a}, B: ${b}`);
});
// ---cut---
workflow.addStep({
inputs: [AEvent, BEvent],
outputs: [ResultEvent]
}, async (
context,
aEvent,
bEvent
) => {
const a = aEvent.data;
const b = bEvent.data;
return new ResultEvent(`A: ${a}, B: ${b}`);
});
```
This step means that it requires two events: `AEvent` and `BEvent`. It will return a `ResultEvent` with the data `A: ${a}, B: ${b}`.
## A or B input
If we want to have a step that can accept either `AEvent` or `BEvent`, we can define the step like this:
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
class AEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
class BEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ResultEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
const workflow = new Workflow<never, string, string>();
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (
context,
startEvent
) => {
const input = startEvent.data;
const aEvent = await context.requireEvent(AEvent);
const bEvent = await context.requireEvent(BEvent);
const a = aEvent.data;
const b = bEvent.data;
return new StopEvent(`Hello, ${input}! A: ${a}, B: ${b}`);
});
// ---cut---
workflow.addStep({
inputs: [WorkflowEvent.or(AEvent, BEvent)],
outputs: [ResultEvent]
}, async (
context,
aOrBEvent
) => {
if (aOrBEvent instanceof AEvent) {
// ^?
const a = aOrBEvent.data;
// ^?
return new ResultEvent(`A: ${a}`);
} else {
const b = aOrBEvent.data;
// ^?
return new ResultEvent(`B: ${b}`);
}
});
```
This step means that it requires either `AEvent` or `BEvent`. It will return a `ResultEvent` with the data `A: ${a}` or `B: ${b}`.
You can still combine the logic with `context.requireEvent` to get the data from the event.
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
<Accordions>
<Accordion title="Under the hood">
We use JavaScript Inheritance and the prototype chain to implement the `or` logic.
The `or` method creates a new class that extends the two classes that you pass to it.
<a
target="_blank"
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain"
>
MDN - Inheritance and the prototype chain
</a>
</Accordion>
</Accordions>
## Multiple outputs
You can define multiple outputs for a step.
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
class AEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
class BEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ResultEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
const workflow = new Workflow<never, string, string>();
// ---cut---
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [AEvent, BEvent]
}, async (
context,
startEvent
) => {
const input = startEvent.data;
if (Math.random() > 0.5) {
return new AEvent(`Hello, ${input}!`);
} else {
return new BEvent(42);
}
});
```
This step will return either an `AEvent` or a `BEvent` based on a random number.
@@ -0,0 +1,208 @@
---
title: Basic Usage
description: Learn how to use the LlamaIndex workflow.
---
A `Workflow` in LlamaIndex.TS is an event-driven abstraction used to chain together several events.
Workflows are made up of steps, with each step responsible for handling certain event types and emitting new events.
Workflows are designed for any cases that benefit from event-driven programming, not only for LLM and AI tasks.
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install @llamaindex/workflow
```
```shell tab="yarn"
yarn add @llamaindex/workflow
```
```shell tab="pnpm"
pnpm add @llamaindex/workflow
```
</Tabs>
## Start from scratch
Let's start from a Hello World workflow.
```ts twoslash
import { Workflow } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
// ---cut---
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
// ^?
```
First, we define a workflow with 3 generic types: `ContextData`, `Input`, and `Output`.
In general, `ContextData` is used to store the shared data between steps, `Input` is the type of the input event, and `Output` is the type of the output event.
In you code logic, you should **share state between steps via `ContextData`**.
```ts twoslash
import { Workflow, StartEvent, StopEvent } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
// ---cut---
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (context, startEvent) => {
const input = startEvent.data;
context.data.counter++;
return new StopEvent(`Hello, ${input}!`);
});
```
In the workflow, we add a step that listens to `StartEvent<string>` and emits `StopEvent<string>`.
The step is an async function that takes two arguments: `context` and `event`.
### `context` type
<AutoTypeTable path="./src/deps/type.ts" name="HandlerContext" />
There are two more properties in `HandlerContext`:
- `sendEvent`: invoke another event in the workflow, other than `StartEvent`, `StopEvent`, or the current event. (Or there will have circular reference)
- `requireEvent`: wait for a specific event to be emitted.
You can use `sendEvent` and `requireEvent` to build complex workflows.
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
// ---cut---
class AnalysisStartEvent extends WorkflowEvent<string> {}
class AnalysisStopEvent extends WorkflowEvent<boolean> {}
workflow.addStep({
inputs: [AnalysisStartEvent],
outputs: [AnalysisStopEvent]
}, async (...args) => {
// do some analysis
return new AnalysisStopEvent(true);
})
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (context, startEvent) => {
const input = startEvent.data;
context.sendEvent(new AnalysisStartEvent('start'));
context.data.counter++;
const { data } = await context.requireEvent(AnalysisStopEvent);
return new StopEvent(`Hello, ${input}! Analysis result: ${data ? 'success' : 'fail'}`);
});
```
For example, you can compile `requireEvent` with `waitUntil` in [Vercel Functions](https://vercel.com/docs/functions/functions-api-reference#waituntil) or [Cloudflare Worker](https://developers.cloudflare.com/workers/runtime-apis/context/#waituntil)
```ts twoslash
import { waitUntil } from '@vercel/functions';
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
class AnalysisStartEvent extends WorkflowEvent<string> {}
class AnalysisStopEvent extends WorkflowEvent<boolean> {}
// ---cut---
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (context, startEvent) => {
const input = startEvent.data;
context.sendEvent(new AnalysisStartEvent('start'));
context.data.counter++;
waitUntil(context.requireEvent(AnalysisStopEvent));
// note that `waitUntil` is not a promise, it will extend the lifetime of the workflow
// you can wait for some background tasks to finish
return new StopEvent(`Hello, ${input}!`);
});
```
## Multiple runs
You can run the same workflow multiple times with different inputs.
```ts twoslash
import { Workflow, StartEvent, StopEvent } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (context, startEvent) => {
const input = startEvent.data;
context.data.counter++;
return new StopEvent(`Hello, ${input}!`);
});
// ---cut---
{
const ret = await workflow.run('Alex', contextData);
console.log(ret.data); // Hello, Alex!
}
{
const ret = await workflow.run('World', contextData);
console.log(ret.data); // Hello, World!
}
```
Context is shared between runs, so the counter will be increased.
Ideally, it should be serializable to make sure it can be recovered from HTTP requests or other storage.
### Full example
<iframe
className="w-full h-[440px]"
aria-label="Workflow example"
src="https://stackblitz.com/github/run-llama/LlamaIndexTS/tree/main/examples?file=node/workflow/basic.ts"
/>
## `Workflow` type
<AutoTypeTable path="./src/deps/type.ts" name="Workflow" />
## `WorkflowContext` type
<AutoTypeTable path="./src/deps/type.ts" name="WorkflowContext" />
@@ -0,0 +1,6 @@
{
"title": "Workflow",
"description": "See how to use @llamaindex/workflow",
"defaultOpen": false,
"pages": ["index", "different-inputs-outputs", "streaming"]
}
@@ -0,0 +1,199 @@
---
title: Streaming
description: Learn how to use the LlamaIndex workflow with streaming.
---
import { WorkflowStreamingDemo } from '../../../../../components/demo/workflow-streaming-ui';
`Workflow` API by default is designed for streaming data. In this guide, we will show you how to use the `Workflow` API with streaming data.
Each `workflow.run` call returns `WorkflowContext`, which implements `AsyncIterable` interface. You can use it to stream data.
```ts twoslash
import { Workflow, WorkflowEvent, StartEvent, StopEvent } from '@llamaindex/workflow';
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
}
const workflow = new Workflow<ContextData, number, number>();
workflow.addStep({
inputs: [StartEvent<number>],
outputs: [StopEvent<number>]
}, async (context, startEvent) => {
const total = startEvent.data;
for (let i = 0; i < total; i++) {
context.sendEvent(new ComputeEvent(i));
}
const computeResults = await Promise.all(Array.from({ length: total }).map(() => context.requireEvent(ComputeResultEvent)));
// Workflow API allows you to start events in parallel and wait for all of them to finish
context.data.sum = computeResults.reduce((acc, curr) => acc + curr.data, 0);
return new StopEvent(context.data.sum);
});
```
We define a parallel computation workflow that computes the sum of numbers from 0 to `total`.
The workflow sends `ComputeEvent` events for each number and waits for `ComputeResultEvent` events. After receiving all `ComputeResultEvent` events, the workflow returns the sum as a `StopEvent`.
What if we want cutoff if the sum exceeds a certain value?
## Streaming
```ts twoslash
import { Workflow, WorkflowEvent, StartEvent, StopEvent } from '@llamaindex/workflow';
import { StopCircle } from 'lucide-react';
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
}
const workflow = new Workflow<ContextData, number, number>();
// ---cut---
const context = workflow.run(1000, {
sum: 0
});
for await (const event of context) {
if (event instanceof ComputeEvent) {
if (context.data.sum > 100) {
throw new Error('Sum exceeds 100');
}
}
if (event instanceof StopEvent) {
console.log('result', event.data);
}
}
```
You can define more custom logic using `AsyncIterable` interface.
For example. I just want to stop the workflow if I get a `ComputeResultEvent`
```ts twoslash
import { Workflow, WorkflowEvent, StartEvent, StopEvent } from '@llamaindex/workflow';
import { StopCircle } from 'lucide-react';
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
}
const workflow = new Workflow<ContextData, number, number>();
// ---cut---
async function compute() {
const context = workflow.run(1000, {
sum: 0
});
for await (const event of context) {
if (event instanceof ComputeResultEvent) {
return event.data;
}
}
throw new Error('UNREACHABLE');
}
const result = await compute();
```
### Streaming with UI
You can use the `Workflow` API with UI libraries like React.
```tsx twoslash
// @filename: utils.ts
export async function runWithoutBlocking(fn: () => Promise<void>) {
fn();
}
// @filename: action.ts
// ---cut---
'use server';
// "use server" is required to enable server side feature in React
import { createStreamableUI } from 'ai/rsc';
import { runWithoutBlocking } from './utils';
// ---cut-start---
import { Workflow, WorkflowEvent, StartEvent, StopEvent } from '@llamaindex/workflow';
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
}
const workflow = new Workflow<ContextData, number, number>();
const min = 100;
const max = 1000;
workflow.addStep(
{
inputs: [ComputeEvent],
outputs: [ComputeResultEvent]
},
async (context, event) => {
await new Promise((resolve) =>
setTimeout(resolve, Math.floor(Math.random() * (max - min + 1) + min))
);
return new ComputeResultEvent(event.data);
}
);
// ---cut-end---
export async function compute() {
'use server';
const ui = createStreamableUI();
const context = workflow.run(100, {
sum: 0
});
runWithoutBlocking(async () => {
for await (const event of context) {
if (event instanceof ComputeResultEvent) {
// Update UI
} else if (event instanceof StopEvent) {
// Update UI
}
// ...
}
});
return ui.value;
}
```
<WorkflowStreamingDemo />
+20 -31
View File
@@ -5,42 +5,31 @@ description: Install llamaindex by running a single command.
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install-llamaindex" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex
```
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex
```
```shell tab="yarn"
yarn add llamaindex
```
```shell tab="pnpm"
pnpm add llamaindex
```
```shell tab="yarn"
yarn add llamaindex
```
```shell tab="pnpm"
pnpm add llamaindex
```
</Tabs>
## What's next?
<Cards>
<Card
title="I'm new to RAG"
description="Learn more about RAG (Retrieval-augmented generation) using LlamaIndex.TS."
href="/docs/llamaindex/setup/what-is-rag"
/>
<Card
title="I want to try LlamaIndex.TS"
description="Learn how to use LlamaIndex.TS with different JS runtime and frameworks."
href="/docs/llamaindex/setup"
/>
<Card
title="I want to improve performance when using LlamaIndex.TS"
description="Learn how to improve performance, reduce bundle size, improve accuracy."
href="/docs/llamaindex/performance"
/>
<Card
title="Show me code examples"
description="Explore code examples using LlamaIndex.TS."
href="https://stackblitz.com/github/run-llama/LlamaIndexTS/tree/main/examples?file=README.md"
/>
<Card
title="I want to try LlamaIndex.TS"
description="Learn how to use LlamaIndex.TS with different JS runtime and frameworks."
href="/docs/llamaindex/setup/getting-started"
/>
<Card
title="Show me code examples"
description="Explore code examples using LlamaIndex.TS."
href="https://stackblitz.com/github/run-llama/LlamaIndexTS/tree/main/examples?file=README.md"
/>
</Cards>
@@ -0,0 +1,39 @@
---
title: Langtrace
description: Learn how to integrate LlamaIndex.TS with Langtrace.
---
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
Enhance your observability with Langtrace, a robust open-source tool supports OpenTelemetry and is designed to trace, evaluate, and manage LLM applications seamlessly. Langtrace integrates directly with LlamaIndex, offering detailed, real-time insights into performance metrics such as accuracy, evaluations, and latency.
## Install
- Self-host or sign-up and generate an API key using [Langtrace](https://www.langtrace.ai) Cloud
<Tabs groupId="install-langtrase" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install @langtrase/typescript-sdk
```
```shell tab="yarn"
yarn add @langtrase/typescript-sdk
```
```shell tab="pnpm"
pnpm add @langtrase/typescript-sdk
```
</Tabs>
## Initialize
```js
import * as Langtrace from "@langtrase/typescript-sdk";
Langtrace.init({ api_key: "<YOUR_API_KEY>" });
```
Features:
- OpenTelemetry compliant, ensuring broad compatibility with observability platforms.
- Provides comprehensive logs and detailed traces of all components.
- Real-time monitoring of accuracy, evaluations, usage, costs, and latency.
- For more configuration options and details, visit [Langtrace Docs](https://docs.langtrace.ai/introduction).
@@ -0,0 +1,5 @@
{
"title": "Integration",
"description": "See our integrations",
"pages": ["open-llm-metry", "lang-trace"]
}
@@ -0,0 +1,34 @@
---
title: OpenLLMetry
description: Learn how to integrate LlamaIndex.TS with OpenLLMetry.
---
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
[OpenLLMetry](https://github.com/traceloop/openllmetry-js) is an open-source project based on OpenTelemetry for tracing and monitoring
LLM applications. It connects to [all major observability platforms](https://www.traceloop.com/docs/openllmetry/integrations/introduction) and installs in minutes.
### Usage Pattern
<Tabs groupId="install-traceloop" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install @traceloop/node-server-sdk
```
```shell tab="yarn"
yarn add @traceloop/node-server-sdk
```
```shell tab="pnpm"
pnpm add @traceloop/node-server-sdk
```
</Tabs>
```js
import * as traceloop from "@traceloop/node-server-sdk";
traceloop.initialize({
apiKey: process.env.TRACELOOP_API_KEY,
disableBatch: true
});
```
@@ -0,0 +1,5 @@
{
"title": "Loading Data",
"description": "Loading Data using LlamaIndex.TS",
"pages": ["index", "node-parser"]
}
@@ -0,0 +1,158 @@
---
title: Node Parsers / Text Splitters
description: Learn how to use Node Parsers and Text Splitters to extract data from documents.
---
import { CodeNodeParserDemo } from '../../../../components/demo/code-node-parser';
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
Node parsers are a simple abstraction that take a list of documents, and chunk them into `Node` objects, such that each node is a specific chunk of the parent document. When a document is broken into nodes, all of it's attributes are inherited to the children nodes (i.e. `metadata`, text and metadata templates, etc.). You can read more about `Node` and `Document` properties [here](./).
## NodeParser
The `NodeParser` in LlamaIndex is responsible for splitting `Document` objects into more manageable `Node` objects.
By default, we will use `Settings.nodeParser` to split the document into nodes. You can also assign a custom `NodeParser` to the `Settings` object.
```ts twoslash
import { TextFileReader } from '@llamaindex/readers/text'
import { SentenceSplitter } from '@llamaindex/core/node-parser';
import { Settings } from 'llamaindex';
const nodeParser = new SentenceSplitter();
Settings.nodeParser = nodeParser;
// ^?
```
## TextSplitter
The underlying text splitter will split text by sentences. It can also be used as a standalone module for splitting raw text.
```ts twoslash
import { SentenceSplitter } from "@llamaindex/core/node-parser";
const splitter = new SentenceSplitter({ chunkSize: 1 });
const texts = splitter.splitText("Hello World");
// ^?
```
## MarkdownNodeParser
The `MarkdownNodeParser` is a more advanced `NodeParser` that can handle markdown documents. It will split the markdown into nodes and then parse the nodes into a `Document` object.
<Tabs items={["with reader", "with node:fs"]}>
```ts twoslash tab="with reader"
import { MarkdownNodeParser } from "@llamaindex/core/node-parser";
import { MarkdownReader } from '@llamaindex/readers/markdown'
const reader = new MarkdownReader();
const markdownNodeParser = new MarkdownNodeParser();
const documents = await reader.loadData('path/to/file.md');
const parsedDocuments = markdownNodeParser(documents);
// ^?
```
```ts twoslash tab="with node:fs"
import fs from 'node:fs/promises';
import { MarkdownNodeParser } from "@llamaindex/core/node-parser";
import { Document } from '@llamaindex/core/schema';
const markdownNodeParser = new MarkdownNodeParser();
const text = await fs.readFile('path/to/file.md', 'utf-8');
const document = new Document({ text });
const parsedDocuments = markdownNodeParser([document]);
// ^?
```
</Tabs>
## CodeSplitter
The `CodeSplitter` is a more advanced `NodeParser` that can handle code documents.
It will split the code by AST nodes and then parse the nodes into a `Document` object.
<Tabs items={["with reader", "with node:fs"]}>
```ts twoslash tab="with reader"
import { TextFileReader } from '@llamaindex/readers/text'
import { CodeSplitter } from '@llamaindex/node-parser/code'
import Parser from "tree-sitter";
import TS from "tree-sitter-typescript";
const parser = new Parser();
parser.setLanguage(TS.typescript);
const codeSplitter = new CodeSplitter({
getParser: () => parser,
});
const reader = new TextFileReader();
const documents = await reader.loadData('path/to/file.ts');
const parsedDocuments = codeSplitter(documents);
// ^?
```
```ts twoslash tab="with node:fs"
import fs from 'node:fs/promises';
import { CodeSplitter } from '@llamaindex/node-parser/code'
import Parser from "tree-sitter";
import TS from "tree-sitter-typescript";
const parser = new Parser();
parser.setLanguage(TS.typescript);
const codeSplitter = new CodeSplitter({
getParser: () => parser,
});
const parsedDocuments = codeSplitter.splitText(await fs.readFile('path/to/file.ts', 'utf-8'));
// ^?
```
</Tabs>
Try it out ⬇️
<CodeNodeParserDemo/>
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
<Accordions>
<Accordion title="Use it in browser">
You might setup WASM files for `web-tree-sitter` and use it in the browser.
```ts
import Parser from 'web-tree-sitter';
Parser.init({
locateFile(scriptName: string) {
return '/' + scriptName
},
}).then(async () => {
const parser = new Parser();
const Lang = await Parser.Language.load('/tree-sitter-typescript.wasm');
parser.setLanguage(Lang);
return new CodeSplitter({
getParser: () => parser,
maxChars: 100
});
});
```
In this example, you should put `tree-sitter-typescript.wasm` to the `public` folder for Next.js.
And also update the `next.config.js` to make `@llamaindex/env` work properly.
```js
const config = {
webpack: (config) => {
if (Array.isArray(config.target) && config.target.includes('web')) {
config.target = ["web", "es2020"];
}
return config;
}
}
export default config;
```
</Accordion>
</Accordions>
@@ -8,6 +8,8 @@
"index",
"setup",
"starter",
"readers"
"loading",
"guide",
"integration"
]
}
@@ -1,5 +0,0 @@
{
"title": "Loading",
"description": "File Readers Collection",
"pages": ["index"]
}
@@ -20,7 +20,7 @@ import {
<>
<SiTypescript className="inline" color="#3178C6" /> TypeScript
</>
} href="/docs/llamaindex/setup/typescript.mdx" />
} href="/docs/llamaindex/setup/typescript" />
<Card title={
<>
<SiVite className='inline' color='#646CFF' /> Vite
@@ -29,7 +29,7 @@ import {
<Card
title={
<>
<SiNextdotjs className='inline' color='#000000' /> Next.js (React Server Component)
<SiNextdotjs className='inline' /> Next.js (React Server Component)
</>
}
href="/docs/llamaindex/setup/next"
@@ -93,6 +93,35 @@ See more about [moduleResolution](https://www.typescriptlang.org/docs/handbook/m
</Accordion>
</Accordions>
## Enable AsyncIterable for `Web Stream` API
Some modules uses `Web Stream` API like `ReadableStream` and `WritableStream`, you need to enable `DOM.AsyncIterable` in your `tsconfig.json`.
```json5
{
compilerOptions: {
// ⬇️ add this lib to your tsconfig.json
lib: ["DOM.AsyncIterable"],
},
}
```
```ts twoslash
import { OpenAIAgent } from '@llamaindex/openai'
const agent = new OpenAIAgent({
tools: []
})
const response = await agent.chat({
message: 'Hello, how are you?',
stream: true
})
for await (const _ of response) {
//^?
// ...
}
```
## Run TypeScript Script in Node.js
+2 -2
View File
@@ -1,8 +1,8 @@
import {
type MetadataFilter,
type MetadataFilters,
PipelinesService,
type RetrievalParams,
runSearchApiV1PipelinesPipelineIdRetrievePost,
type TextNodeWithScore,
} from "@llamaindex/cloud/api";
import { QueryBundle } from "@llamaindex/core/query-engine";
@@ -74,7 +74,7 @@ export class LlamaCloudRetriever extends BaseRetriever {
const pipelineId = this.pipelineId;
const { data: results } =
await PipelinesService.runSearchApiV1PipelinesPipelineIdRetrievePost({
await runSearchApiV1PipelinesPipelineIdRetrievePost({
throwOnError: true,
path: {
pipeline_id: pipelineId,
+5
View File
@@ -0,0 +1,5 @@
export type {
HandlerContext,
Workflow,
WorkflowContext,
} from "@llamaindex/workflow";
+1 -1
View File
@@ -1,2 +1,2 @@
// when we are ready, change to /docs/llamaindex
export const DOCUMENT_URL = 'https://legacy.ts.llamaindex.ai/'
export const LEGACY_DOCUMENT_URL = 'https://legacy.ts.llamaindex.ai/'
+2
View File
@@ -10,8 +10,10 @@ export default {
"./src/mdx-components.{ts,tsx}",
"./node_modules/fumadocs-ui/dist/**/*.js",
"./node_modules/fumadocs-openapi/dist/**/*.js",
"./node_modules/@llamaindex/chat-ui/**/*.{ts,tsx}",
],
presets: [createPreset()],
// eslint-disable-next-line @typescript-eslint/no-require-imports
plugins: [require("tailwindcss-animate")],
theme: {
extend: {
+7 -1
View File
@@ -24,6 +24,12 @@
}
]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
"**/*.mts"
],
"exclude": ["node_modules"]
}
+16
View File
@@ -0,0 +1,16 @@
{
"extends": ["//"],
"tasks": {
"build": {
"outputs": [
".next",
".source",
"next-env.d.ts",
"src/content/docs/cloud/api/**"
]
},
"dev": {
"dependsOn": ["^build"]
}
}
}
-7
View File
@@ -1,7 +0,0 @@
<svg fill="none" height="50" viewBox="0 0 512 512" width="50" xmlns="http://www.w3.org/2000/svg">
<rect fill="#3178c6" height="512" rx="50" width="512" />
<rect fill="#3178c6" height="512" rx="50" width="512" />
<path clip-rule="evenodd"
d="m316.939 407.424v50.061c8.138 4.172 17.763 7.3 28.875 9.386s22.823 3.129 35.135 3.129c11.999 0 23.397-1.147 34.196-3.442 10.799-2.294 20.268-6.075 28.406-11.342 8.138-5.266 14.581-12.15 19.328-20.65s7.121-19.007 7.121-31.522c0-9.074-1.356-17.026-4.069-23.857s-6.625-12.906-11.738-18.225c-5.112-5.319-11.242-10.091-18.389-14.315s-15.207-8.213-24.18-11.967c-6.573-2.712-12.468-5.345-17.685-7.9-5.217-2.556-9.651-5.163-13.303-7.822-3.652-2.66-6.469-5.476-8.451-8.448-1.982-2.973-2.974-6.336-2.974-10.091 0-3.441.887-6.544 2.661-9.308s4.278-5.136 7.512-7.118c3.235-1.981 7.199-3.52 11.894-4.615 4.696-1.095 9.912-1.642 15.651-1.642 4.173 0 8.581.313 13.224.938 4.643.626 9.312 1.591 14.008 2.894 4.695 1.304 9.259 2.947 13.694 4.928 4.434 1.982 8.529 4.276 12.285 6.884v-46.776c-7.616-2.92-15.937-5.084-24.962-6.492s-19.381-2.112-31.066-2.112c-11.895 0-23.163 1.278-33.805 3.833s-20.006 6.544-28.093 11.967c-8.086 5.424-14.476 12.333-19.171 20.729-4.695 8.395-7.043 18.433-7.043 30.114 0 14.914 4.304 27.638 12.912 38.172 8.607 10.533 21.675 19.45 39.204 26.751 6.886 2.816 13.303 5.579 19.25 8.291s11.086 5.528 15.415 8.448c4.33 2.92 7.747 6.101 10.252 9.543 2.504 3.441 3.756 7.352 3.756 11.733 0 3.233-.783 6.231-2.348 8.995s-3.939 5.162-7.121 7.196-7.147 3.624-11.894 4.771c-4.748 1.148-10.303 1.721-16.668 1.721-10.851 0-21.597-1.903-32.24-5.71-10.642-3.806-20.502-9.516-29.579-17.13zm-84.159-123.342h64.22v-41.082h-179v41.082h63.906v182.918h50.874z"
fill="#fff" fill-rule="evenodd" />
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

@@ -1,5 +1,93 @@
# @llamaindex/cloudflare-worker-agent-test
## 0.0.109
### Patch Changes
- llamaindex@0.8.13
## 0.0.108
### Patch Changes
- llamaindex@0.8.12
## 0.0.107
### Patch Changes
- llamaindex@0.8.11
## 0.0.106
### Patch Changes
- Updated dependencies [f066e50]
- llamaindex@0.8.10
## 0.0.105
### Patch Changes
- Updated dependencies [4fc001c]
- Updated dependencies [4d4cd8a]
- llamaindex@0.8.9
## 0.0.104
### Patch Changes
- Updated dependencies [ad85bd0]
- llamaindex@0.8.8
## 0.0.103
### Patch Changes
- llamaindex@0.8.7
## 0.0.102
### Patch Changes
- Updated dependencies [95a5cc6]
- llamaindex@0.8.6
## 0.0.101
### Patch Changes
- Updated dependencies [14cc9eb]
- Updated dependencies [a6db5dd]
- Updated dependencies [396b1e1]
- llamaindex@0.8.5
## 0.0.100
### Patch Changes
- Updated dependencies [35430d3]
- llamaindex@0.8.4
## 0.0.99
### Patch Changes
- llamaindex@0.8.3
## 0.0.98
### Patch Changes
- Updated dependencies [c7a918c]
- llamaindex@0.8.2
## 0.0.97
### Patch Changes
- llamaindex@0.8.1
## 0.0.96
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/cloudflare-worker-agent-test",
"version": "0.0.96",
"version": "0.0.109",
"type": "module",
"private": true,
"scripts": {
@@ -14,10 +14,10 @@
"devDependencies": {
"@cloudflare/vitest-pool-workers": "^0.5.8",
"@cloudflare/workers-types": "^4.20240924.0",
"@vitest/runner": "2.1.1",
"@vitest/snapshot": "2.1.1",
"typescript": "^5.6.2",
"vitest": "2.1.1",
"@vitest/runner": "2.1.4",
"@vitest/snapshot": "2.1.4",
"typescript": "^5.6.3",
"vitest": "2.1.4",
"wrangler": "^3.78.8"
},
"dependencies": {
@@ -1,3 +1,4 @@
// Generated by Wrangler
// After adding bindings to `wrangler.toml`, regenerate this interface via `npm run cf-typegen`
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface Env {}
@@ -1,5 +1,65 @@
# @llamaindex/llama-parse-browser-test
## 0.0.30
### Patch Changes
- @llamaindex/cloud@2.0.10
## 0.0.29
### Patch Changes
- @llamaindex/cloud@2.0.9
## 0.0.28
### Patch Changes
- @llamaindex/cloud@2.0.8
## 0.0.27
### Patch Changes
- @llamaindex/cloud@2.0.7
## 0.0.26
### Patch Changes
- @llamaindex/cloud@2.0.6
## 0.0.25
### Patch Changes
- @llamaindex/cloud@2.0.5
## 0.0.24
### Patch Changes
- @llamaindex/cloud@2.0.4
## 0.0.23
### Patch Changes
- @llamaindex/cloud@2.0.3
## 0.0.22
### Patch Changes
- @llamaindex/cloud@2.0.2
## 0.0.21
### Patch Changes
- @llamaindex/cloud@2.0.1
## 0.0.20
### Patch Changes
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/llama-parse-browser-test",
"private": true,
"version": "0.0.20",
"version": "0.0.30",
"type": "module",
"scripts": {
"dev": "vite",
@@ -9,7 +9,7 @@
"preview": "vite preview"
},
"devDependencies": {
"typescript": "^5.5.3",
"typescript": "^5.6.3",
"vite": "^5.4.1",
"vite-plugin-wasm": "^3.3.0"
},
@@ -1,5 +1,5 @@
{
"extends": "../../../../../tsconfig.json",
"extends": "../../../tsconfig.json",
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
@@ -20,7 +20,7 @@
},
"references": [
{
"path": "../../../../cloud/tsconfig.json"
"path": "../../../packages/cloud/tsconfig.json"
}
]
}
@@ -1,5 +1,93 @@
# @llamaindex/next-agent-test
## 0.1.109
### Patch Changes
- llamaindex@0.8.13
## 0.1.108
### Patch Changes
- llamaindex@0.8.12
## 0.1.107
### Patch Changes
- llamaindex@0.8.11
## 0.1.106
### Patch Changes
- Updated dependencies [f066e50]
- llamaindex@0.8.10
## 0.1.105
### Patch Changes
- Updated dependencies [4fc001c]
- Updated dependencies [4d4cd8a]
- llamaindex@0.8.9
## 0.1.104
### Patch Changes
- Updated dependencies [ad85bd0]
- llamaindex@0.8.8
## 0.1.103
### Patch Changes
- llamaindex@0.8.7
## 0.1.102
### Patch Changes
- Updated dependencies [95a5cc6]
- llamaindex@0.8.6
## 0.1.101
### Patch Changes
- Updated dependencies [14cc9eb]
- Updated dependencies [a6db5dd]
- Updated dependencies [396b1e1]
- llamaindex@0.8.5
## 0.1.100
### Patch Changes
- Updated dependencies [35430d3]
- llamaindex@0.8.4
## 0.1.99
### Patch Changes
- llamaindex@0.8.3
## 0.1.98
### Patch Changes
- Updated dependencies [c7a918c]
- llamaindex@0.8.2
## 0.1.97
### Patch Changes
- llamaindex@0.8.1
## 0.1.96
### Patch Changes
@@ -1,28 +1,27 @@
{
"name": "@llamaindex/next-agent-test",
"version": "0.1.96",
"version": "0.1.109",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"start": "next start"
},
"dependencies": {
"ai": "^3.3.21",
"llamaindex": "workspace:*",
"next": "14.2.11",
"next": "15.0.2",
"react": "18.3.1",
"react-dom": "18.3.1"
},
"devDependencies": {
"@types/node": "^22.5.1",
"@types/node": "^22.9.0",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"eslint": "8.57.0",
"eslint-config-next": "14.2.11",
"eslint": "9.14.0",
"eslint-config-next": "15.0.2",
"postcss": "^8.4.41",
"tailwindcss": "^3.4.10",
"typescript": "^5.6.2"
"typescript": "^5.6.3"
}
}

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before

Width:  |  Height:  |  Size: 629 B

After

Width:  |  Height:  |  Size: 629 B

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Some files were not shown because too many files have changed in this diff Show More