Compare commits

...

15 Commits

Author SHA1 Message Date
github-actions[bot] 5bb4531245 Release 0.8.3 (#1427)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-11-02 19:05:28 -07:00
Alex Yang 2ff0a89891 fix: expose @llamaindex/node-parser (#1426) 2024-11-02 18:57:05 -07:00
Alex Yang d57917d782 feat: add code splitter and html node parser (#1425) 2024-11-02 15:14:03 -07:00
github-actions[bot] f231e0739f Release (#1424)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: himself65 <himself65@users.noreply.github.com>
2024-11-01 16:50:36 -07:00
Alex Yang 0765742ef3 feat: revamped workflow (#1422) 2024-11-01 15:59:19 -07:00
github-actions[bot] ec7fd6be5c Release 0.8.2 (#1421)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-31 23:54:40 -07:00
Thuc Pham c7a918c3f5 fix: export postprocessors in core (#1419) 2024-10-31 23:40:37 -07:00
Marcus Schiesser 00e681d43b ci: run type-check for reader examples 2024-11-01 12:52:06 +07:00
Alex Yang c01502fb84 docs: update document (#1418) 2024-10-31 14:02:31 -07:00
github-actions[bot] 075f88dbc3 Release 0.8.1 (#1415)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-31 11:57:26 -07:00
Alex Yang cc47ee0602 docs: update README.md (#1416) 2024-10-31 11:56:54 -07:00
Alex Yang 5e6ef55a5a chore: drop nodejs 18 support (#1414) 2024-10-31 11:23:29 -07:00
Alex Yang 9c73f0a530 fix(core): async local storage in Setting.with API (#1413) 2024-10-31 11:06:14 -07:00
Alex Yang 52a4d2b83d chore: bump to eslint 9 (#1410) 2024-10-30 18:34:17 -07:00
Alex Yang 0fd78d5434 docs(next): fix update llamacloud (#1409) 2024-10-29 21:47:21 -07:00
271 changed files with 7933 additions and 4383 deletions
-84
View File
@@ -1,84 +0,0 @@
const { join } = require("node:path");
module.exports = {
root: true,
extends: [
"turbo",
"prettier",
"plugin:@typescript-eslint/recommended-type-checked-only",
],
parserOptions: {
project: join(__dirname, "tsconfig.eslint.json"),
__tsconfigRootDir: __dirname,
},
settings: {
react: {
version: "999.999.999",
},
},
rules: {
"max-params": ["error", 4],
"prefer-const": "error",
"@typescript-eslint/no-floating-promises": [
"error",
{
ignoreIIFE: true,
},
],
"no-debugger": "error",
"@typescript-eslint/await-thenable": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-types": "off",
"no-array-constructor": "off",
"@typescript-eslint/no-array-constructor": "off",
"@typescript-eslint/no-base-to-string": [
"error",
{
ignoredTypeNames: ["Error", "RegExp", "URL", "URLSearchParams"],
},
],
"@typescript-eslint/no-duplicate-enum-values": "off",
"@typescript-eslint/no-duplicate-type-constituents": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-extra-non-null-assertion": "off",
"@typescript-eslint/no-for-in-array": "off",
"no-implied-eval": "off",
"@typescript-eslint/no-implied-eval": "off",
"no-loss-of-precision": "off",
"@typescript-eslint/no-loss-of-precision": "off",
"@typescript-eslint/no-misused-new": "off",
"@typescript-eslint/no-misused-promises": "off",
"@typescript-eslint/no-namespace": "off",
"@typescript-eslint/no-non-null-asserted-optional-chain": "off",
"@typescript-eslint/no-redundant-type-constituents": "off",
"@typescript-eslint/no-this-alias": "off",
"@typescript-eslint/no-unnecessary-type-assertion": "off",
"@typescript-eslint/no-unnecessary-type-constraint": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-declaration-merging": "off",
"@typescript-eslint/no-unsafe-enum-comparison": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-return": "off",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/prefer-as-const": "off",
"require-await": "off",
"@typescript-eslint/require-await": "off",
"@typescript-eslint/restrict-plus-operands": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/triple-slash-reference": "off",
"@typescript-eslint/unbound-method": "off",
},
overrides: [
{
files: ["examples/**/*.ts"],
rules: {
"turbo/no-undeclared-env-vars": "off",
},
},
],
ignorePatterns: ["dist/", "lib/", "deps/"],
};
+5 -3
View File
@@ -23,7 +23,7 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: [18.x, 20.x, 22.x]
node-version: [20.x, 22.x, 23.x]
name: E2E on Node.js ${{ matrix.node-version }}
runs-on: ubuntu-latest
steps:
@@ -53,7 +53,7 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: [18.x, 20.x, 22.x]
node-version: [20.x, 22.x, 23.x]
name: Test on Node.js ${{ matrix.node-version }}
runs-on: ubuntu-latest
steps:
@@ -84,7 +84,9 @@ jobs:
- name: Build
run: pnpm run build
- name: Use Build For Examples
run: pnpm link ../packages/llamaindex/
run: |
pnpm link ../packages/llamaindex/
cd readers && pnpm link ../../packages/llamaindex/
working-directory: ./examples
- name: Run Type Check
run: pnpm run type-check
+3 -207
View File
@@ -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
+25
View File
@@ -1,5 +1,30 @@
# docs
## 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
+2
View File
@@ -1,6 +1,7 @@
// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
// eslint-disable-next-line @typescript-eslint/no-require-imports
const renderer = require("prism-react-renderer");
const lightCodeTheme = renderer.themes.github;
const darkCodeTheme = renderer.themes.dracula;
@@ -39,6 +40,7 @@ const config = {
// editUrl:
// "https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/",
remarkPlugins: [
// eslint-disable-next-line @typescript-eslint/no-require-imports
[require("@docusaurus/remark-plugin-npm2yarn"), { sync: true }],
],
},
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "docs",
"version": "0.0.103",
"version": "0.0.107",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
@@ -33,7 +33,7 @@
"@docusaurus/theme-classic": "3.5.2",
"@docusaurus/types": "3.5.2",
"@tsconfig/docusaurus": "2.0.3",
"@types/node": "^22.5.1",
"@types/node": "^22.8.4",
"docusaurus-plugin-typedoc": "1.0.5",
"typedoc": "0.26.6",
"typedoc-plugin-markdown": "4.2.6",
@@ -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: (
<>
+33
View File
@@ -1,5 +1,38 @@
# @llamaindex/doc
## 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
+24 -1
View File
@@ -1,10 +1,33 @@
import { createMDX } from "fumadocs-mdx/next";
import MonacoWebpackPlugin from "monaco-editor-webpack-plugin";
const withMDX = createMDX();
/** @type {import('next').NextConfig} */
const config = {
reactStrictMode: true,
transpilePackages: ["monaco-editor"],
webpack: (config, { isServer }) => {
if (Array.isArray(config.target) && config.target.includes("web")) {
config.target = ["web", "es2020"];
}
config.resolve.alias = {
...config.resolve.alias,
sharp$: false,
"onnxruntime-node$": false,
};
config.resolve.fallback ??= {};
config.resolve.fallback.fs = false;
if (!isServer) {
config.plugins.push(
new MonacoWebpackPlugin({
languages: ["typescript"],
filename: "static/[name].worker.js",
}),
);
}
return config;
},
};
export default withMDX(config);
+37 -16
View File
@@ -1,65 +1,86 @@
{
"name": "@llamaindex/doc",
"version": "0.0.1",
"version": "0.0.5",
"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/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.8.6",
"@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"
}
}
Binary file not shown.
BIN
View File
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
import env from "@next/env";
import { updateLlamaCloud } from "./update-llamacloud.mjs";
env.loadEnvConfig(process.cwd());
await updateLlamaCloud();
+110
View File
@@ -0,0 +1,110 @@
import { PipelinesService } 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> {
// eslint-disable-next-line turbo/no-undeclared-env-vars
const apiKey = process.env.LLAMA_CLOUD_API_KEY;
// eslint-disable-next-line turbo/no-undeclared-env-vars
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 PipelinesService.upsertBatchPipelineDocumentsApiV1PipelinesPipelineIdDocumentsPut(
{
baseUrl: "https://api.cloud.llamaindex.ai/",
body: records.map((record) => ({
id: record.id,
metadata: {
title: record.title,
description: record.description,
documentUrl: record.id,
category: record.category,
},
text: record.content,
})),
path: {
pipeline_id: index,
},
throwOnError: true,
headers: {
Authorization: `Bearer ${apiKey}`,
},
},
);
console.log("done");
}
-67
View File
@@ -1,15 +1,10 @@
import { PipelinesService } from "@llamaindex/cloud/api";
import { rehypeCodeDefaultOptions } from "fumadocs-core/mdx-plugins";
import { fileGenerator, remarkDocGen, remarkInstall } from "fumadocs-docgen";
import { defineConfig, defineDocs } from "fumadocs-mdx/config";
import { transformerTwoslash } from "fumadocs-twoslash";
import { relative } from "node:path";
import { fileURLToPath } from "node:url";
import rehypeKatex from "rehype-katex";
import remarkMath from "remark-math";
const baseDir = fileURLToPath(new URL("../src/content", import.meta.url));
export const { docs, meta } = defineDocs({
dir: "./src/content/docs",
});
@@ -49,68 +44,6 @@ export default defineConfig({
remarkMath,
[remarkInstall, { persist: { id: "package-manager" } }],
[remarkDocGen, { generators: [fileGenerator()] }],
() => {
return (_, file, next) => {
const metadata = file.data.frontmatter as Record<string, unknown>;
const title = metadata.title as string;
const description = metadata.description as string;
let content: string;
if (file.value instanceof Uint8Array) {
content = file.value.toString();
} else {
content = file.value;
}
if (file.path.includes("content/docs/cloud/api")) {
// skip cloud api docs
return next();
}
// eslint-disable-next-line turbo/no-undeclared-env-vars
if (process.env.NODE_ENV === "development") {
// skip development
return next();
}
if (!title || !description) {
throw new Error(`Missing title or description in ${file.path}`);
}
const id = relative(baseDir, file.path);
if (
// eslint-disable-next-line turbo/no-undeclared-env-vars
process.env.LLAMA_CLOUD_UPSERT_PIPELINE_DOCUMENTS === "true" &&
// eslint-disable-next-line turbo/no-undeclared-env-vars
process.env.LLAMA_CLOUD_PIPELINE_ID !== undefined
) {
PipelinesService.upsertBatchPipelineDocumentsApiV1PipelinesPipelineIdDocumentsPut(
{
baseUrl: "https://api.cloud.llamaindex.ai/",
body: [
{
metadata: {
title,
description,
documentUrl: id,
},
text: content,
id,
},
],
path: {
// eslint-disable-next-line turbo/no-undeclared-env-vars
pipeline_id: process.env.LLAMA_CLOUD_PIPELINE_ID,
},
throwOnError: true,
headers: {
// eslint-disable-next-line turbo/no-undeclared-env-vars
Authorization: `Bearer ${process.env.LLAMA_CLOUD_API_KEY}`,
},
},
).catch((error) => {
console.error(error);
});
}
return next();
};
},
],
rehypePlugins: (v) => [rehypeKatex, ...v],
},
+3 -3
View File
@@ -14,10 +14,9 @@ Settings.llm = new OpenAI({
});
const retriever = new LlamaCloudRetriever({
// eslint-disable-next-line turbo/no-undeclared-env-vars
apiKey: process.env.LLAMA_CLOUD_API_KEY!,
baseUrl: "https://api.cloud.llamaindex.ai/",
// eslint-disable-next-line turbo/no-undeclared-env-vars
pipelineId: process.env.LLAMA_CLOUD_PIPELINE_ID!,
});
@@ -27,7 +26,7 @@ const initialAIState = {
messages: ChatMessage[];
};
type UIMessage = {
export type UIMessage = {
id: number;
display: ReactNode;
};
@@ -38,6 +37,7 @@ const initialUIState = {
messages: UIMessage[];
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const runAsyncFnWithoutBlocking = (fn: (...args: any) => Promise<any>) => {
fn().catch((error) => {
console.error(error);
+1 -2
View File
@@ -11,7 +11,6 @@ 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 { SiStackblitz } from "@icons-pack/react-simple-icons";
import {
CodeBlock as FumaCodeBlock,
@@ -38,7 +37,7 @@ export default function HomePage() {
</div>
<div className="flex flex-wrap justify-center gap-4">
<Link href={DOCUMENT_URL}>
<Link href="/docs/llamaindex">
<Button variant="outline">Get Started</Button>
</Link>
<NpmInstall />
+2 -2
View File
@@ -1,4 +1,4 @@
import { DOCUMENT_URL } from "@/lib/const";
import { LEGACY_DOCUMENT_URL } from "@/lib/const";
import { redirect } from "next/navigation";
export default async function Page(props: {
@@ -7,5 +7,5 @@ export default async function Page(props: {
}>;
}) {
const path = await props.params.then(({ any }) => any.join("/"));
return redirect(new URL(path, DOCUMENT_URL).toString());
return redirect(new URL(path, LEGACY_DOCUMENT_URL).toString());
}
+14 -1
View File
@@ -1,6 +1,7 @@
import { createMetadata, metadataImage } from "@/lib/metadata";
import { openapi, source } from "@/lib/source";
import { Popup, PopupContent, PopupTrigger } from "fumadocs-twoslash/ui";
import { createTypeTable } from "fumadocs-typescript/ui";
import defaultMdxComponents from "fumadocs-ui/mdx";
import {
DocsBody,
@@ -10,6 +11,8 @@ import {
} from "fumadocs-ui/page";
import { notFound } from "next/navigation";
const { AutoTypeTable } = createTypeTable();
export default async function Page(props: {
params: Promise<{ slug?: string[] }>;
}) {
@@ -20,7 +23,16 @@ export default async function Page(props: {
const MDX = page.data.body;
return (
<DocsPage toc={page.data.toc} full={page.data.full}>
<DocsPage
toc={page.data.toc}
full={page.data.full}
editOnGithub={{
owner: "run-llama",
repo: "LlamaIndexTS",
sha: "main",
path: `apps/next/src/content/docs/${page.file.path}`,
}}
>
<DocsTitle>{page.data.title}</DocsTitle>
<DocsDescription>{page.data.description}</DocsDescription>
<DocsBody>
@@ -31,6 +43,7 @@ export default async function Page(props: {
Popup,
PopupContent,
PopupTrigger,
AutoTypeTable,
}}
/>
</DocsBody>
+40 -24
View File
@@ -1,38 +1,54 @@
import { baseOptions } from "@/app/layout.config";
import { AITrigger } from "@/components/ai-chat";
import { buttonVariants } from "@/components/ui/button";
import { LEGACY_DOCUMENT_URL } from "@/lib/const";
import { source } from "@/lib/source";
import { cn } from "@/lib/utils";
import "fumadocs-twoslash/twoslash.css";
import { Banner } from "fumadocs-ui/components/banner";
import { DocsLayout } from "fumadocs-ui/layouts/docs";
import { MessageCircle } from "lucide-react";
import type { ReactNode } from "react";
export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout
tree={source.pageTree}
{...baseOptions}
nav={{
...baseOptions.nav,
children: (
<AITrigger
className={cn(
buttonVariants({
variant: "secondary",
size: "xs",
className:
"md:flex-1 px-2 ms-2 gap-1.5 text-fd-muted-foreground rounded-full",
}),
)}
>
<MessageCircle className="size-3" />
Ask LlamaCloud
</AITrigger>
),
}}
>
{children}
</DocsLayout>
<>
<Banner variant="rainbow" id="welcome">
Welcome to the new LlamaIndex.TS documentation! 🎉 If you are looking
for the old documentation
<a
className="underline text-blue-500 ml-1"
target="_blank"
href={LEGACY_DOCUMENT_URL}
>
check it here
</a>
.
</Banner>
<DocsLayout
tree={source.pageTree}
{...baseOptions}
nav={{
...baseOptions.nav,
children: (
<AITrigger
className={cn(
buttonVariants({
variant: "secondary",
size: "xs",
className:
"md:flex-1 px-2 ms-2 gap-1.5 text-fd-muted-foreground rounded-full",
}),
)}
>
<MessageCircle className="size-3" />
Ask LlamaCloud
</AITrigger>
),
}}
>
{children}
</DocsLayout>
</>
);
}
+13 -3
View File
@@ -1,4 +1,4 @@
import { DOCUMENT_URL } from "@/lib/const";
import { Badge } from "@/components/ui/badge";
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
import Image from "next/image";
@@ -27,8 +27,18 @@ export const baseOptions: BaseLayoutProps = {
githubUrl: "https://github.com/run-llama/LlamaIndexTS",
links: [
{
text: "Documentation",
url: DOCUMENT_URL,
text: (
<div className="relative">
Docs
<Badge
variant="outline"
className="text-blue-500 absolute -top-5 -left-5 bg-fd-background hover:scale-125 transition-transform -rotate-3 hover:-rotate-12"
>
new
</Badge>
</div>
),
url: "/docs/llamaindex",
active: "nested-url",
},
],
+2 -2
View File
@@ -1,5 +1,5 @@
"use client";
import type { AIProvider } from "@/actions";
import type { AIProvider, UIMessage } from "@/actions";
import { UserMessage } from "@/components/message";
import { useActions, useUIState } from "ai/rsc";
import { Info } from "lucide-react";
@@ -21,7 +21,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip";
type AITriggerProps = ButtonHTMLAttributes<HTMLButtonElement>;
function ChatList({ messages }: { messages: any[] }) {
function ChatList({ messages }: { messages: UIMessage[] }) {
if (messages.length === 0) {
return null;
}
@@ -0,0 +1,182 @@
"use client";
import { createContextState } from "foxact/context-state";
import { useIsClient } from "foxact/use-is-client";
import { useShiki } from "fumadocs-core/utils/use-shiki";
import { CodeBlock, Pre } from "fumadocs-ui/components/codeblock";
import { lazy, Suspense, use, useMemo } from "react";
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
import Parser from "web-tree-sitter";
import { Label } from "@/components/ui/label";
import { Skeleton } from "@/components/ui/skeleton";
import { Slider } from "@/components/ui/slider";
import { CodeSplitter } from "@llamaindex/node-parser/code";
let promise: Promise<CodeSplitter>;
if (typeof window !== "undefined") {
promise = Parser.init({
locateFile(scriptName: string) {
return "/" + scriptName;
},
}).then(async () => {
const parser = new Parser();
const Lang = await Parser.Language.load("/tree-sitter-typescript.wasm");
parser.setLanguage(Lang);
return new CodeSplitter({
getParser: () => parser,
maxChars: 100,
});
});
}
const [SliderProvider, useSlider, useSetSlider] = createContextState(100);
const [CodeProvider, useCode, useSetCode] =
createContextState(`interface Person {
name: string;
age: number;
}
function greet(person: Person): string {
return \`Hello, \${person.name}! You are \${person.age} years old.\`;
}
const john: Person = {
name: "John Doe",
age: 30
};
console.log(greet(john));`);
const Editor = lazy(() => import("react-monaco-editor"));
export const IDE = () => {
const codeSplitter = use(promise);
const code = useCode();
const setCode = useSetCode();
const maxChars = useSlider();
const useSetMaxChars = useSetSlider();
return (
<div className="flex flex-col p-4 border-r max-h-96 overflow-scroll">
<div>
<Label>Max Chars {maxChars}</Label>
<Slider
className="my-4"
min={10}
max={300}
step={10}
value={[maxChars]}
onValueChange={(value) => {
useSetMaxChars(value[0]);
codeSplitter.maxChars = value[0];
}}
/>
</div>
<Editor
editorWillMount={() => {}}
editorDidMount={() => {
window.MonacoEnvironment!.getWorkerUrl = (
_moduleId: string,
label: string,
) => {
if (label === "json") return "/_next/static/json.worker.js";
if (label === "css") return "/_next/static/css.worker.js";
if (label === "html") return "/_next/static/html.worker.js";
if (label === "typescript" || label === "javascript")
return "/_next/static/ts.worker.js";
return "/_next/static/editor.worker.js";
};
}}
editorWillUnmount={() => {}}
options={{
minimap: {
enabled: false,
},
}}
theme="vs-dark"
height="100%"
width="100%"
language="typescript"
onChange={setCode}
value={code}
/>
</div>
);
};
const Preview = ({ text }: { text: string }) => {
const rendered = useShiki(text, {
lang: "ts",
components: {
pre: (props) => {
return <Pre {...props}>{props.children}</Pre>;
},
},
});
return <CodeBlock className="py-0 m-2">{rendered}</CodeBlock>;
};
function ScrollToBottom() {
const { isAtBottom, scrollToBottom } = useStickToBottomContext();
return (
!isAtBottom && (
<button
className="absolute i-ph-arrow-circle-down-fill text-4xl rounded-lg left-[50%] translate-x-[-50%] bottom-0"
onClick={() => scrollToBottom()}
/>
)
);
}
export const NodePreview = () => {
const parser = use(promise);
const code = useCode();
const maxChars = useSlider();
const textChunks = useMemo(() => parser.splitText(code), [code, maxChars]);
return (
<StickToBottom
className="block relative max-h-96 overflow-scroll"
resize="smooth"
initial="smooth"
>
<StickToBottom.Content>
{textChunks.map((chunk, i) => (
<Preview key={i} text={chunk} />
))}
</StickToBottom.Content>
<ScrollToBottom />
</StickToBottom>
);
};
export const CodeNodeParserDemo = () => {
const isClient = useIsClient();
if (!isClient) {
return (
<div className="my-2 grid grid-cols-1 md:grid-cols-2 gap-2 border rounded-xl w-full max-h-96">
<Skeleton className="h-96" />
<Skeleton className="h-96" />
</div>
);
}
return (
<SliderProvider>
<CodeProvider>
<Suspense
fallback={
<div className="my-2 grid grid-cols-1 md:grid-cols-2 gap-2 border rounded-xl w-full max-h-96">
<Skeleton className="h-96" />
<Skeleton className="h-96" />
</div>
}
>
<div className="my-2 grid grid-cols-1 md:grid-cols-2 gap-2 border rounded-xl w-full max-h-96">
<IDE />
<NodePreview />
</div>
</Suspense>
</CodeProvider>
</SliderProvider>
);
};
@@ -0,0 +1,152 @@
"use client";
import FlowInput from "@/components/flow-input";
import { Button } from "@/components/ui/button";
import {
StartEvent,
StopEvent,
Workflow,
WorkflowEvent,
} from "@llamaindex/workflow";
import { ReactNode, startTransition, useState } from "react";
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
};
const workflow = new Workflow<ContextData, number, number>();
const max = 1000;
const min = 100;
workflow.addStep(
{
inputs: [StartEvent<number>],
outputs: [StopEvent<number>],
},
async (context, event) => {
const total = event.data;
for (let i = 0; i < total; i++) {
context.sendEvent(new ComputeEvent(i));
}
console.log("waiting");
const computeResults = await Promise.all(
Array.from({ length: total }).map(() =>
context.requireEvent(ComputeResultEvent),
),
);
context.data.sum = computeResults.reduce(
(acc, result) => acc + result.data,
0,
);
console.log("stop");
return new StopEvent(context.data.sum);
},
);
workflow.addStep(
{
inputs: [ComputeEvent],
outputs: [ComputeResultEvent],
},
async (context, event) => {
await new Promise((resolve) =>
setTimeout(resolve, Math.floor(Math.random() * (max - min + 1) + min)),
);
return new ComputeResultEvent(event.data);
},
);
function ScrollToBottom() {
const { isAtBottom, scrollToBottom } = useStickToBottomContext();
return (
!isAtBottom && (
<button
className="absolute i-ph-arrow-circle-down-fill text-4xl rounded-lg left-[50%] translate-x-[-50%] bottom-0"
onClick={() => scrollToBottom()}
/>
)
);
}
export function WorkflowStreamingDemo() {
const [ui, setUI] = useState<ReactNode[]>([
<div key={0} className="bg-gray-100 dark:bg-gray-800">
Waiting for workflow to start
</div>,
]);
const [total, setTotal] = useState<number>(10);
return (
<div className="flex flex-col items-start w-full gap-2">
<div className="flex flex-row justify-center items-center">
<div className="text-lg mr-2">Compute total</div>{" "}
<FlowInput value={total} onChange={(value) => setTotal(value)} />
</div>
<Button
onClick={async () => {
startTransition(() => {
setUI([]);
});
const context = workflow.run(total, {
sum: 0,
});
let i = 0;
for await (const event of context) {
console.log(event);
if (event instanceof ComputeEvent) {
setUI((ui) => [
...ui,
<div key={i++} className="bg-yellow-100 dark:bg-yellow-800">
Computing task id: {event.data}
</div>,
]);
} else if (event instanceof ComputeResultEvent) {
setUI((ui) => [
...ui,
<div key={i++} className="bg-green-100 dark:bg-green-800">
Computed task id: {event.data}
</div>,
]);
} else if (event instanceof StartEvent) {
setUI((ui) => [
...ui,
<div key={i++} className="bg-blue-100 dark:bg-blue-800">
Started workflow with total {event.data}
</div>,
]);
} else if (event instanceof StopEvent) {
setUI((ui) => [
...ui,
<div key={i++} className="bg-red-100 dark:bg-red-800">
Workflow stopped
</div>,
]);
}
}
}}
>
Start Workflow
</Button>
<StickToBottom className="w-full flex flex-col gap-2 p-2 border border-gray-200 rounded-lg max-h-96 overflow-y-auto">
<StickToBottom.Content className="flex flex-col gap-2">
{ui}
</StickToBottom.Content>
<ScrollToBottom />
</StickToBottom>
</div>
);
}
+98
View File
@@ -0,0 +1,98 @@
import NumberFlow from "@number-flow/react";
import clsx from "clsx/lite";
import { Minus, Plus } from "lucide-react";
import * as React from "react";
type Props = {
value?: number;
min?: number;
max?: number;
onChange?: (value: number) => void;
};
export default function FlowInput({
value = 0,
min = -Infinity,
max = Infinity,
onChange,
}: Props) {
const defaultValue = React.useRef(value);
const inputRef = React.useRef<HTMLInputElement>(null);
const [animated, setAnimated] = React.useState(true);
const [showCaret, setShowCaret] = React.useState(true);
const handleInput: React.ChangeEventHandler<HTMLInputElement> = ({
currentTarget: el,
}) => {
setAnimated(false);
let next = value;
if (el.value === "") {
next = defaultValue.current;
} else {
const num = parseInt(el.value);
if (!isNaN(num) && min <= num && num <= max) next = num;
}
el.value = String(next);
onChange?.(next);
};
const handlePointerDown =
(diff: number) => (event: React.PointerEvent<HTMLButtonElement>) => {
setAnimated(true);
if (event.pointerType === "mouse") {
event?.preventDefault();
inputRef.current?.focus();
}
const newVal = Math.min(Math.max(value + diff, min), max);
onChange?.(newVal);
};
return (
<div className="group flex items-stretch rounded-md text-lg font-semibold ring ring-zinc-200 transition-[box-shadow] focus-within:ring-2 focus-within:ring-blue-500 dark:ring-zinc-800">
<button
aria-hidden
tabIndex={-1}
className="flex items-center pl-[.5em] pr-[.325em]"
disabled={min != null && value <= min}
onPointerDown={handlePointerDown(-1)}
>
<Minus className="size-4" absoluteStrokeWidth strokeWidth={3.5} />
</button>
<div className="relative grid items-center justify-items-center text-center [grid-template-areas:'overlap'] *:[grid-area:overlap]">
<input
ref={inputRef}
className={clsx(
showCaret ? "caret-primary" : "caret-transparent",
"spin-hide w-[1.5em] bg-transparent py-2 text-center font-[inherit] text-transparent outline-none",
"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
)}
// Make sure to disable kerning, to match NumberFlow:
style={{ fontKerning: "none" }}
type="number"
min={min}
step={1}
autoComplete="off"
inputMode="numeric"
max={max}
value={value}
onInput={handleInput}
/>
<NumberFlow
value={value}
format={{ useGrouping: false }}
aria-hidden
animated={animated}
onAnimationsStart={() => setShowCaret(false)}
onAnimationsFinish={() => setShowCaret(true)}
className="pointer-events-none"
willChange
/>
</div>
<button
aria-hidden
tabIndex={-1}
className="flex items-center pl-[.325em] pr-[.5em]"
disabled={max != null && value >= max}
onPointerDown={handlePointerDown(1)}
>
<Plus className="size-4" absoluteStrokeWidth strokeWidth={3.5} />
</button>
</div>
);
}
+36
View File
@@ -0,0 +1,36 @@
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { cn } from "@/lib/utils";
const badgeVariants = cva(
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
},
);
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
);
}
export { Badge, badgeVariants };
+1 -2
View File
@@ -2,8 +2,7 @@ import * as React from "react";
import { cn } from "@/lib/utils";
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
+26
View File
@@ -0,0 +1,26 @@
"use client";
import * as LabelPrimitive from "@radix-ui/react-label";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { cn } from "@/lib/utils";
const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
);
const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
<LabelPrimitive.Root
ref={ref}
className={cn(labelVariants(), className)}
{...props}
/>
));
Label.displayName = LabelPrimitive.Root.displayName;
export { Label };
+28
View File
@@ -0,0 +1,28 @@
"use client";
import * as SliderPrimitive from "@radix-ui/react-slider";
import * as React from "react";
import { cn } from "@/lib/utils";
const Slider = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
>(({ className, ...props }, ref) => (
<SliderPrimitive.Root
ref={ref}
className={cn(
"relative flex w-full touch-none select-none items-center",
className,
)}
{...props}
>
<SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
<SliderPrimitive.Range className="absolute h-full bg-primary" />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb className="block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" />
</SliderPrimitive.Root>
));
Slider.displayName = SliderPrimitive.Root.displayName;
export { Slider };
+1 -2
View File
@@ -2,8 +2,7 @@ import * as React from "react";
import { cn } from "@/lib/utils";
export interface TextareaProps
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, ...props }, ref) => {
@@ -12,7 +12,9 @@ export interface TextProps {
weight?: 400 | 500 | 600;
children?: ReactNode;
className?: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
as?: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
maximumWidth?: any;
}
@@ -0,0 +1,5 @@
{
"title": "Guide",
"description": "See our guide",
"pages": ["workflow"]
}
@@ -0,0 +1,226 @@
---
title: Inputs / Outputs
description: Learn how to use different inputs and outputs in your workflows.
---
Inputs and outputs are the way to communicate between steps in a workflow. In the previous example,
we used `StartEvent` and `StopEvent` to communicate between steps. However, you can use any type of event to communicate between steps.
## Multiple inputs
You can define multiple inputs for a step.
In the following example, we define a complex workflow with multiple inputs and outputs.
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
class AEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
class BEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ResultEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
```
First, let's define the events that we will use in the workflow.
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
class AEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
class BEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ResultEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
const workflow = new Workflow<never, string, string>();
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (
context,
startEvent
) => {
const input = startEvent.data;
const aEvent = await context.requireEvent(AEvent);
const bEvent = await context.requireEvent(BEvent);
const a = aEvent.data;
const b = bEvent.data;
return new StopEvent(`Hello, ${input}! A: ${a}, B: ${b}`);
});
// ---cut---
workflow.addStep({
inputs: [AEvent, BEvent],
outputs: [ResultEvent]
}, async (
context,
aEvent,
bEvent
) => {
const a = aEvent.data;
const b = bEvent.data;
return new ResultEvent(`A: ${a}, B: ${b}`);
});
```
This step means that it requires two events: `AEvent` and `BEvent`. It will return a `ResultEvent` with the data `A: ${a}, B: ${b}`.
## A or B input
If we want to have a step that can accept either `AEvent` or `BEvent`, we can define the step like this:
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
class AEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
class BEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ResultEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
const workflow = new Workflow<never, string, string>();
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (
context,
startEvent
) => {
const input = startEvent.data;
const aEvent = await context.requireEvent(AEvent);
const bEvent = await context.requireEvent(BEvent);
const a = aEvent.data;
const b = bEvent.data;
return new StopEvent(`Hello, ${input}! A: ${a}, B: ${b}`);
});
// ---cut---
workflow.addStep({
inputs: [WorkflowEvent.or(AEvent, BEvent)],
outputs: [ResultEvent]
}, async (
context,
aOrBEvent
) => {
if (aOrBEvent instanceof AEvent) {
// ^?
const a = aOrBEvent.data;
// ^?
return new ResultEvent(`A: ${a}`);
} else {
const b = aOrBEvent.data;
// ^?
return new ResultEvent(`B: ${b}`);
}
});
```
This step means that it requires either `AEvent` or `BEvent`. It will return a `ResultEvent` with the data `A: ${a}` or `B: ${b}`.
You can still combine the logic with `context.requireEvent` to get the data from the event.
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
<Accordions>
<Accordion title="Under the hood">
We use JavaScript Inheritance and the prototype chain to implement the `or` logic.
The `or` method creates a new class that extends the two classes that you pass to it.
<a
target="_blank"
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain"
>
MDN - Inheritance and the prototype chain
</a>
</Accordion>
</Accordions>
## Multiple outputs
You can define multiple outputs for a step.
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
class AEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
class BEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ResultEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
const workflow = new Workflow<never, string, string>();
// ---cut---
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [AEvent, BEvent]
}, async (
context,
startEvent
) => {
const input = startEvent.data;
if (Math.random() > 0.5) {
return new AEvent(`Hello, ${input}!`);
} else {
return new BEvent(42);
}
});
```
This step will return either an `AEvent` or a `BEvent` based on a random number.
@@ -0,0 +1,208 @@
---
title: Basic Usage
description: Learn how to use the LlamaIndex workflow.
---
A `Workflow` in LlamaIndex.TS is an event-driven abstraction used to chain together several events.
Workflows are made up of steps, with each step responsible for handling certain event types and emitting new events.
Workflows are designed for any cases that benefit from event-driven programming, not only for LLM and AI tasks.
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install @llamaindex/workflow
```
```shell tab="yarn"
yarn add @llamaindex/workflow
```
```shell tab="pnpm"
pnpm add @llamaindex/workflow
```
</Tabs>
## Start from scratch
Let's start from a Hello World workflow.
```ts twoslash
import { Workflow } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
// ---cut---
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
// ^?
```
First, we define a workflow with 3 generic types: `ContextData`, `Input`, and `Output`.
In general, `ContextData` is used to store the shared data between steps, `Input` is the type of the input event, and `Output` is the type of the output event.
In you code logic, you should **share state between steps via `ContextData`**.
```ts twoslash
import { Workflow, StartEvent, StopEvent } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
// ---cut---
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (context, startEvent) => {
const input = startEvent.data;
context.data.counter++;
return new StopEvent(`Hello, ${input}!`);
});
```
In the workflow, we add a step that listens to `StartEvent<string>` and emits `StopEvent<string>`.
The step is an async function that takes two arguments: `context` and `event`.
### `context` type
<AutoTypeTable path="./src/deps/type.ts" name="HandlerContext" />
There are two more properties in `HandlerContext`:
- `sendEvent`: invoke another event in the workflow, other than `StartEvent`, `StopEvent`, or the current event. (Or there will have circular reference)
- `requireEvent`: wait for a specific event to be emitted.
You can use `sendEvent` and `requireEvent` to build complex workflows.
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
// ---cut---
class AnalysisStartEvent extends WorkflowEvent<string> {}
class AnalysisStopEvent extends WorkflowEvent<boolean> {}
workflow.addStep({
inputs: [AnalysisStartEvent],
outputs: [AnalysisStopEvent]
}, async (...args) => {
// do some analysis
return new AnalysisStopEvent(true);
})
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (context, startEvent) => {
const input = startEvent.data;
context.sendEvent(new AnalysisStartEvent('start'));
context.data.counter++;
const { data } = await context.requireEvent(AnalysisStopEvent);
return new StopEvent(`Hello, ${input}! Analysis result: ${data ? 'success' : 'fail'}`);
});
```
For example, you can compile `requireEvent` with `waitUntil` in [Vercel Functions](https://vercel.com/docs/functions/functions-api-reference#waituntil) or [Cloudflare Worker](https://developers.cloudflare.com/workers/runtime-apis/context/#waituntil)
```ts twoslash
import { waitUntil } from '@vercel/functions';
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
class AnalysisStartEvent extends WorkflowEvent<string> {}
class AnalysisStopEvent extends WorkflowEvent<boolean> {}
// ---cut---
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (context, startEvent) => {
const input = startEvent.data;
context.sendEvent(new AnalysisStartEvent('start'));
context.data.counter++;
waitUntil(context.requireEvent(AnalysisStopEvent));
// note that `waitUntil` is not a promise, it will extend the lifetime of the workflow
// you can wait for some background tasks to finish
return new StopEvent(`Hello, ${input}!`);
});
```
## Multiple runs
You can run the same workflow multiple times with different inputs.
```ts twoslash
import { Workflow, StartEvent, StopEvent } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (context, startEvent) => {
const input = startEvent.data;
context.data.counter++;
return new StopEvent(`Hello, ${input}!`);
});
// ---cut---
{
const ret = await workflow.run('Alex', contextData);
console.log(ret.data); // Hello, Alex!
}
{
const ret = await workflow.run('World', contextData);
console.log(ret.data); // Hello, World!
}
```
Context is shared between runs, so the counter will be increased.
Ideally, it should be serializable to make sure it can be recovered from HTTP requests or other storage.
### Full example
<iframe
className="w-full h-[440px]"
aria-label="Workflow example"
src="https://stackblitz.com/github/run-llama/LlamaIndexTS/tree/main/examples?file=node/workflow/basic.ts"
/>
## `Workflow` type
<AutoTypeTable path="./src/deps/type.ts" name="Workflow" />
## `WorkflowContext` type
<AutoTypeTable path="./src/deps/type.ts" name="WorkflowContext" />
@@ -0,0 +1,6 @@
{
"title": "Workflow",
"description": "See how to use @llamaindex/workflow",
"defaultOpen": false,
"pages": ["index", "different-inputs-outputs", "streaming"]
}
@@ -0,0 +1,199 @@
---
title: Streaming
description: Learn how to use the LlamaIndex workflow with streaming.
---
import { WorkflowStreamingDemo } from '../../../../../components/demo/workflow-streaming-ui';
`Workflow` API by default is designed for streaming data. In this guide, we will show you how to use the `Workflow` API with streaming data.
Each `workflow.run` call returns `WorkflowContext`, which implements `AsyncIterable` interface. You can use it to stream data.
```ts twoslash
import { Workflow, WorkflowEvent, StartEvent, StopEvent } from '@llamaindex/workflow';
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
}
const workflow = new Workflow<ContextData, number, number>();
workflow.addStep({
inputs: [StartEvent<number>],
outputs: [StopEvent<number>]
}, async (context, startEvent) => {
const total = startEvent.data;
for (let i = 0; i < total; i++) {
context.sendEvent(new ComputeEvent(i));
}
const computeResults = await Promise.all(Array.from({ length: total }).map(() => context.requireEvent(ComputeResultEvent)));
// Workflow API allows you to start events in parallel and wait for all of them to finish
context.data.sum = computeResults.reduce((acc, curr) => acc + curr.data, 0);
return new StopEvent(context.data.sum);
});
```
We define a parallel computation workflow that computes the sum of numbers from 0 to `total`.
The workflow sends `ComputeEvent` events for each number and waits for `ComputeResultEvent` events. After receiving all `ComputeResultEvent` events, the workflow returns the sum as a `StopEvent`.
What if we want cutoff if the sum exceeds a certain value?
## Streaming
```ts twoslash
import { Workflow, WorkflowEvent, StartEvent, StopEvent } from '@llamaindex/workflow';
import { StopCircle } from 'lucide-react';
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
}
const workflow = new Workflow<ContextData, number, number>();
// ---cut---
const context = workflow.run(1000, {
sum: 0
});
for await (const event of context) {
if (event instanceof ComputeEvent) {
if (context.data.sum > 100) {
throw new Error('Sum exceeds 100');
}
}
if (event instanceof StopEvent) {
console.log('result', event.data);
}
}
```
You can define more custom logic using `AsyncIterable` interface.
For example. I just want to stop the workflow if I get a `ComputeResultEvent`
```ts twoslash
import { Workflow, WorkflowEvent, StartEvent, StopEvent } from '@llamaindex/workflow';
import { StopCircle } from 'lucide-react';
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
}
const workflow = new Workflow<ContextData, number, number>();
// ---cut---
async function compute() {
const context = workflow.run(1000, {
sum: 0
});
for await (const event of context) {
if (event instanceof ComputeResultEvent) {
return event.data;
}
}
throw new Error('UNREACHABLE');
}
const result = await compute();
```
### Streaming with UI
You can use the `Workflow` API with UI libraries like React.
```tsx twoslash
// @filename: utils.ts
export async function runWithoutBlocking(fn: () => Promise<void>) {
fn();
}
// @filename: action.ts
// ---cut---
'use server';
// "use server" is required to enable server side feature in React
import { createStreamableUI } from 'ai/rsc';
import { runWithoutBlocking } from './utils';
// ---cut-start---
import { Workflow, WorkflowEvent, StartEvent, StopEvent } from '@llamaindex/workflow';
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
}
const workflow = new Workflow<ContextData, number, number>();
const min = 100;
const max = 1000;
workflow.addStep(
{
inputs: [ComputeEvent],
outputs: [ComputeResultEvent]
},
async (context, event) => {
await new Promise((resolve) =>
setTimeout(resolve, Math.floor(Math.random() * (max - min + 1) + min))
);
return new ComputeResultEvent(event.data);
}
);
// ---cut-end---
export async function compute() {
'use server';
const ui = createStreamableUI();
const context = workflow.run(100, {
sum: 0
});
runWithoutBlocking(async () => {
for await (const event of context) {
if (event instanceof ComputeResultEvent) {
// Update UI
} else if (event instanceof StopEvent) {
// Update UI
}
// ...
}
});
return ui.value;
}
```
<WorkflowStreamingDemo />
+20 -31
View File
@@ -5,42 +5,31 @@ description: Install llamaindex by running a single command.
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install-llamaindex" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex
```
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex
```
```shell tab="yarn"
yarn add llamaindex
```
```shell tab="pnpm"
pnpm add llamaindex
```
```shell tab="yarn"
yarn add llamaindex
```
```shell tab="pnpm"
pnpm add llamaindex
```
</Tabs>
## What's next?
<Cards>
<Card
title="I'm new to RAG"
description="Learn more about RAG (Retrieval-augmented generation) using LlamaIndex.TS."
href="/docs/llamaindex/setup/what-is-rag"
/>
<Card
title="I want to try LlamaIndex.TS"
description="Learn how to use LlamaIndex.TS with different JS runtime and frameworks."
href="/docs/llamaindex/setup"
/>
<Card
title="I want to improve performance when using LlamaIndex.TS"
description="Learn how to improve performance, reduce bundle size, improve accuracy."
href="/docs/llamaindex/performance"
/>
<Card
title="Show me code examples"
description="Explore code examples using LlamaIndex.TS."
href="https://stackblitz.com/github/run-llama/LlamaIndexTS/tree/main/examples?file=README.md"
/>
<Card
title="I want to try LlamaIndex.TS"
description="Learn how to use LlamaIndex.TS with different JS runtime and frameworks."
href="/docs/llamaindex/setup/getting-started"
/>
<Card
title="Show me code examples"
description="Explore code examples using LlamaIndex.TS."
href="https://stackblitz.com/github/run-llama/LlamaIndexTS/tree/main/examples?file=README.md"
/>
</Cards>
@@ -0,0 +1,39 @@
---
title: Langtrace
description: Learn how to integrate LlamaIndex.TS with Langtrace.
---
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
Enhance your observability with Langtrace, a robust open-source tool supports OpenTelemetry and is designed to trace, evaluate, and manage LLM applications seamlessly. Langtrace integrates directly with LlamaIndex, offering detailed, real-time insights into performance metrics such as accuracy, evaluations, and latency.
## Install
- Self-host or sign-up and generate an API key using [Langtrace](https://www.langtrace.ai) Cloud
<Tabs groupId="install-langtrase" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install @langtrase/typescript-sdk
```
```shell tab="yarn"
yarn add @langtrase/typescript-sdk
```
```shell tab="pnpm"
pnpm add @langtrase/typescript-sdk
```
</Tabs>
## Initialize
```js
import * as Langtrace from "@langtrase/typescript-sdk";
Langtrace.init({ api_key: "<YOUR_API_KEY>" });
```
Features:
- OpenTelemetry compliant, ensuring broad compatibility with observability platforms.
- Provides comprehensive logs and detailed traces of all components.
- Real-time monitoring of accuracy, evaluations, usage, costs, and latency.
- For more configuration options and details, visit [Langtrace Docs](https://docs.langtrace.ai/introduction).
@@ -0,0 +1,5 @@
{
"title": "Integration",
"description": "See our integrations",
"pages": ["open-llm-metry", "lang-trace"]
}
@@ -0,0 +1,34 @@
---
title: OpenLLMetry
description: Learn how to integrate LlamaIndex.TS with OpenLLMetry.
---
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
[OpenLLMetry](https://github.com/traceloop/openllmetry-js) is an open-source project based on OpenTelemetry for tracing and monitoring
LLM applications. It connects to [all major observability platforms](https://www.traceloop.com/docs/openllmetry/integrations/introduction) and installs in minutes.
### Usage Pattern
<Tabs groupId="install-traceloop" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install @traceloop/node-server-sdk
```
```shell tab="yarn"
yarn add @traceloop/node-server-sdk
```
```shell tab="pnpm"
pnpm add @traceloop/node-server-sdk
```
</Tabs>
```js
import * as traceloop from "@traceloop/node-server-sdk";
traceloop.initialize({
apiKey: process.env.TRACELOOP_API_KEY,
disableBatch: true
});
```
@@ -0,0 +1,5 @@
{
"title": "Loading Data",
"description": "Loading Data using LlamaIndex.TS",
"pages": ["index", "node-parser"]
}
@@ -0,0 +1,158 @@
---
title: Node Parsers / Text Splitters
description: Learn how to use Node Parsers and Text Splitters to extract data from documents.
---
import { CodeNodeParserDemo } from '../../../../components/demo/code-node-parser';
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
Node parsers are a simple abstraction that take a list of documents, and chunk them into `Node` objects, such that each node is a specific chunk of the parent document. When a document is broken into nodes, all of it's attributes are inherited to the children nodes (i.e. `metadata`, text and metadata templates, etc.). You can read more about `Node` and `Document` properties [here](./).
## NodeParser
The `NodeParser` in LlamaIndex is responsible for splitting `Document` objects into more manageable `Node` objects.
By default, we will use `Settings.nodeParser` to split the document into nodes. You can also assign a custom `NodeParser` to the `Settings` object.
```ts twoslash
import { TextFileReader } from '@llamaindex/readers/text'
import { SentenceSplitter } from '@llamaindex/core/node-parser';
import { Settings } from 'llamaindex';
const nodeParser = new SentenceSplitter();
Settings.nodeParser = nodeParser;
// ^?
```
## TextSplitter
The underlying text splitter will split text by sentences. It can also be used as a standalone module for splitting raw text.
```ts twoslash
import { SentenceSplitter } from "@llamaindex/core/node-parser";
const splitter = new SentenceSplitter({ chunkSize: 1 });
const texts = splitter.splitText("Hello World");
// ^?
```
## MarkdownNodeParser
The `MarkdownNodeParser` is a more advanced `NodeParser` that can handle markdown documents. It will split the markdown into nodes and then parse the nodes into a `Document` object.
<Tabs items={["with reader", "with node:fs"]}>
```ts twoslash tab="with reader"
import { MarkdownNodeParser } from "@llamaindex/core/node-parser";
import { MarkdownReader } from '@llamaindex/readers/markdown'
const reader = new MarkdownReader();
const markdownNodeParser = new MarkdownNodeParser();
const documents = await reader.loadData('path/to/file.md');
const parsedDocuments = markdownNodeParser(documents);
// ^?
```
```ts twoslash tab="with node:fs"
import fs from 'node:fs/promises';
import { MarkdownNodeParser } from "@llamaindex/core/node-parser";
import { Document } from '@llamaindex/core/schema';
const markdownNodeParser = new MarkdownNodeParser();
const text = await fs.readFile('path/to/file.md', 'utf-8');
const document = new Document({ text });
const parsedDocuments = markdownNodeParser([document]);
// ^?
```
</Tabs>
## CodeSplitter
The `CodeSplitter` is a more advanced `NodeParser` that can handle code documents.
It will split the code by AST nodes and then parse the nodes into a `Document` object.
<Tabs items={["with reader", "with node:fs"]}>
```ts twoslash tab="with reader"
import { TextFileReader } from '@llamaindex/readers/text'
import { CodeSplitter } from '@llamaindex/node-parser/code'
import Parser from "tree-sitter";
import TS from "tree-sitter-typescript";
const parser = new Parser();
parser.setLanguage(TS.typescript);
const codeSplitter = new CodeSplitter({
getParser: () => parser,
});
const reader = new TextFileReader();
const documents = await reader.loadData('path/to/file.ts');
const parsedDocuments = codeSplitter(documents);
// ^?
```
```ts twoslash tab="with node:fs"
import fs from 'node:fs/promises';
import { CodeSplitter } from '@llamaindex/node-parser/code'
import Parser from "tree-sitter";
import TS from "tree-sitter-typescript";
const parser = new Parser();
parser.setLanguage(TS.typescript);
const codeSplitter = new CodeSplitter({
getParser: () => parser,
});
const parsedDocuments = codeSplitter.splitText(await fs.readFile('path/to/file.ts', 'utf-8'));
// ^?
```
</Tabs>
Try it out ⬇️
<CodeNodeParserDemo/>
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
<Accordions>
<Accordion title="Use it in browser">
You might setup WASM files for `web-tree-sitter` and use it in the browser.
```ts
import Parser from 'web-tree-sitter';
Parser.init({
locateFile(scriptName: string) {
return '/' + scriptName
},
}).then(async () => {
const parser = new Parser();
const Lang = await Parser.Language.load('/tree-sitter-typescript.wasm');
parser.setLanguage(Lang);
return new CodeSplitter({
getParser: () => parser,
maxChars: 100
});
});
```
In this example, you should put `tree-sitter-typescript.wasm` to the `public` folder for Next.js.
And also update the `next.config.js` to make `@llamaindex/env` work properly.
```js
const config = {
webpack: (config) => {
if (Array.isArray(config.target) && config.target.includes('web')) {
config.target = ["web", "es2020"];
}
return config;
}
}
export default config;
```
</Accordion>
</Accordions>
@@ -8,6 +8,8 @@
"index",
"setup",
"starter",
"readers"
"loading",
"guide",
"integration"
]
}
@@ -1,5 +0,0 @@
{
"title": "Loading",
"description": "File Readers Collection",
"pages": ["index"]
}
@@ -20,7 +20,7 @@ import {
<>
<SiTypescript className="inline" color="#3178C6" /> TypeScript
</>
} href="/docs/llamaindex/setup/typescript.mdx" />
} href="/docs/llamaindex/setup/typescript" />
<Card title={
<>
<SiVite className='inline' color='#646CFF' /> Vite
@@ -29,7 +29,7 @@ import {
<Card
title={
<>
<SiNextdotjs className='inline' color='#000000' /> Next.js (React Server Component)
<SiNextdotjs className='inline' /> Next.js (React Server Component)
</>
}
href="/docs/llamaindex/setup/next"
+5
View File
@@ -0,0 +1,5 @@
export type {
HandlerContext,
Workflow,
WorkflowContext,
} from "@llamaindex/workflow";
+1 -1
View File
@@ -1,2 +1,2 @@
// when we are ready, change to /docs/llamaindex
export const DOCUMENT_URL = 'https://legacy.ts.llamaindex.ai/'
export const LEGACY_DOCUMENT_URL = 'https://legacy.ts.llamaindex.ai/'
+1
View File
@@ -12,6 +12,7 @@ export default {
"./node_modules/fumadocs-openapi/dist/**/*.js",
],
presets: [createPreset()],
// eslint-disable-next-line @typescript-eslint/no-require-imports
plugins: [require("tailwindcss-animate")],
theme: {
extend: {
+7 -1
View File
@@ -24,6 +24,12 @@
}
]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
"**/*.mts"
],
"exclude": ["node_modules"]
}
+135
View File
@@ -0,0 +1,135 @@
// Type definitions for Next.js cacheLife configs
declare module "next/cache" {
export { cacheTag as unstable_cacheTag } from "next/dist/server/use-cache/cache-tag";
export {
revalidatePath,
revalidateTag,
} from "next/dist/server/web/spec-extension/revalidate";
export { unstable_cache } from "next/dist/server/web/spec-extension/unstable-cache";
export { unstable_noStore } from "next/dist/server/web/spec-extension/unstable-no-store";
/**
* Cache this `"use cache"` for a timespan defined by the `"default"` profile.
* ```
* stale: 300 seconds (5 minutes)
* revalidate: 900 seconds (15 minutes)
* expire: never
* ```
*
* This cache may be stale on clients for 5 minutes before checking with the server.
* If the server receives a new request after 15 minutes, start revalidating new values in the background.
* It lives for the maximum age of the server cache. If this entry has no traffic for a while, it may serve an old value the next request.
*/
export function unstable_cacheLife(profile: "default"): void;
/**
* Cache this `"use cache"` for a timespan defined by the `"seconds"` profile.
* ```
* stale: 0 seconds
* revalidate: 1 seconds
* expire: 1 seconds
* ```
*
* This cache may be stale on clients for 0 seconds before checking with the server.
* This cache will expire after 1 seconds. The next request will recompute it.
*/
export function unstable_cacheLife(profile: "seconds"): void;
/**
* Cache this `"use cache"` for a timespan defined by the `"minutes"` profile.
* ```
* stale: 300 seconds (5 minutes)
* revalidate: 60 seconds (1 minute)
* expire: 3600 seconds (1 hour)
* ```
*
* This cache may be stale on clients for 5 minutes before checking with the server.
* If the server receives a new request after 1 minute, start revalidating new values in the background.
* If this entry has no traffic for 1 hour it will expire. The next request will recompute it.
*/
export function unstable_cacheLife(profile: "minutes"): void;
/**
* Cache this `"use cache"` for a timespan defined by the `"hours"` profile.
* ```
* stale: 300 seconds (5 minutes)
* revalidate: 3600 seconds (1 hour)
* expire: 86400 seconds (1 day)
* ```
*
* This cache may be stale on clients for 5 minutes before checking with the server.
* If the server receives a new request after 1 hour, start revalidating new values in the background.
* If this entry has no traffic for 1 day it will expire. The next request will recompute it.
*/
export function unstable_cacheLife(profile: "hours"): void;
/**
* Cache this `"use cache"` for a timespan defined by the `"days"` profile.
* ```
* stale: 300 seconds (5 minutes)
* revalidate: 86400 seconds (1 day)
* expire: 604800 seconds (1 week)
* ```
*
* This cache may be stale on clients for 5 minutes before checking with the server.
* If the server receives a new request after 1 day, start revalidating new values in the background.
* If this entry has no traffic for 1 week it will expire. The next request will recompute it.
*/
export function unstable_cacheLife(profile: "days"): void;
/**
* Cache this `"use cache"` for a timespan defined by the `"weeks"` profile.
* ```
* stale: 300 seconds (5 minutes)
* revalidate: 604800 seconds (1 week)
* expire: 2592000 seconds (30 days)
* ```
*
* This cache may be stale on clients for 5 minutes before checking with the server.
* If the server receives a new request after 1 week, start revalidating new values in the background.
* If this entry has no traffic for 30 days it will expire. The next request will recompute it.
*/
export function unstable_cacheLife(profile: "weeks"): void;
/**
* Cache this `"use cache"` for a timespan defined by the `"max"` profile.
* ```
* stale: 300 seconds (5 minutes)
* revalidate: 2592000 seconds (30 days)
* expire: never
* ```
*
* This cache may be stale on clients for 5 minutes before checking with the server.
* If the server receives a new request after 30 days, start revalidating new values in the background.
* It lives for the maximum age of the server cache. If this entry has no traffic for a while, it may serve an old value the next request.
*/
export function unstable_cacheLife(profile: "max"): void;
/**
* Cache this `"use cache"` using a custom timespan.
* ```
* stale: ... // seconds
* revalidate: ... // seconds
* expire: ... // seconds
* ```
*
* This is similar to Cache-Control: max-age=`stale`,s-max-age=`revalidate`,stale-while-revalidate=`expire-revalidate`
*
* If a value is left out, the lowest of other cacheLife() calls or the default, is used instead.
*/
export function unstable_cacheLife(profile: {
/**
* This cache may be stale on clients for ... seconds before checking with the server.
*/
stale?: number;
/**
* If the server receives a new request after ... seconds, start revalidating new values in the background.
*/
revalidate?: number;
/**
* If this entry has no traffic for ... seconds it will expire. The next request will recompute it.
*/
expire?: number;
}): void;
}
+3
View File
@@ -0,0 +1,3 @@
{
"type": "module"
}
-7
View File
@@ -1,7 +0,0 @@
<svg fill="none" height="50" viewBox="0 0 512 512" width="50" xmlns="http://www.w3.org/2000/svg">
<rect fill="#3178c6" height="512" rx="50" width="512" />
<rect fill="#3178c6" height="512" rx="50" width="512" />
<path clip-rule="evenodd"
d="m316.939 407.424v50.061c8.138 4.172 17.763 7.3 28.875 9.386s22.823 3.129 35.135 3.129c11.999 0 23.397-1.147 34.196-3.442 10.799-2.294 20.268-6.075 28.406-11.342 8.138-5.266 14.581-12.15 19.328-20.65s7.121-19.007 7.121-31.522c0-9.074-1.356-17.026-4.069-23.857s-6.625-12.906-11.738-18.225c-5.112-5.319-11.242-10.091-18.389-14.315s-15.207-8.213-24.18-11.967c-6.573-2.712-12.468-5.345-17.685-7.9-5.217-2.556-9.651-5.163-13.303-7.822-3.652-2.66-6.469-5.476-8.451-8.448-1.982-2.973-2.974-6.336-2.974-10.091 0-3.441.887-6.544 2.661-9.308s4.278-5.136 7.512-7.118c3.235-1.981 7.199-3.52 11.894-4.615 4.696-1.095 9.912-1.642 15.651-1.642 4.173 0 8.581.313 13.224.938 4.643.626 9.312 1.591 14.008 2.894 4.695 1.304 9.259 2.947 13.694 4.928 4.434 1.982 8.529 4.276 12.285 6.884v-46.776c-7.616-2.92-15.937-5.084-24.962-6.492s-19.381-2.112-31.066-2.112c-11.895 0-23.163 1.278-33.805 3.833s-20.006 6.544-28.093 11.967c-8.086 5.424-14.476 12.333-19.171 20.729-4.695 8.395-7.043 18.433-7.043 30.114 0 14.914 4.304 27.638 12.912 38.172 8.607 10.533 21.675 19.45 39.204 26.751 6.886 2.816 13.303 5.579 19.25 8.291s11.086 5.528 15.415 8.448c4.33 2.92 7.747 6.101 10.252 9.543 2.504 3.441 3.756 7.352 3.756 11.733 0 3.233-.783 6.231-2.348 8.995s-3.939 5.162-7.121 7.196-7.147 3.624-11.894 4.771c-4.748 1.148-10.303 1.721-16.668 1.721-10.851 0-21.597-1.903-32.24-5.71-10.642-3.806-20.502-9.516-29.579-17.13zm-84.159-123.342h64.22v-41.082h-179v41.082h63.906v182.918h50.874z"
fill="#fff" fill-rule="evenodd" />
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

+62
View File
@@ -0,0 +1,62 @@
// @ts-check
import eslint from "@eslint/js";
import eslintConfigPrettier from "eslint-config-prettier";
import turboPlugin from "eslint-plugin-turbo";
import globals from "globals";
import tseslint from "typescript-eslint";
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
eslintConfigPrettier,
{
languageOptions: {
ecmaVersion: 2022,
sourceType: "module",
globals: {
...globals.browser,
...globals.node,
},
},
},
{
name: "eslint-config-turbo (recreated flat)",
plugins: {
turbo: { rules: turboPlugin.rules },
},
},
{
rules: {
"no-irregular-whitespace": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-explicit-any": [
"error",
{
ignoreRestArgs: true,
},
],
},
},
{
files: ["packages/wasm-tools/**"],
rules: {
"@typescript-eslint/no-explicit-any": "off",
},
},
{
ignores: [
"**/dist/**",
"**/lib/*",
"**/deps/**",
"**/.next/**",
"**/node_modules/**",
"**/build/**",
"**/.docusaurus/**",
// third party deps
"packages/env/src/fs/memfs/index.js",
"packages/core/src/prompts/format.ts",
"packages/core/src/node-parser/sentence_tokenizer.js",
],
},
);
+7
View File
@@ -1,5 +1,12 @@
# examples
## 0.0.12
### Patch Changes
- Updated dependencies [0765742]
- @llamaindex/workflow@0.0.2
## 0.0.11
### Patch Changes
+2 -1
View File
@@ -22,13 +22,14 @@ const extractWikipediaTitle = async (title: string) => {
const url = `https://en.wikipedia.org/w/api.php?${queryParams}`;
const response = await fetch(url);
const data: any = await response.json();
const data = await response.json();
const pages = data.query.pages;
const page = pages[Object.keys(pages)[0]];
const wikiText = page.extract;
await new Promise((resolve) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fs.writeFile(path.join(dataPath, `${title}.txt`), wikiText, (err: any) => {
if (err) {
console.error(err);
+2
View File
@@ -37,7 +37,9 @@ async function main() {
});
// TODO: fix any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const documentAgents: any = {};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const queryEngines: any = {};
for (const title of wikiTitles) {
+1 -1
View File
@@ -3,7 +3,7 @@ import { SimpleDirectoryReader } from "llamaindex";
function callback(
category: string,
name: string,
status: any,
status: unknown,
message?: string,
): boolean {
console.log(category, name, status, message);
-1
View File
@@ -1,4 +1,3 @@
/* eslint-disable turbo/no-undeclared-env-vars */
import * as dotenv from "dotenv";
import * as fs from "fs";
import { MongoClient } from "mongodb";
-1
View File
@@ -1,4 +1,3 @@
/* eslint-disable turbo/no-undeclared-env-vars */
import { SimpleMongoReader } from "@llamaindex/readers/mongo";
import * as dotenv from "dotenv";
import {
-1
View File
@@ -1,4 +1,3 @@
/* eslint-disable turbo/no-undeclared-env-vars */
import * as dotenv from "dotenv";
import { MongoDBAtlasVectorSearch, VectorStoreIndex } from "llamaindex";
import { MongoClient } from "mongodb";
+1
View File
@@ -6,6 +6,7 @@ import { getStorageContext } from "./storage";
Settings.chunkSize = 512;
Settings.chunkOverlap = 20;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function getRuntime(func: any) {
const start = Date.now();
await func();
+33
View File
@@ -0,0 +1,33 @@
import { StartEvent, StopEvent, Workflow } 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}!`);
},
);
{
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!
}
console.log(contextData.counter); // 2
+3 -2
View File
@@ -1,13 +1,14 @@
{
"name": "@llamaindex/examples",
"private": true,
"version": "0.0.11",
"version": "0.0.12",
"dependencies": {
"@aws-crypto/sha256-js": "^5.2.0",
"@azure/identity": "^4.4.1",
"@datastax/astra-db-ts": "^1.4.1",
"@llamaindex/core": "^0.4.0",
"@llamaindex/readers": "^1.0.0",
"@llamaindex/workflow": "^0.0.2",
"@notionhq/client": "^2.2.15",
"@pinecone-database/pinecone": "^3.0.2",
"@vercel/postgres": "^0.10.0",
@@ -22,7 +23,7 @@
"postgres": "^3.4.4"
},
"devDependencies": {
"@types/node": "^22.5.1",
"@types/node": "^22.8.4",
"tsx": "^4.19.0",
"typescript": "^5.6.2"
},
+2 -1
View File
@@ -16,13 +16,14 @@ async function getSourceFilenames(sourceDir: string) {
function callback(
category: string,
name: string,
status: any,
status: unknown,
message: string = "",
): boolean {
console.log(category, name, status, message);
return true;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function main(args: any) {
const sourceDir: string = args.length > 2 ? args[2] : "../data";
+2
View File
@@ -1,6 +1,7 @@
import { PineconeVectorStore, VectorStoreIndex } from "llamaindex";
async function main() {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
@@ -44,6 +45,7 @@ function isQuit(question: string) {
}
// Function to get user input as a promise
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function getUserInput(readline: any): Promise<string> {
return new Promise((resolve) => {
readline.question(
+1 -1
View File
@@ -22,7 +22,7 @@
"llamaindex": "*"
},
"devDependencies": {
"@types/node": "^22.5.1",
"@types/node": "^22.8.4",
"tsx": "^4.19.0",
"typescript": "^5.6.2"
}
+1
View File
@@ -39,6 +39,7 @@ function getTextDocs(jsonList: { text: string; page: number }[]): Document[] {
}
// Download all images from jsonObjs, send them to OpenAI API to get alt text, return an array of Document objects
async function getImageTextDocs(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
jsonObjs: Record<string, any>[],
): Promise<Document[]> {
const llm = new OpenAI({
+2 -1
View File
@@ -16,13 +16,14 @@ async function getSourceFilenames(sourceDir: string) {
function callback(
category: string,
name: string,
status: any,
status: unknown,
message: string = "",
): boolean {
console.log(category, name, status, message);
return true;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function main(args: any) {
const sourceDir: string = args.length > 2 ? args[2] : "../data";
-1
View File
@@ -1,4 +1,3 @@
/* eslint-disable turbo/no-undeclared-env-vars */
import dotenv from "dotenv";
import { Document, PGVectorStore, VectorStoreQueryMode } from "llamaindex";
import postgres from "postgres";
+2
View File
@@ -1,6 +1,7 @@
import { PGVectorStore, VectorStoreIndex } from "llamaindex";
async function main() {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
@@ -50,6 +51,7 @@ function isQuit(question: string) {
}
// Function to get user input as a promise
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function getUserInput(readline: any): Promise<string> {
return new Promise((resolve) => {
readline.question(
+1
View File
@@ -46,6 +46,7 @@ class PineconeVectorStore<T extends RecordMetadata = RecordMetadata>
async query(
query: VectorStoreQuery,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
kwargs?: any,
): Promise<VectorStoreQueryResult> {
let queryEmbedding: number[] = [];
+11 -10
View File
@@ -19,19 +19,20 @@
},
"devDependencies": {
"@changesets/cli": "^2.27.5",
"@typescript-eslint/eslint-plugin": "^8.3.0",
"eslint": "8.57.0",
"eslint-config-next": "^14.2.7",
"eslint": "9.13.0",
"eslint-config-next": "^15.0.2",
"eslint-config-prettier": "^9.1.0",
"eslint-config-turbo": "^2.1.0",
"eslint-plugin-react": "7.35.0",
"husky": "^9.1.5",
"lint-staged": "^15.2.9",
"eslint-config-turbo": "^2.2.3",
"eslint-plugin-react": "7.37.2",
"globals": "^15.11.0",
"husky": "^9.1.6",
"lint-staged": "^15.2.10",
"madge": "^8.0.0",
"prettier": "^3.3.3",
"prettier-plugin-organize-imports": "^4.0.0",
"turbo": "^2.1.2",
"typescript": "^5.6.2"
"prettier-plugin-organize-imports": "^4.1.0",
"turbo": "^2.2.3",
"typescript": "^5.6.2",
"typescript-eslint": "^8.12.2"
},
"packageManager": "pnpm@9.5.0",
"pnpm": {
+19
View File
@@ -1,5 +1,24 @@
# @llamaindex/autotool
## 5.0.3
### Patch Changes
- llamaindex@0.8.3
## 5.0.2
### Patch Changes
- Updated dependencies [c7a918c]
- llamaindex@0.8.2
## 5.0.1
### Patch Changes
- llamaindex@0.8.1
## 5.0.0
### Patch Changes
@@ -1,5 +1,27 @@
# @llamaindex/autotool-01-node-example
## 0.0.46
### Patch Changes
- llamaindex@0.8.3
- @llamaindex/autotool@5.0.3
## 0.0.45
### Patch Changes
- Updated dependencies [c7a918c]
- llamaindex@0.8.2
- @llamaindex/autotool@5.0.2
## 0.0.44
### Patch Changes
- llamaindex@0.8.1
- @llamaindex/autotool@5.0.1
## 0.0.43
### Patch Changes
@@ -13,5 +13,5 @@
"scripts": {
"start": "node --import tsx --import @llamaindex/autotool/node ./src/index.ts"
},
"version": "0.0.43"
"version": "0.0.46"
}
@@ -18,6 +18,6 @@ const openai = new OpenAI();
const toolCalls = response.choices[0]!.message.tool_calls ?? [];
for (const toolCall of toolCalls) {
toolCall.function.name;
console.log(toolCall);
}
}
@@ -1,5 +1,27 @@
# @llamaindex/autotool-02-next-example
## 0.1.90
### Patch Changes
- llamaindex@0.8.3
- @llamaindex/autotool@5.0.3
## 0.1.89
### Patch Changes
- Updated dependencies [c7a918c]
- llamaindex@0.8.2
- @llamaindex/autotool@5.0.2
## 0.1.88
### Patch Changes
- llamaindex@0.8.1
- @llamaindex/autotool@5.0.1
## 0.1.87
### Patch Changes
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/autotool-02-next-example",
"private": true,
"version": "0.1.87",
"version": "0.1.90",
"scripts": {
"dev": "next dev",
"build": "next build",
@@ -24,7 +24,7 @@
"tailwind-merge": "^2.5.2"
},
"devDependencies": {
"@types/node": "^22.5.1",
"@types/node": "^22.8.4",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@types/react-syntax-highlighter": "^15.5.11",
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/autotool",
"type": "module",
"version": "5.0.0",
"version": "5.0.3",
"description": "auto transpile your JS function to LLM Agent compatible",
"files": [
"dist",
@@ -69,7 +69,7 @@
"devDependencies": {
"@swc/types": "^0.1.12",
"@types/json-schema": "^7.0.15",
"@types/node": "^22.5.1",
"@types/node": "^22.8.4",
"bunchee": "5.5.1",
"llamaindex": "workspace:*",
"next": "14.2.11",
+2
View File
@@ -2,6 +2,7 @@ import { atom, createStore } from "jotai/vanilla";
import type { ToolMetadata } from "llamaindex";
export type Info = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
originalFunction?: (...args: any[]) => any;
/**
* In current LLM, it doesn't support non-object parameter, so we mock arguments as object, and use this mapping to convert it back.
@@ -23,4 +24,5 @@ export type InfoString = {
export const store = createStore();
export const toolMetadataAtom = atom<[ToolMetadata, Info][]>([]);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const toolsAtom = atom<Record<string, (...args: any[]) => any>>({});
+1
View File
@@ -4,6 +4,7 @@ import webpackPlugin from "./webpack";
export function withNext(config: NextConfig) {
return {
...config,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
webpack: (webpackConfig: any, context: any) => {
webpackConfig = config.webpack?.(webpackConfig, context) ?? webpackConfig;
webpackConfig.plugins.push(webpackPlugin());
+1 -1
View File
@@ -3,7 +3,7 @@ import type { ExpressionStatement } from "@swc/types";
import { createUnplugin, type UnpluginFactory } from "unplugin";
import { isJSorTS, isToolFile, transformAutoTool } from "./compiler";
export interface Options {}
export type Options = object;
const name = "llama-index-tool";
+7
View File
@@ -1,5 +1,12 @@
# @llamaindex/cloud
## 2.0.1
### Patch Changes
- Updated dependencies [9c73f0a]
- @llamaindex/core@0.4.1
## 2.0.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/cloud",
"version": "2.0.0",
"version": "2.0.1",
"type": "module",
"license": "MIT",
"scripts": {
+9 -1
View File
@@ -18,7 +18,7 @@ type WriteStream = {
};
// Do not modify this variable or cause type errors
// eslint-disable-next-line no-var
// eslint-disable-next-line @typescript-eslint/no-explicit-any, no-var
var process: any;
/**
@@ -215,6 +215,7 @@ export class LlamaParseReader extends FileReader {
private async getJobResult(
jobId: string,
resultType: "text" | "json" | "markdown",
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Promise<any> {
const signal = AbortSignal.timeout(this.maxTimeout * 1000);
let tries = 0;
@@ -354,6 +355,7 @@ export class LlamaParseReader extends FileReader {
*/
async loadJson(
filePathOrContent: string | Uint8Array,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Promise<Record<string, any>[]> {
let jobId;
const isFilePath = typeof filePathOrContent === "string";
@@ -394,8 +396,10 @@ export class LlamaParseReader extends FileReader {
* @return {Promise<Record<string, any>[]>} A Promise that resolves to an array of image objects.
*/
async getImages(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
jsonResult: Record<string, any>[],
downloadPath: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Promise<Record<string, any>[]> {
try {
// Create download directory if it doesn't exist (Actually check for write access, not existence, since fsPromises does not have a `existsSync` method)
@@ -405,6 +409,7 @@ export class LlamaParseReader extends FileReader {
await fs.mkdir(downloadPath, { recursive: true });
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const images: Record<string, any>[] = [];
for (const result of jsonResult) {
const jobId = result.job_id;
@@ -473,9 +478,12 @@ export class LlamaParseReader extends FileReader {
// Filters out invalid values (null, undefined, empty string) of specific params.
private filterSpecificParams(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
params: Record<string, any>,
keysToCheck: string[],
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Record<string, any> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const filteredParams: Record<string, any> = {};
for (const [key, value] of Object.entries(params)) {
if (keysToCheck.includes(key)) {
+7
View File
@@ -1,5 +1,12 @@
# @llamaindex/community
## 0.0.58
### Patch Changes
- Updated dependencies [9c73f0a]
- @llamaindex/core@0.4.1
## 0.0.57
### Patch Changes
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/community",
"description": "Community package for LlamaIndexTS",
"version": "0.0.57",
"version": "0.0.58",
"type": "module",
"types": "dist/type/index.d.ts",
"main": "dist/cjs/index.js",
@@ -42,7 +42,7 @@
"dev": "bunchee --watch"
},
"devDependencies": {
"@types/node": "^22.5.1",
"@types/node": "^22.8.4",
"bunchee": "5.5.1"
},
"dependencies": {
@@ -31,12 +31,14 @@ import {
export class AnthropicProvider extends Provider<AnthropicStreamEvent> {
getResultFromResponse(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
response: Record<string, any>,
): AnthropicNoneStreamingResponse {
return JSON.parse(toUtf8(response.body));
}
getToolsFromResponse<AnthropicToolContent>(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
response: Record<string, any>,
): AnthropicToolContent[] {
const result = this.getResultFromResponse(response);
@@ -45,6 +47,7 @@ export class AnthropicProvider extends Provider<AnthropicStreamEvent> {
.map((item) => item as AnthropicToolContent);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getTextFromResponse(response: Record<string, any>): string {
const result = this.getResultFromResponse(response);
return result.content
@@ -53,6 +56,7 @@ export class AnthropicProvider extends Provider<AnthropicStreamEvent> {
.join(" ");
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getTextFromStreamResponse(response: Record<string, any>): string {
const event = this.getStreamingEventResponse(response);
if (event?.type === "content_block_delta") {
@@ -23,12 +23,14 @@ import {
export class MetaProvider extends Provider<MetaStreamEvent> {
getResultFromResponse(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
response: Record<string, any>,
): MetaNoneStreamingResponse {
return JSON.parse(toUtf8(response.body));
}
getToolsFromResponse<ToolContent>(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
response: Record<string, any>,
): ToolContent[] {
const result = this.getResultFromResponse(response);
@@ -45,12 +47,14 @@ export class MetaProvider extends Provider<MetaStreamEvent> {
];
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getTextFromResponse(response: Record<string, any>): string {
const result = this.getResultFromResponse(response);
if (result.generation.trim().startsWith(TOKENS.TOOL_CALL)) return "";
return result.generation;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getTextFromStreamResponse(response: Record<string, any>): string {
const event = this.getStreamingEventResponse(response);
if (event?.generation) {
@@ -20,15 +20,18 @@ export type BedrockChatStreamResponse = AsyncIterable<
ChatResponseChunk<ToolCallLLMMessageOptions>
>;
export abstract class Provider<ProviderStreamEvent extends {} = {}> {
export abstract class Provider<ProviderStreamEvent extends object = object> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
abstract getTextFromResponse(response: Record<string, any>): string;
// Return tool calls from none streaming calls
abstract getToolsFromResponse<T extends {} = {}>(
abstract getToolsFromResponse<T extends object = object>(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
response: Record<string, any>,
): T[];
getStreamingEventResponse(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
response: Record<string, any>,
): ProviderStreamEvent | undefined {
return response.chunk?.bytes
@@ -47,6 +50,7 @@ export abstract class Provider<ProviderStreamEvent extends {} = {}> {
});
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getTextFromStreamResponse(response: Record<string, any>): string {
return this.getTextFromResponse(response);
}
+6
View File
@@ -1,5 +1,11 @@
# @llamaindex/core
## 0.4.1
### Patch Changes
- 9c73f0a: fix: async local storage in `Setting.with` API
## 0.4.0
### Minor Changes
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/core",
"type": "module",
"version": "0.4.0",
"version": "0.4.1",
"description": "LlamaIndex Core Module",
"exports": {
"./agent": {
@@ -355,7 +355,7 @@
},
"dependencies": {
"@llamaindex/env": "workspace:*",
"@types/node": "^22.5.1",
"@types/node": "^22.8.4",
"magic-bytes.js": "^1.10.0",
"zod": "^3.23.8",
"zod-to-json-schema": "^3.23.3"
+8
View File
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
+5 -5
View File
@@ -28,7 +28,7 @@ export const MAX_TOOL_CALLS = 10;
export function createTaskOutputStream<
Model extends LLM,
Store extends object = {},
Store extends object = object,
AdditionalMessageOptions extends object = Model extends LLM<
object,
infer AdditionalMessageOptions
@@ -99,7 +99,7 @@ export function createTaskOutputStream<
export type AgentRunnerParams<
AI extends LLM,
Store extends object = {},
Store extends object = object,
AdditionalMessageOptions extends object = AI extends LLM<
object,
infer AdditionalMessageOptions
@@ -146,7 +146,7 @@ export type AgentParamsBase<
*/
export abstract class AgentWorker<
AI extends LLM,
Store extends object = {},
Store extends object = object,
AdditionalMessageOptions extends object = AI extends LLM<
object,
infer AdditionalMessageOptions
@@ -198,7 +198,7 @@ export abstract class AgentWorker<
*/
export abstract class AgentRunner<
AI extends LLM,
Store extends object = {},
Store extends object = object,
AdditionalMessageOptions extends object = AI extends LLM<
object,
infer AdditionalMessageOptions
@@ -292,7 +292,7 @@ export abstract class AgentRunner<
static shouldContinue<
AI extends LLM,
Store extends object = {},
Store extends object = object,
AdditionalMessageOptions extends object = AI extends LLM<
object,
infer AdditionalMessageOptions
+4 -4
View File
@@ -12,7 +12,7 @@ import type {
export type AgentTaskContext<
Model extends LLM,
Store extends object = {},
Store extends object = object,
AdditionalMessageOptions extends object = Model extends LLM<
object,
infer AdditionalMessageOptions
@@ -38,7 +38,7 @@ export type AgentTaskContext<
export type TaskStep<
Model extends LLM = LLM,
Store extends object = {},
Store extends object = object,
AdditionalMessageOptions extends object = Model extends LLM<
object,
infer AdditionalMessageOptions
@@ -56,7 +56,7 @@ export type TaskStep<
export type TaskStepOutput<
Model extends LLM,
Store extends object = {},
Store extends object = object,
AdditionalMessageOptions extends object = Model extends LLM<
object,
infer AdditionalMessageOptions
@@ -74,7 +74,7 @@ export type TaskStepOutput<
export type TaskHandler<
Model extends LLM,
Store extends object = {},
Store extends object = object,
AdditionalMessageOptions extends object = Model extends LLM<
object,
infer AdditionalMessageOptions
+2 -2
View File
@@ -25,9 +25,9 @@ import type { TaskHandler } from "./types.js";
type StepToolsResponseParams<Model extends LLM> = {
response: ChatResponse<ToolCallLLMMessageOptions>;
tools: BaseTool[];
step: Parameters<TaskHandler<Model, {}, ToolCallLLMMessageOptions>>[0];
step: Parameters<TaskHandler<Model, object, ToolCallLLMMessageOptions>>[0];
enqueueOutput: Parameters<
TaskHandler<Model, {}, ToolCallLLMMessageOptions>
TaskHandler<Model, object, ToolCallLLMMessageOptions>
>[1];
};
+2 -2
View File
@@ -8,9 +8,9 @@ export function wrapEventCaller<This, Result, Args extends unknown[]>(
) {
const name = context.name;
context.addInitializer(function () {
// @ts-expect-error
// @ts-expect-error - this is a valid assignment
const fn = this[name].bind(this);
// @ts-expect-error
// @ts-expect-error - this is a valid assignment
this[name] = (...args: unknown[]) => {
return withEventCaller(this, () => fn(...args));
};
+3 -1
View File
@@ -19,7 +19,9 @@ export type BaseEmbeddingOptions = {
logProgress?: boolean;
};
export abstract class BaseEmbedding extends TransformComponent {
export abstract class BaseEmbedding extends TransformComponent<
Promise<BaseNode[]>
> {
embedBatchSize = DEFAULT_EMBED_BATCH_SIZE;
embedInfo?: EmbeddingInfo;
+9 -2
View File
@@ -72,13 +72,15 @@ export function similarity(
* @param similarityCutoff minimum similarity score
* @returns
*/
// eslint-disable-next-line max-params
export function getTopKEmbeddings(
queryEmbedding: number[],
embeddings: number[][],
similarityTopK: number = 2,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
embeddingIds: any[] | null = null,
similarityCutoff: number | null = null,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): [number[], any[]] {
if (embeddingIds == null) {
embeddingIds = Array(embeddings.length).map((_, i) => i);
@@ -102,6 +104,7 @@ export function getTopKEmbeddings(
similarities.sort((a, b) => b.similarity - a.similarity); // Reverse sort
const resultSimilarities: number[] = [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const resultIds: any[] = [];
for (let i = 0; i < similarityTopK; i++) {
@@ -115,15 +118,16 @@ export function getTopKEmbeddings(
return [resultSimilarities, resultIds];
}
// eslint-disable-next-line max-params
export function getTopKMMREmbeddings(
queryEmbedding: number[],
embeddings: number[][],
similarityFn: ((...args: any[]) => number) | null = null,
similarityTopK: number | null = null,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
embeddingIds: any[] | null = null,
_similarityCutoff: number | null = null,
mmrThreshold: number | null = null,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): [number[], any[]] {
const threshold = mmrThreshold || 0.5;
similarityFn = similarityFn || similarity;
@@ -133,8 +137,10 @@ export function getTopKMMREmbeddings(
}
const fullEmbedMap = new Map(embeddingIds.map((value, i) => [value, i]));
const embedMap = new Map(fullEmbedMap);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const embedSimilarity: Map<any, number> = new Map();
let score: number = Number.NEGATIVE_INFINITY;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let highScoreId: any | null = null;
for (let i = 0; i < embeddings.length; i++) {
@@ -147,6 +153,7 @@ export function getTopKMMREmbeddings(
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const results: [number, any][] = [];
const embeddingLength = embeddings.length;

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