mirror of
https://github.com/run-llama/LlamaIndexTS.git
synced 2026-07-01 22:14:03 -04:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5bb4531245 | |||
| 2ff0a89891 | |||
| d57917d782 | |||
| f231e0739f | |||
| 0765742ef3 | |||
| ec7fd6be5c | |||
| c7a918c3f5 | |||
| 00e681d43b | |||
| c01502fb84 | |||
| 075f88dbc3 | |||
| cc47ee0602 | |||
| 5e6ef55a5a | |||
| 9c73f0a530 | |||
| 52a4d2b83d | |||
| 0fd78d5434 |
@@ -1,84 +0,0 @@
|
||||
const { join } = require("node:path");
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: [
|
||||
"turbo",
|
||||
"prettier",
|
||||
"plugin:@typescript-eslint/recommended-type-checked-only",
|
||||
],
|
||||
parserOptions: {
|
||||
project: join(__dirname, "tsconfig.eslint.json"),
|
||||
__tsconfigRootDir: __dirname,
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
version: "999.999.999",
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
"max-params": ["error", 4],
|
||||
"prefer-const": "error",
|
||||
"@typescript-eslint/no-floating-promises": [
|
||||
"error",
|
||||
{
|
||||
ignoreIIFE: true,
|
||||
},
|
||||
],
|
||||
"no-debugger": "error",
|
||||
"@typescript-eslint/await-thenable": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/ban-types": "off",
|
||||
"no-array-constructor": "off",
|
||||
"@typescript-eslint/no-array-constructor": "off",
|
||||
"@typescript-eslint/no-base-to-string": [
|
||||
"error",
|
||||
{
|
||||
ignoredTypeNames: ["Error", "RegExp", "URL", "URLSearchParams"],
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-duplicate-enum-values": "off",
|
||||
"@typescript-eslint/no-duplicate-type-constituents": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-extra-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-for-in-array": "off",
|
||||
"no-implied-eval": "off",
|
||||
"@typescript-eslint/no-implied-eval": "off",
|
||||
"no-loss-of-precision": "off",
|
||||
"@typescript-eslint/no-loss-of-precision": "off",
|
||||
"@typescript-eslint/no-misused-new": "off",
|
||||
"@typescript-eslint/no-misused-promises": "off",
|
||||
"@typescript-eslint/no-namespace": "off",
|
||||
"@typescript-eslint/no-non-null-asserted-optional-chain": "off",
|
||||
"@typescript-eslint/no-redundant-type-constituents": "off",
|
||||
"@typescript-eslint/no-this-alias": "off",
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "off",
|
||||
"@typescript-eslint/no-unnecessary-type-constraint": "off",
|
||||
"@typescript-eslint/no-unsafe-argument": "off",
|
||||
"@typescript-eslint/no-unsafe-assignment": "off",
|
||||
"@typescript-eslint/no-unsafe-call": "off",
|
||||
"@typescript-eslint/no-unsafe-declaration-merging": "off",
|
||||
"@typescript-eslint/no-unsafe-enum-comparison": "off",
|
||||
"@typescript-eslint/no-unsafe-member-access": "off",
|
||||
"@typescript-eslint/no-unsafe-return": "off",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"@typescript-eslint/prefer-as-const": "off",
|
||||
"require-await": "off",
|
||||
"@typescript-eslint/require-await": "off",
|
||||
"@typescript-eslint/restrict-plus-operands": "off",
|
||||
"@typescript-eslint/restrict-template-expressions": "off",
|
||||
"@typescript-eslint/triple-slash-reference": "off",
|
||||
"@typescript-eslint/unbound-method": "off",
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["examples/**/*.ts"],
|
||||
rules: {
|
||||
"turbo/no-undeclared-env-vars": "off",
|
||||
},
|
||||
},
|
||||
],
|
||||
ignorePatterns: ["dist/", "lib/", "deps/"],
|
||||
};
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version: [18.x, 20.x, 22.x]
|
||||
node-version: [20.x, 22.x, 23.x]
|
||||
name: E2E on Node.js ${{ matrix.node-version }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version: [18.x, 20.x, 22.x]
|
||||
node-version: [20.x, 22.x, 23.x]
|
||||
name: Test on Node.js ${{ matrix.node-version }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -84,7 +84,9 @@ jobs:
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
- name: Use Build For Examples
|
||||
run: pnpm link ../packages/llamaindex/
|
||||
run: |
|
||||
pnpm link ../packages/llamaindex/
|
||||
cd readers && pnpm link ../../packages/llamaindex/
|
||||
working-directory: ./examples
|
||||
- name: Run Type Check
|
||||
run: pnpm run type-check
|
||||
|
||||
@@ -25,7 +25,7 @@ LlamaIndex.TS aims to be a lightweight, easy to use set of libraries to help you
|
||||
|
||||
LlamaIndex.TS supports multiple JS environments, including:
|
||||
|
||||
- Node.js (18, 20, 22) ✅
|
||||
- Node.js >= 20 ✅
|
||||
- Deno ✅
|
||||
- Bun ✅
|
||||
- Nitro ✅
|
||||
@@ -57,213 +57,9 @@ pnpm install llamaindex
|
||||
yarn add llamaindex
|
||||
```
|
||||
|
||||
### Setup TypeScript
|
||||
### Setup in Node.js, Deno, Bun, TypeScript...?
|
||||
|
||||
```json5
|
||||
{
|
||||
compilerOptions: {
|
||||
// ⬇️ add this line to your tsconfig.json
|
||||
moduleResolution: "bundler", // or "node16"
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Why?</summary>
|
||||
We are shipping both ESM and CJS module, and compatible with Vercel Edge, Cloudflare Workers, and other serverless platforms.
|
||||
|
||||
So we are using [conditional exports](https://nodejs.org/api/packages.html#conditional-exports) to support all environments.
|
||||
|
||||
This is a kind of modern way of shipping packages, but might cause TypeScript type check to fail because of legacy module resolution.
|
||||
|
||||
Imaging you put output file into `/dist/openai.js` but you are importing `llamaindex/openai` in your code, and set `package.json` like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"exports": {
|
||||
"./openai": "./dist/openai.js"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In old module resolution, TypeScript will not be able to find the module because it is not follow the file structure, even you run `node index.js` successfully. (on Node.js >=16)
|
||||
|
||||
See more about [moduleResolution](https://www.typescriptlang.org/docs/handbook/modules/theory.html#module-resolution) or
|
||||
[TypeScript 5.0 blog](https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#--moduleresolution-bundler7).
|
||||
|
||||
</details>
|
||||
|
||||
### Node.js
|
||||
|
||||
```ts
|
||||
import fs from "node:fs/promises";
|
||||
import { Document, VectorStoreIndex } from "llamaindex";
|
||||
|
||||
async function main() {
|
||||
// Load essay from abramov.txt in Node
|
||||
const essay = await fs.readFile(
|
||||
"node_modules/llamaindex/examples/abramov.txt",
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
// Create Document object with essay
|
||||
const document = new Document({ text: essay });
|
||||
|
||||
// Split text and create embeddings. Store them in a VectorStoreIndex
|
||||
const index = await VectorStoreIndex.fromDocuments([document]);
|
||||
|
||||
// Query the index
|
||||
const queryEngine = index.asQueryEngine();
|
||||
const response = await queryEngine.query({
|
||||
query: "What did the author do in college?",
|
||||
});
|
||||
|
||||
// Output response
|
||||
console.log(response.toString());
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
```bash
|
||||
# `pnpm install tsx` before running the script
|
||||
node --import tsx ./main.ts
|
||||
```
|
||||
|
||||
### Next.js
|
||||
|
||||
You will need to add a llamaindex plugin to your Next.js project.
|
||||
|
||||
```js
|
||||
// next.config.js
|
||||
const withLlamaIndex = require("llamaindex/next");
|
||||
|
||||
module.exports = withLlamaIndex({
|
||||
// your next.js config
|
||||
});
|
||||
```
|
||||
|
||||
### React Server Actions
|
||||
|
||||
You can combine `ai` with `llamaindex` in Next.js, Waku or Redwood.js with RSC (React Server Components).
|
||||
|
||||
```tsx
|
||||
"use client";
|
||||
import { chatWithAgent } from "@/actions";
|
||||
import type { JSX } from "react";
|
||||
import { useActionState } from "react";
|
||||
|
||||
export default function Home() {
|
||||
const [ui, action] = useActionState<JSX.Element | null>(async () => {
|
||||
return chatWithAgent("hello!", []);
|
||||
}, null);
|
||||
return (
|
||||
<main>
|
||||
{ui}
|
||||
<form action={action}>
|
||||
<button>Chat</button>
|
||||
</form>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
```tsx
|
||||
// src/actions/index.ts
|
||||
"use server";
|
||||
import { createStreamableUI } from "ai/rsc";
|
||||
import { OpenAIAgent } from "llamaindex";
|
||||
import type { ChatMessage } from "llamaindex/llm/types";
|
||||
|
||||
export async function chatWithAgent(
|
||||
question: string,
|
||||
prevMessages: ChatMessage[] = [],
|
||||
) {
|
||||
const agent = new OpenAIAgent({
|
||||
tools: [
|
||||
// ... adding your tools here
|
||||
],
|
||||
});
|
||||
const responseStream = await agent.chat(
|
||||
{
|
||||
message: question,
|
||||
chatHistory: prevMessages,
|
||||
},
|
||||
true,
|
||||
);
|
||||
const uiStream = createStreamableUI(<div>loading...</div>);
|
||||
responseStream
|
||||
.pipeTo(
|
||||
new WritableStream({
|
||||
start: () => {
|
||||
uiStream.update("response:");
|
||||
},
|
||||
write: async (message) => {
|
||||
uiStream.append(message.response.delta);
|
||||
},
|
||||
}),
|
||||
)
|
||||
.catch(console.error);
|
||||
return uiStream.value;
|
||||
}
|
||||
```
|
||||
|
||||
### Cloudflare Workers
|
||||
|
||||
> [!TIP]
|
||||
> Some modules are not supported in Cloudflare Workers which require Node.js APIs.
|
||||
|
||||
```ts
|
||||
// add `OPENAI_API_KEY` to the `.dev.vars` file
|
||||
interface Env {
|
||||
OPENAI_API_KEY: string;
|
||||
}
|
||||
|
||||
export default {
|
||||
async fetch(
|
||||
request: Request,
|
||||
env: Env,
|
||||
ctx: ExecutionContext,
|
||||
): Promise<Response> {
|
||||
const { OpenAIAgent, OpenAI } = await import("@llamaindex/openai");
|
||||
const text = await request.text();
|
||||
const agent = new OpenAIAgent({
|
||||
llm: new OpenAI({
|
||||
apiKey: env.OPENAI_API_KEY,
|
||||
}),
|
||||
tools: [],
|
||||
});
|
||||
const responseStream = await agent.chat({
|
||||
stream: true,
|
||||
message: text,
|
||||
});
|
||||
const textEncoder = new TextEncoder();
|
||||
const response = responseStream.pipeThrough<Uint8Array>(
|
||||
new TransformStream({
|
||||
transform: (chunk, controller) => {
|
||||
controller.enqueue(textEncoder.encode(chunk.delta));
|
||||
},
|
||||
}),
|
||||
);
|
||||
return new Response(response);
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Vite
|
||||
|
||||
We have some wasm dependencies for better performance. You can use `vite-plugin-wasm` to load them.
|
||||
|
||||
```ts
|
||||
import wasm from "vite-plugin-wasm";
|
||||
|
||||
export default {
|
||||
plugins: [wasm()],
|
||||
ssr: {
|
||||
external: ["tiktoken"],
|
||||
},
|
||||
};
|
||||
```
|
||||
See our official document: <https://ts.llamaindex.ai/docs/llamaindex/setup/getting-started>
|
||||
|
||||
### Tips when using in non-Node.js environments
|
||||
|
||||
|
||||
@@ -1,5 +1,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
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @ts-check
|
||||
// Note: type annotations allow type checking and IDEs autocompletion
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const renderer = require("prism-react-renderer");
|
||||
const lightCodeTheme = renderer.themes.github;
|
||||
const darkCodeTheme = renderer.themes.dracula;
|
||||
@@ -39,6 +40,7 @@ const config = {
|
||||
// editUrl:
|
||||
// "https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/",
|
||||
remarkPlugins: [
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
[require("@docusaurus/remark-plugin-npm2yarn"), { sync: true }],
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docs",
|
||||
"version": "0.0.103",
|
||||
"version": "0.0.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: (
|
||||
<>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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.
Executable
BIN
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
import env from "@next/env";
|
||||
|
||||
import { updateLlamaCloud } from "./update-llamacloud.mjs";
|
||||
|
||||
env.loadEnvConfig(process.cwd());
|
||||
|
||||
await updateLlamaCloud();
|
||||
@@ -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");
|
||||
}
|
||||
@@ -1,15 +1,10 @@
|
||||
import { PipelinesService } from "@llamaindex/cloud/api";
|
||||
import { rehypeCodeDefaultOptions } from "fumadocs-core/mdx-plugins";
|
||||
import { fileGenerator, remarkDocGen, remarkInstall } from "fumadocs-docgen";
|
||||
import { defineConfig, defineDocs } from "fumadocs-mdx/config";
|
||||
import { transformerTwoslash } from "fumadocs-twoslash";
|
||||
import { relative } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import rehypeKatex from "rehype-katex";
|
||||
import remarkMath from "remark-math";
|
||||
|
||||
const baseDir = fileURLToPath(new URL("../src/content", import.meta.url));
|
||||
|
||||
export const { docs, meta } = defineDocs({
|
||||
dir: "./src/content/docs",
|
||||
});
|
||||
@@ -49,68 +44,6 @@ export default defineConfig({
|
||||
remarkMath,
|
||||
[remarkInstall, { persist: { id: "package-manager" } }],
|
||||
[remarkDocGen, { generators: [fileGenerator()] }],
|
||||
() => {
|
||||
return (_, file, next) => {
|
||||
const metadata = file.data.frontmatter as Record<string, unknown>;
|
||||
const title = metadata.title as string;
|
||||
const description = metadata.description as string;
|
||||
let content: string;
|
||||
if (file.value instanceof Uint8Array) {
|
||||
content = file.value.toString();
|
||||
} else {
|
||||
content = file.value;
|
||||
}
|
||||
if (file.path.includes("content/docs/cloud/api")) {
|
||||
// skip cloud api docs
|
||||
return next();
|
||||
}
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
// skip development
|
||||
return next();
|
||||
}
|
||||
if (!title || !description) {
|
||||
throw new Error(`Missing title or description in ${file.path}`);
|
||||
}
|
||||
const id = relative(baseDir, file.path);
|
||||
|
||||
if (
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
process.env.LLAMA_CLOUD_UPSERT_PIPELINE_DOCUMENTS === "true" &&
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
process.env.LLAMA_CLOUD_PIPELINE_ID !== undefined
|
||||
) {
|
||||
PipelinesService.upsertBatchPipelineDocumentsApiV1PipelinesPipelineIdDocumentsPut(
|
||||
{
|
||||
baseUrl: "https://api.cloud.llamaindex.ai/",
|
||||
body: [
|
||||
{
|
||||
metadata: {
|
||||
title,
|
||||
description,
|
||||
documentUrl: id,
|
||||
},
|
||||
text: content,
|
||||
id,
|
||||
},
|
||||
],
|
||||
path: {
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
pipeline_id: process.env.LLAMA_CLOUD_PIPELINE_ID,
|
||||
},
|
||||
throwOnError: true,
|
||||
headers: {
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
Authorization: `Bearer ${process.env.LLAMA_CLOUD_API_KEY}`,
|
||||
},
|
||||
},
|
||||
).catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
return next();
|
||||
};
|
||||
},
|
||||
],
|
||||
rehypePlugins: (v) => [rehypeKatex, ...v],
|
||||
},
|
||||
|
||||
@@ -14,10 +14,9 @@ Settings.llm = new OpenAI({
|
||||
});
|
||||
|
||||
const retriever = new LlamaCloudRetriever({
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
apiKey: process.env.LLAMA_CLOUD_API_KEY!,
|
||||
baseUrl: "https://api.cloud.llamaindex.ai/",
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
|
||||
pipelineId: process.env.LLAMA_CLOUD_PIPELINE_ID!,
|
||||
});
|
||||
|
||||
@@ -27,7 +26,7 @@ const initialAIState = {
|
||||
messages: ChatMessage[];
|
||||
};
|
||||
|
||||
type UIMessage = {
|
||||
export type UIMessage = {
|
||||
id: number;
|
||||
display: ReactNode;
|
||||
};
|
||||
@@ -38,6 +37,7 @@ const initialUIState = {
|
||||
messages: UIMessage[];
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const runAsyncFnWithoutBlocking = (fn: (...args: any) => Promise<any>) => {
|
||||
fn().catch((error) => {
|
||||
console.error(error);
|
||||
|
||||
@@ -11,7 +11,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 />
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createMetadata, metadataImage } from "@/lib/metadata";
|
||||
import { openapi, source } from "@/lib/source";
|
||||
import { Popup, PopupContent, PopupTrigger } from "fumadocs-twoslash/ui";
|
||||
import { createTypeTable } from "fumadocs-typescript/ui";
|
||||
import defaultMdxComponents from "fumadocs-ui/mdx";
|
||||
import {
|
||||
DocsBody,
|
||||
@@ -10,6 +11,8 @@ import {
|
||||
} from "fumadocs-ui/page";
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
const { AutoTypeTable } = createTypeTable();
|
||||
|
||||
export default async function Page(props: {
|
||||
params: Promise<{ slug?: string[] }>;
|
||||
}) {
|
||||
@@ -20,7 +23,16 @@ export default async function Page(props: {
|
||||
const MDX = page.data.body;
|
||||
|
||||
return (
|
||||
<DocsPage toc={page.data.toc} full={page.data.full}>
|
||||
<DocsPage
|
||||
toc={page.data.toc}
|
||||
full={page.data.full}
|
||||
editOnGithub={{
|
||||
owner: "run-llama",
|
||||
repo: "LlamaIndexTS",
|
||||
sha: "main",
|
||||
path: `apps/next/src/content/docs/${page.file.path}`,
|
||||
}}
|
||||
>
|
||||
<DocsTitle>{page.data.title}</DocsTitle>
|
||||
<DocsDescription>{page.data.description}</DocsDescription>
|
||||
<DocsBody>
|
||||
@@ -31,6 +43,7 @@ export default async function Page(props: {
|
||||
Popup,
|
||||
PopupContent,
|
||||
PopupTrigger,
|
||||
AutoTypeTable,
|
||||
}}
|
||||
/>
|
||||
</DocsBody>
|
||||
|
||||
@@ -1,38 +1,54 @@
|
||||
import { baseOptions } from "@/app/layout.config";
|
||||
import { AITrigger } from "@/components/ai-chat";
|
||||
import { buttonVariants } from "@/components/ui/button";
|
||||
import { LEGACY_DOCUMENT_URL } from "@/lib/const";
|
||||
import { source } from "@/lib/source";
|
||||
import { cn } from "@/lib/utils";
|
||||
import "fumadocs-twoslash/twoslash.css";
|
||||
import { Banner } from "fumadocs-ui/components/banner";
|
||||
import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
||||
import { MessageCircle } from "lucide-react";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<DocsLayout
|
||||
tree={source.pageTree}
|
||||
{...baseOptions}
|
||||
nav={{
|
||||
...baseOptions.nav,
|
||||
children: (
|
||||
<AITrigger
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
variant: "secondary",
|
||||
size: "xs",
|
||||
className:
|
||||
"md:flex-1 px-2 ms-2 gap-1.5 text-fd-muted-foreground rounded-full",
|
||||
}),
|
||||
)}
|
||||
>
|
||||
<MessageCircle className="size-3" />
|
||||
Ask LlamaCloud
|
||||
</AITrigger>
|
||||
),
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</DocsLayout>
|
||||
<>
|
||||
<Banner variant="rainbow" id="welcome">
|
||||
Welcome to the new LlamaIndex.TS documentation! 🎉 If you are looking
|
||||
for the old documentation
|
||||
<a
|
||||
className="underline text-blue-500 ml-1"
|
||||
target="_blank"
|
||||
href={LEGACY_DOCUMENT_URL}
|
||||
>
|
||||
check it here
|
||||
</a>
|
||||
.
|
||||
</Banner>
|
||||
<DocsLayout
|
||||
tree={source.pageTree}
|
||||
{...baseOptions}
|
||||
nav={{
|
||||
...baseOptions.nav,
|
||||
children: (
|
||||
<AITrigger
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
variant: "secondary",
|
||||
size: "xs",
|
||||
className:
|
||||
"md:flex-1 px-2 ms-2 gap-1.5 text-fd-muted-foreground rounded-full",
|
||||
}),
|
||||
)}
|
||||
>
|
||||
<MessageCircle className="size-3" />
|
||||
Ask LlamaCloud
|
||||
</AITrigger>
|
||||
),
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</DocsLayout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DOCUMENT_URL } from "@/lib/const";
|
||||
import { 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",
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import NumberFlow from "@number-flow/react";
|
||||
import clsx from "clsx/lite";
|
||||
import { Minus, Plus } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
type Props = {
|
||||
value?: number;
|
||||
min?: number;
|
||||
max?: number;
|
||||
onChange?: (value: number) => void;
|
||||
};
|
||||
export default function FlowInput({
|
||||
value = 0,
|
||||
min = -Infinity,
|
||||
max = Infinity,
|
||||
onChange,
|
||||
}: Props) {
|
||||
const defaultValue = React.useRef(value);
|
||||
const inputRef = React.useRef<HTMLInputElement>(null);
|
||||
const [animated, setAnimated] = React.useState(true);
|
||||
const [showCaret, setShowCaret] = React.useState(true);
|
||||
const handleInput: React.ChangeEventHandler<HTMLInputElement> = ({
|
||||
currentTarget: el,
|
||||
}) => {
|
||||
setAnimated(false);
|
||||
let next = value;
|
||||
if (el.value === "") {
|
||||
next = defaultValue.current;
|
||||
} else {
|
||||
const num = parseInt(el.value);
|
||||
if (!isNaN(num) && min <= num && num <= max) next = num;
|
||||
}
|
||||
el.value = String(next);
|
||||
onChange?.(next);
|
||||
};
|
||||
const handlePointerDown =
|
||||
(diff: number) => (event: React.PointerEvent<HTMLButtonElement>) => {
|
||||
setAnimated(true);
|
||||
if (event.pointerType === "mouse") {
|
||||
event?.preventDefault();
|
||||
inputRef.current?.focus();
|
||||
}
|
||||
const newVal = Math.min(Math.max(value + diff, min), max);
|
||||
onChange?.(newVal);
|
||||
};
|
||||
return (
|
||||
<div className="group flex items-stretch rounded-md text-lg font-semibold ring ring-zinc-200 transition-[box-shadow] focus-within:ring-2 focus-within:ring-blue-500 dark:ring-zinc-800">
|
||||
<button
|
||||
aria-hidden
|
||||
tabIndex={-1}
|
||||
className="flex items-center pl-[.5em] pr-[.325em]"
|
||||
disabled={min != null && value <= min}
|
||||
onPointerDown={handlePointerDown(-1)}
|
||||
>
|
||||
<Minus className="size-4" absoluteStrokeWidth strokeWidth={3.5} />
|
||||
</button>
|
||||
<div className="relative grid items-center justify-items-center text-center [grid-template-areas:'overlap'] *:[grid-area:overlap]">
|
||||
<input
|
||||
ref={inputRef}
|
||||
className={clsx(
|
||||
showCaret ? "caret-primary" : "caret-transparent",
|
||||
"spin-hide w-[1.5em] bg-transparent py-2 text-center font-[inherit] text-transparent outline-none",
|
||||
"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
|
||||
)}
|
||||
// Make sure to disable kerning, to match NumberFlow:
|
||||
style={{ fontKerning: "none" }}
|
||||
type="number"
|
||||
min={min}
|
||||
step={1}
|
||||
autoComplete="off"
|
||||
inputMode="numeric"
|
||||
max={max}
|
||||
value={value}
|
||||
onInput={handleInput}
|
||||
/>
|
||||
<NumberFlow
|
||||
value={value}
|
||||
format={{ useGrouping: false }}
|
||||
aria-hidden
|
||||
animated={animated}
|
||||
onAnimationsStart={() => setShowCaret(false)}
|
||||
onAnimationsFinish={() => setShowCaret(true)}
|
||||
className="pointer-events-none"
|
||||
willChange
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
aria-hidden
|
||||
tabIndex={-1}
|
||||
className="flex items-center pl-[.325em] pr-[.5em]"
|
||||
disabled={max != null && value >= max}
|
||||
onPointerDown={handlePointerDown(1)}
|
||||
>
|
||||
<Plus className="size-4" absoluteStrokeWidth strokeWidth={3.5} />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const badgeVariants = cva(
|
||||
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
|
||||
secondary:
|
||||
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
destructive:
|
||||
"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
|
||||
outline: "text-foreground",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
export interface BadgeProps
|
||||
extends React.HTMLAttributes<HTMLDivElement>,
|
||||
VariantProps<typeof badgeVariants> {}
|
||||
|
||||
function Badge({ className, variant, ...props }: BadgeProps) {
|
||||
return (
|
||||
<div className={cn(badgeVariants({ variant }), className)} {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
export { Badge, badgeVariants };
|
||||
@@ -2,8 +2,7 @@ import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export interface InputProps
|
||||
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
||||
export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
|
||||
|
||||
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
({ className, type, ...props }, ref) => {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
"use client";
|
||||
|
||||
import * as LabelPrimitive from "@radix-ui/react-label";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const labelVariants = cva(
|
||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
||||
);
|
||||
|
||||
const Label = React.forwardRef<
|
||||
React.ElementRef<typeof LabelPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
|
||||
VariantProps<typeof labelVariants>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<LabelPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(labelVariants(), className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
Label.displayName = LabelPrimitive.Root.displayName;
|
||||
|
||||
export { Label };
|
||||
@@ -0,0 +1,28 @@
|
||||
"use client";
|
||||
|
||||
import * as SliderPrimitive from "@radix-ui/react-slider";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Slider = React.forwardRef<
|
||||
React.ElementRef<typeof SliderPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SliderPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex w-full touch-none select-none items-center",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
|
||||
<SliderPrimitive.Range className="absolute h-full bg-primary" />
|
||||
</SliderPrimitive.Track>
|
||||
<SliderPrimitive.Thumb className="block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" />
|
||||
</SliderPrimitive.Root>
|
||||
));
|
||||
Slider.displayName = SliderPrimitive.Root.displayName;
|
||||
|
||||
export { Slider };
|
||||
@@ -2,8 +2,7 @@ import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export interface TextareaProps
|
||||
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
||||
export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
|
||||
|
||||
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
({ className, ...props }, ref) => {
|
||||
|
||||
@@ -12,7 +12,9 @@ export interface TextProps {
|
||||
weight?: 400 | 500 | 600;
|
||||
children?: ReactNode;
|
||||
className?: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
as?: any;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
maximumWidth?: any;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,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 />
|
||||
@@ -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"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export type {
|
||||
HandlerContext,
|
||||
Workflow,
|
||||
WorkflowContext,
|
||||
} from "@llamaindex/workflow";
|
||||
@@ -1,2 +1,2 @@
|
||||
// when we are ready, change to /docs/llamaindex
|
||||
export const DOCUMENT_URL = 'https://legacy.ts.llamaindex.ai/'
|
||||
export const LEGACY_DOCUMENT_URL = 'https://legacy.ts.llamaindex.ai/'
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
|
||||
Vendored
+135
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
@@ -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 |
@@ -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",
|
||||
],
|
||||
},
|
||||
);
|
||||
@@ -1,5 +1,12 @@
|
||||
# examples
|
||||
|
||||
## 0.0.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [0765742]
|
||||
- @llamaindex/workflow@0.0.2
|
||||
|
||||
## 0.0.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,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,4 +1,3 @@
|
||||
/* eslint-disable turbo/no-undeclared-env-vars */
|
||||
import { SimpleMongoReader } from "@llamaindex/readers/mongo";
|
||||
import * as dotenv from "dotenv";
|
||||
import {
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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,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(
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"llamaindex": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.5.1",
|
||||
"@types/node": "^22.8.4",
|
||||
"tsx": "^4.19.0",
|
||||
"typescript": "^5.6.2"
|
||||
}
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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,4 +1,3 @@
|
||||
/* eslint-disable turbo/no-undeclared-env-vars */
|
||||
import dotenv from "dotenv";
|
||||
import { Document, PGVectorStore, VectorStoreQueryMode } from "llamaindex";
|
||||
import postgres from "postgres";
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
@@ -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": {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,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>>({});
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/cloud",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @llamaindex/community
|
||||
|
||||
## 0.0.58
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9c73f0a]
|
||||
- @llamaindex/core@0.4.1
|
||||
|
||||
## 0.0.57
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
};
|
||||
|
||||
|
||||
@@ -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));
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user