Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 14792cd8b4 | |||
| 7ae6eaa0a2 | |||
| dbb5bd9f23 | |||
| aacd606204 | |||
| f865c984d3 | |||
| 7b10882d06 | |||
| f066e50482 | |||
| fd8c882792 | |||
| d89ebe0261 | |||
| 968feb32cd | |||
| 43f6f56c5b | |||
| b2364dc5ba | |||
| 67f4db8501 | |||
| e4151a8b02 | |||
| 4d4cd8ac6b | |||
| 4fc001c8de | |||
| cf675bdc7a | |||
| 660b831b9e | |||
| ad85bd0b46 | |||
| 18ec1f2f61 | |||
| b0fbd8b5c8 | |||
| c0dfc8c641 | |||
| a8d3fa68a1 | |||
| f9470c470a | |||
| 95a5cc6ee1 | |||
| 487782cd98 | |||
| 58e65d399e | |||
| fdad3d66ac | |||
| a6db5dd29b | |||
| 7b684c4480 | |||
| c66868a98a | |||
| 14cc9ebe59 | |||
| 396b1e1474 | |||
| 69f3095424 | |||
| dc8bd5ea92 | |||
| 4af9a77d8b | |||
| 9c1d094455 | |||
| 0a8e3fdbcd | |||
| 1c0e0e1e1d | |||
| 47a7c3ea15 | |||
| 898cff0d6a | |||
| 9df37edef4 | |||
| f86a7a4fa3 | |||
| 35430d3609 | |||
| 3c162b2b4a | |||
| 5bb4531245 | |||
| 2ff0a89891 | |||
| d57917d782 | |||
| f231e0739f | |||
| 0765742ef3 | |||
| ec7fd6be5c | |||
| c7a918c3f5 | |||
| 00e681d43b | |||
| c01502fb84 | |||
| 075f88dbc3 | |||
| cc47ee0602 | |||
| 5e6ef55a5a | |||
| 9c73f0a530 | |||
| 52a4d2b83d | |||
| 0fd78d5434 |
@@ -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/"],
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -25,7 +25,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 +57,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
|
||||
|
||||
|
||||
@@ -1,5 +1,95 @@
|
||||
# docs
|
||||
|
||||
## 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";
|
||||
|
||||
@@ -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 }],
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docs",
|
||||
"version": "0.0.103",
|
||||
"version": "0.0.116",
|
||||
"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: (
|
||||
<>
|
||||
|
||||
@@ -29,3 +29,4 @@ next-env.d.ts
|
||||
|
||||
# build
|
||||
/src/content/docs/cloud/api
|
||||
./types
|
||||
|
||||
@@ -1,5 +1,149 @@
|
||||
# @llamaindex/doc
|
||||
|
||||
## 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,65 +1,87 @@
|
||||
{
|
||||
"name": "@llamaindex/doc",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.14",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import env from "@next/env";
|
||||
|
||||
import { updateLlamaCloud } from "./update-llamacloud.mjs";
|
||||
|
||||
env.loadEnvConfig(process.cwd());
|
||||
|
||||
await updateLlamaCloud();
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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],
|
||||
},
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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 };
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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 };
|
||||
@@ -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 };
|
||||
@@ -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 />
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export type {
|
||||
HandlerContext,
|
||||
Workflow,
|
||||
WorkflowContext,
|
||||
} from "@llamaindex/workflow";
|
||||
@@ -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/'
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": ["//"],
|
||||
"tasks": {
|
||||
"build": {
|
||||
"outputs": [
|
||||
".next",
|
||||
".source",
|
||||
"next-env.d.ts",
|
||||
"src/content/docs/cloud/api/**"
|
||||
]
|
||||
},
|
||||
"dev": {
|
||||
"dependsOn": ["^build"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,87 @@
|
||||
# @llamaindex/cloudflare-worker-agent-test
|
||||
|
||||
## 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.108",
|
||||
"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,59 @@
|
||||
# @llamaindex/llama-parse-browser-test
|
||||
|
||||
## 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.29",
|
||||
"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,87 @@
|
||||
# @llamaindex/next-agent-test
|
||||
|
||||
## 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.108",
|
||||
"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 |