Compare commits

..

27 Commits

Author SHA1 Message Date
Logan Markewich 62eb1e5f4f ensure build works 2025-04-17 14:26:58 -06:00
Peter Goldstein e5c3f95c6e Update o4-mini to allow reasoning parameters and exclude temperature (#1859) 2025-04-17 13:51:27 +07:00
Thuc Pham b155c8cf2c chore: make llamaindex as peer deps of server (#1860) 2025-04-17 13:50:28 +07:00
github-actions[bot] be6fead71a Release 0.10.1 (#1858)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: himself65 <14026360+himself65@users.noreply.github.com>
2025-04-16 19:15:34 -07:00
Peter Goldstein 96dd79853a Add o3 and o4-mini models (#1857) 2025-04-16 13:28:39 -07:00
Fuma Nama f49366c9af make docs great again (#1855)
Co-authored-by: Marcus Schiesser <mail@marcusschiesser.de>
Co-authored-by: Alex Yang <himself65@outlook.com>
2025-04-16 11:19:25 -07:00
github-actions[bot] cde403be58 Release 0.10.0 (#1854)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: marcusschiesser <17126+marcusschiesser@users.noreply.github.com>
2025-04-16 17:02:34 +07:00
Parham Saidi e9bf4424e2 fix: update the tool call schema for nova (#1850)
Co-authored-by: Marcus Schiesser <mail@marcusschiesser.de>
2025-04-16 16:52:29 +07:00
Thuc Pham edb8b87d86 fix: shadcn components cannot be used in next server (#1853) 2025-04-16 15:57:25 +07:00
Thuc Pham 6cf928f390 chore: use bunchee for llamaindex (#1821) 2025-04-16 15:47:30 +07:00
Alex Yang 8e27fd2009 fix(docs): sha on edit page (#1852) 2025-04-15 23:51:38 -07:00
Alex Yang c84036bbdd fix(doc): use install shortcut (#1849) 2025-04-15 09:08:32 -07:00
github-actions[bot] f43406fc9b Release @llamaindex/community@0.0.95 (#1848)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-04-15 16:00:59 +07:00
Peter Goldstein 411dceaa41 Add Nova Premier model. Add EU endpoints for Nova models (#1841) 2025-04-15 15:48:11 +07:00
Alex Yang 2447384f31 chore: bump fumadocs & next & react (#1845) 2025-04-15 01:20:29 -07:00
github-actions[bot] 5f3eb457e6 Release 0.9.19 (#1844)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: marcusschiesser <17126+marcusschiesser@users.noreply.github.com>
2025-04-15 00:31:31 -07:00
Peter Goldstein d365eb2e54 Add GPT-4.1 models to OpenAI (#1842) 2025-04-15 09:07:38 +02:00
Thuc Pham bb34ade6d4 feat: support cn utils for server UI (#1843) 2025-04-15 09:06:39 +02:00
github-actions[bot] c540df5069 Release 0.9.18 (#1836)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: marcusschiesser <17126+marcusschiesser@users.noreply.github.com>
2025-04-14 20:52:09 +07:00
Marcus Schiesser 400b3b54bf feat: use full-source code with import statements for custom comps (#1838)
Co-authored-by: thucpn <thucsh2@gmail.com>
Co-authored-by: Thuc Pham <51660321+thucpn@users.noreply.github.com>
2025-04-14 13:48:21 +02:00
Marcus Schiesser 88b7046c68 chore: Move zod to peer deps (#1837) 2025-04-10 18:17:26 +07:00
Zhanghao 2ffdb274f2 docs: correct the CondenseQuestionChatEngine path (#1834) 2025-04-10 16:07:07 +07:00
github-actions[bot] 139eb050f9 Release @llamaindex/server@0.1.0 (#1835)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-04-10 15:38:40 +07:00
Thuc Pham 3ffee26b77 feat: enhance config params for LlamaIndexServer (#1833) 2025-04-10 15:21:51 +07:00
Marcus Schiesser dc6e774d78 chore: remove deepresearch events (#1831) 2025-04-09 20:45:49 +07:00
github-actions[bot] 6716188e10 Release @llamaindex/server@0.0.9 (#1830)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-04-09 17:44:13 +07:00
Thuc Pham 0b75bd6d92 feat: component dir in llamaindex server (#1828) 2025-04-09 17:25:21 +07:00
271 changed files with 14431 additions and 6705 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@llamaindex/openai": patch
---
Update o4-mini to accept reasoning parameters and exclude temperature
+45
View File
@@ -1,5 +1,50 @@
# @llamaindex/doc
## 0.2.12
### Patch Changes
- Updated dependencies [96dd798]
- @llamaindex/openai@0.3.3
- llamaindex@0.10.1
## 0.2.11
### Patch Changes
- 6cf928f: chore: use bunchee for llamaindex
- Updated dependencies [6cf928f]
- llamaindex@0.10.0
## 0.2.10
### Patch Changes
- 411dcea: Add Nova Premier to AWS Nova models. Add EU endpoints
## 0.2.9
### Patch Changes
- Updated dependencies [d365eb2]
- @llamaindex/openai@0.3.2
- llamaindex@0.9.19
## 0.2.8
### Patch Changes
- 2ffdb27: docs: correct the CondenseQuestionChatEngine path
- Updated dependencies [88b7046]
- @llamaindex/openai@0.3.1
- llamaindex@0.9.18
## 0.2.7
### Patch Changes
- 3ffee26: feat: enhance config params for LlamaIndexServer
## 0.2.6
### Patch Changes
+2
View File
@@ -0,0 +1,2 @@
// fallback for `fs` usage in `web-tree-sitter`
module.exports = {};
+6 -10
View File
@@ -1,5 +1,4 @@
import { createMDX } from "fumadocs-mdx/next";
import MonacoWebpackPlugin from "monaco-editor-webpack-plugin";
const withMDX = createMDX();
/** @type {import('next').NextConfig} */
@@ -16,7 +15,12 @@ const config = {
"twoslash",
"typescript",
],
webpack: (config, { isServer }) => {
turbopack: {
resolveAlias: {
fs: { browser: "./fallback.js" },
},
},
webpack: (config) => {
if (Array.isArray(config.target) && config.target.includes("web")) {
config.target = ["web", "es2020"];
}
@@ -28,14 +32,6 @@ const config = {
};
config.resolve.fallback ??= {};
config.resolve.fallback.fs = false;
if (!isServer) {
config.plugins.push(
new MonacoWebpackPlugin({
languages: ["typescript"],
filename: "static/[name].worker.js",
}),
);
}
config.resolve.alias["replicate"] = false;
return config;
},
+20 -17
View File
@@ -1,19 +1,21 @@
{
"name": "@llamaindex/doc",
"version": "0.2.6",
"version": "0.2.12",
"private": true,
"scripts": {
"postinstall": "fumadocs-mdx",
"prebuild": "pnpm run build:docs",
"build": "next build",
"dev": "next dev",
"dev": "next dev --turbo",
"start": "next start",
"postbuild": "tsx scripts/post-build.mts && tsx scripts/validate-links.mts",
"build:docs": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" typedoc && tsx scripts/generate-docs.mts",
"validate-links": "tsx scripts/validate-links.mts"
},
"dependencies": {
"@huggingface/transformers": "^3.5.0",
"@icons-pack/react-simple-icons": "^10.1.0",
"@llama-flow/docs": "0.0.3",
"@llamaindex/chat-ui": "0.2.0",
"@llamaindex/cloud": "workspace:*",
"@llamaindex/core": "workspace:*",
@@ -22,6 +24,7 @@
"@llamaindex/readers": "workspace:*",
"@llamaindex/workflow": "workspace:*",
"@mdx-js/mdx": "^3.1.0",
"@monaco-editor/react": "^4.7.0",
"@number-flow/react": "^0.3.4",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-icons": "^1.3.2",
@@ -36,22 +39,21 @@
"clsx": "2.1.1",
"foxact": "^0.2.41",
"framer-motion": "^11.11.17",
"fumadocs-core": "^15.0.15",
"fumadocs-core": "^15.2.7",
"fumadocs-docgen": "^2.0.0",
"fumadocs-mdx": "^11.5.6",
"fumadocs-openapi": "^6.3.0",
"fumadocs-twoslash": "^3.1.0",
"fumadocs-typescript": "^3.1.0",
"fumadocs-ui": "^15.0.15",
"fumadocs-mdx": "^11.6.0",
"fumadocs-openapi": "^8.0.1",
"fumadocs-twoslash": "^3.1.1",
"fumadocs-typescript": "^4.0.2",
"fumadocs-ui": "^15.2.7",
"hast-util-to-jsx-runtime": "^2.3.2",
"llamaindex": "workspace:*",
"lucide-react": "^0.460.0",
"next": "^15.2.4",
"next": "^15.3.0",
"next-themes": "^0.4.3",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-icons": "^5.3.0",
"react-monaco-editor": "^0.56.2",
"react-use-measure": "^2.1.1",
"rehype-katex": "^7.0.1",
"remark-math": "^6.0.0",
@@ -63,12 +65,14 @@
"tailwindcss-animate": "^1.0.7",
"tree-sitter": "^0.22.1",
"tree-sitter-typescript": "^0.23.2",
"ts-morph": "^25.0.1",
"twoslash": "^0.3.1",
"use-stick-to-bottom": "^1.0.42",
"web-tree-sitter": "^0.24.4",
"zod": "^3.23.8"
},
"devDependencies": {
"@next/env": "^15.2.1",
"@next/env": "^15.3.0",
"@tailwindcss/postcss": "^4.0.9",
"@types/mdx": "^2.0.13",
"@types/node": "22.9.0",
@@ -78,7 +82,6 @@
"cross-env": "^7.0.3",
"fast-glob": "^3.3.2",
"gray-matter": "^4.0.3",
"monaco-editor-webpack-plugin": "^7.1.0",
"postcss": "^8.5.3",
"raw-loader": "^4.0.2",
"remark": "^15.0.1",
@@ -87,9 +90,9 @@
"remark-stringify": "^11.0.0",
"tailwindcss": "^4.0.9",
"tsx": "^4.19.3",
"typedoc": "0.27.4",
"typedoc-plugin-markdown": "^4.3.1",
"typedoc-plugin-merge-modules": "^6.1.0",
"typedoc": "0.28.2",
"typedoc-plugin-markdown": "^4.6.2",
"typedoc-plugin-merge-modules": "^7.0.0",
"typescript": "^5.7.3"
}
}

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Before

Width:  |  Height:  |  Size: 236 KiB

After

Width:  |  Height:  |  Size: 236 KiB

Before

Width:  |  Height:  |  Size: 540 KiB

After

Width:  |  Height:  |  Size: 540 KiB

+6 -2
View File
@@ -1,9 +1,13 @@
import { generateFiles as openapiGenerateFiles } from "fumadocs-openapi";
import { generateFiles as typescriptGenerateFiles } from "fumadocs-typescript";
import {
createGenerator,
generateFiles as typescriptGenerateFiles,
} from "fumadocs-typescript";
import fs from "node:fs";
import * as path from "node:path";
import { rimrafSync } from "rimraf";
const generator = createGenerator();
const out = "./src/content/docs/cloud/api";
const apiRefOut = "./src/content/docs/api";
@@ -20,7 +24,7 @@ void openapiGenerateFiles({
groupBy: "tag",
});
void typescriptGenerateFiles({
void typescriptGenerateFiles(generator, {
input: ["./src/content/docs/api/**/*.mdx"],
output: (file) => path.resolve(path.dirname(file), path.basename(file)),
transformOutput,
+4 -1
View File
@@ -7,7 +7,10 @@ import rehypeKatex from "rehype-katex";
import remarkMath from "remark-math";
export const docs = defineDocs({
dir: "./src/content/docs",
dir: ["./src/content/docs", "./node_modules/@llama-flow/docs"],
docs: {
async: true,
},
});
export default defineConfig({
+51 -67
View File
@@ -10,16 +10,55 @@ import { MagicMove } from "@/components/magic-move";
import { NpmInstall } from "@/components/npm-install";
import { Supports } from "@/components/supports";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import { LEGACY_DOCUMENT_URL } from "@/lib/const";
import { DOCUMENT_URL } from "@/lib/const";
import { SiStackblitz } from "@icons-pack/react-simple-icons";
import {
CodeBlock as FumaCodeBlock,
Pre,
} from "fumadocs-ui/components/codeblock";
import { Blocks, Bot, Footprints, Terminal } from "lucide-react";
import Link from "next/link";
import { Suspense } from "react";
const codes = [
`import { openai } from "@llamaindex/openai";
const llm = openai();
const response = await llm.complete({ prompt: "How are you?" });`,
`import { openai } from "@llamaindex/openai";
const llm = openai();
const response = await llm.chat({
messages: [{ content: "Tell me a joke.", role: "user" }],
});`,
`import { agent } from "llamaindex";
import { openai } from "@llamaindex/openai";
const analyseAgent = agent({
llm: openai({ model: "gpt-4o" }),
tools: [analyseTools],
systemPrompt,
});
const response = await analyseAgent.run(\`Analyse the given data:
\${data}\`);`,
`import { agent, multiAgent } from "llamaindex";
import { openai } from "@llamaindex/openai";
const analyseAgent = agent({
name: "AnalyseAgent",
llm: openai({ model: "gpt-4o" }),
tools: [analyseTools],
});
const reporterAgent = agent({
name: "ReporterAgent",
llm: openai({ model: "gpt-4o" }),
tools: [reporterTools],
canHandoffTo: [analyseAgent],
});
const agents = multiAgent({
agents: [analyseAgent, reporterAgent],
rootAgent: reporterAgent,
});
const response = await agents.run(\`Analyse the given data:
\${data}\`);`,
];
export default function HomePage() {
return (
@@ -39,7 +78,7 @@ export default function HomePage() {
</div>
<div className="flex flex-wrap justify-center gap-4">
<Link href={LEGACY_DOCUMENT_URL}>
<Link href={DOCUMENT_URL}>
<Button variant="outline">Get Started</Button>
</Link>
<NpmInstall />
@@ -62,65 +101,10 @@ export default function HomePage() {
heading="From the simplest to the most complex"
description="LlamaIndex.TS is designed to be simple to get started, but powerful enough to build complex, agentic AI applications using multi-agents."
>
<Suspense
fallback={
<FumaCodeBlock allowCopy={false}>
<Pre>
<div className="space-y-2">
<Skeleton className="h-4 w-[250px]" />
<Skeleton className="h-4 w-[200px]" />
</div>
</Pre>
</FumaCodeBlock>
}
>
<MagicMove
code={[
`import { openai } from "@llamaindex/openai";
const llm = openai();
const response = await llm.complete({ prompt: "How are you?" });`,
`import { openai } from "@llamaindex/openai";
const llm = openai();
const response = await llm.chat({
messages: [{ content: "Tell me a joke.", role: "user" }],
});`,
`import { agent } from "llamaindex";
import { openai } from "@llamaindex/openai";
const analyseAgent = agent({
llm: openai({ model: "gpt-4o" }),
tools: [analyseTools],
systemPrompt,
});
const response = await analyseAgent.run(\`Analyse the given data:
\${data}\`);`,
`import { agent, multiAgent } from "llamaindex";
import { openai } from "@llamaindex/openai";
const analyseAgent = agent({
name: "AnalyseAgent",
llm: openai({ model: "gpt-4o" }),
tools: [analyseTools],
});
const reporterAgent = agent({
name: "ReporterAgent",
llm: openai({ model: "gpt-4o" }),
tools: [reporterTools],
canHandoffTo: [analyseAgent],
});
const agents = multiAgent({
agents: [analyseAgent, reporterAgent],
rootAgent: reporterAgent,
});
const response = await agents.run(\`Analyse the given data:
\${data}\`);`,
]}
/>
</Suspense>
<MagicMove
placeholder={<CodeBlock lang="ts" code={codes[0]} />}
code={codes}
/>
</Feature>
<Feature
icon={Bot}
+9 -1
View File
@@ -1,4 +1,12 @@
import { source } from "@/lib/source";
import { structure } from "fumadocs-core/mdx-plugins";
import { createFromSource } from "fumadocs-core/search/server";
export const { GET } = createFromSource(source);
// TODO: migrate to another search service, I don't think Vercel can handle that many of documents.
export const { GET } = createFromSource(source, (page) => ({
id: page.url,
title: page.data.title,
description: page.data.description,
url: page.url,
structuredData: structure(page.data.content),
}));
+25 -7
View File
@@ -1,7 +1,14 @@
import { ChatDemoRSC } from "@/components/demo/chat/rsc/demo";
import * as demos from "@/components/demo/lazy";
import { createMetadata, metadataImage } from "@/lib/metadata";
import { openapi, source } from "@/lib/source";
import * as Icons from "@icons-pack/react-simple-icons";
import { APIPage } from "fumadocs-openapi/ui";
import { Popup, PopupContent, PopupTrigger } from "fumadocs-twoslash/ui";
import { createTypeTable } from "fumadocs-typescript/ui";
import { createGenerator } from "fumadocs-typescript";
import { AutoTypeTable } from "fumadocs-typescript/ui";
import { Accordion, Accordions } from "fumadocs-ui/components/accordion";
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
import defaultMdxComponents from "fumadocs-ui/mdx";
import {
DocsBody,
@@ -11,6 +18,8 @@ import {
} from "fumadocs-ui/page";
import { notFound } from "next/navigation";
const generator = createGenerator();
export const revalidate = false;
export default async function Page(props: {
@@ -20,17 +29,17 @@ export default async function Page(props: {
const page = source.getPage(params.slug);
if (!page) notFound();
const { AutoTypeTable } = createTypeTable();
const MDX = page.data.body;
const { body: MDX, toc, lastModified } = await page.data.load();
return (
<DocsPage
toc={page.data.toc}
toc={toc}
full={page.data.full}
lastUpdate={page.data.lastModified}
lastUpdate={lastModified}
editOnGithub={{
owner: "run-llama",
repo: "LlamaIndexTS",
sha: "main",
path: `apps/next/src/content/docs/${page.file.path}`,
}}
>
@@ -39,12 +48,21 @@ export default async function Page(props: {
<DocsBody>
<MDX
components={{
...Icons,
...defaultMdxComponents,
APIPage: openapi.APIPage,
...demos,
ChatDemoRSC,
Accordion,
Accordions,
APIPage: (props) => <APIPage {...openapi.getAPIPageProps(props)} />,
Tab,
Tabs,
Popup,
PopupContent,
PopupTrigger,
AutoTypeTable,
AutoTypeTable: (props) => (
<AutoTypeTable generator={generator} {...props} />
),
}}
/>
</DocsBody>
+1 -1
View File
@@ -1,7 +1,7 @@
@import "tailwindcss";
@import "fumadocs-ui/css/neutral.css";
@import "fumadocs-ui/css/preset.css";
@import "../../node_modules/fumadocs-twoslash/dist/twoslash.css";
@import "../../node_modules/fumadocs-twoslash/styles/twoslash.css";
@plugin "tailwindcss-animate";
@source '../../node_modules/fumadocs-ui/dist/**/*.js';
@source "../../node_modules/fumadocs-openapi/dist/**/*.js",
+2 -2
View File
@@ -1,4 +1,4 @@
import { LEGACY_DOCUMENT_URL } from "@/lib/const";
import { DOCUMENT_URL } from "@/lib/const";
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
import Image from "next/image";
@@ -28,7 +28,7 @@ export const baseOptions: BaseLayoutProps = {
links: [
{
text: "Docs",
url: LEGACY_DOCUMENT_URL,
url: DOCUMENT_URL,
active: "nested-url",
},
],
@@ -1,24 +1,26 @@
"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";
import { Editor } from "@monaco-editor/react";
import { createContextState } from "foxact/context-state";
import { useIsClient } from "foxact/use-is-client";
import { useShiki } from "fumadocs-core/highlight/client";
import { CodeBlock, Pre } from "fumadocs-ui/components/codeblock";
import { Suspense, use, useMemo } from "react";
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
let promise: Promise<CodeSplitter>;
if (typeof window !== "undefined") {
promise = Parser.init({
locateFile(scriptName: string) {
return "/" + scriptName;
},
}).then(async () => {
async function run() {
const { default: Parser } = await import("web-tree-sitter");
await Parser.init({
locateFile(scriptName: string) {
return "/" + scriptName;
},
});
const parser = new Parser();
const Lang = await Parser.Language.load("/tree-sitter-typescript.wasm");
parser.setLanguage(Lang);
@@ -26,7 +28,9 @@ if (typeof window !== "undefined") {
getParser: () => parser,
maxChars: 100,
});
});
}
promise = run();
}
const [SliderProvider, useSlider, useSetSlider] = createContextState(100);
@@ -48,8 +52,6 @@ const john: Person = {
console.log(greet(john));`);
const Editor = lazy(() => import("react-monaco-editor"));
export const IDE = () => {
const codeSplitter = use(promise);
const code = useCode();
@@ -73,21 +75,6 @@ export const IDE = () => {
/>
</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,
@@ -97,7 +84,9 @@ export const IDE = () => {
height="100%"
width="100%"
language="typescript"
onChange={setCode}
onChange={(v) => {
if (v) setCode(v);
}}
value={code}
/>
</div>
+18
View File
@@ -0,0 +1,18 @@
"use client";
import dynamic from "next/dynamic";
// lazy load client components
export const ChatDemo = dynamic(() =>
import("@/components/demo/chat/api/demo").then((mod) => mod.ChatDemo),
);
export const CodeNodeParserDemo = dynamic(() =>
import("@/components/demo/code-node-parser").then(
(mod) => mod.CodeNodeParserDemo,
),
);
export const WorkflowStreamingDemo = dynamic(() =>
import("@/components/demo/workflow-streaming-ui").then(
(mod) => mod.WorkflowStreamingDemo,
),
);
+26 -21
View File
@@ -1,25 +1,27 @@
"use client";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { CodeBlock, Pre } from "fumadocs-ui/components/codeblock";
import { CodeBlock } from "fumadocs-ui/components/codeblock";
import { RotateCcw } from "lucide-react";
import { useTheme } from "next-themes";
import { use, useCallback, useEffect, useState } from "react";
import { getSingletonHighlighter } from "shiki";
import { type ReactNode, use, useCallback, useEffect, useState } from "react";
import { createJavaScriptRegexEngine, getSingletonHighlighter } from "shiki";
import { ShikiMagicMove } from "shiki-magic-move/react";
import { createOnigurumaEngine } from "shiki/engine/oniguruma";
const engine = createJavaScriptRegexEngine();
const highlighterPromise = getSingletonHighlighter({
engine: createOnigurumaEngine(() => import("shiki/wasm")),
engine,
themes: ["vesper", "github-light"],
langs: ["js", "ts", "tsx"],
});
export type MagicMoveProps = {
code: string[];
placeholder: ReactNode;
};
export function MagicMove(props: MagicMoveProps) {
const [mounted, setMounted] = useState(false);
const [move, setMove] = useState<number>(0);
const currentCode = props.code[move];
const highlighter = use(highlighterPromise);
@@ -38,24 +40,27 @@ export function MagicMove(props: MagicMoveProps) {
}
}, [animate, move, props.code]);
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) return props.placeholder;
return (
<CodeBlock allowCopy={false}>
{highlighter && (
<Pre>
<ShikiMagicMove
lang="ts"
theme={resolvedTheme === "dark" ? "vesper" : "github-light"}
highlighter={highlighter}
code={currentCode}
options={{
duration: 800,
stagger: 0.3,
lineNumbers: false,
containerStyle: false,
}}
/>
</Pre>
)}
<ShikiMagicMove
className="shiki !block p-4 *:!inline"
lang="ts"
theme={resolvedTheme === "dark" ? "vesper" : "github-light"}
highlighter={highlighter}
code={currentCode}
options={{
duration: 800,
stagger: 0.3,
lineNumbers: false,
containerStyle: false,
}}
/>
<Button
className={cn(
"absolute bottom-2 right-2",
@@ -18,4 +18,4 @@ npm run dev
to start the development server. You can then visit [http://localhost:3000](http://localhost:3000) to see your app, which should look something like this:
![create-llama interface](./images/create_llama.png)
![create-llama interface](/images/create_llama.png)
@@ -11,7 +11,7 @@ It may be useful to check out all the examples at once so you can try them out l
```bash npm2yarn
npx degit run-llama/LlamaIndexTS/examples my-new-project
cd my-new-project
npm install
npm i
```
Then you can run any example in the folder with `tsx`, e.g.:
@@ -3,13 +3,6 @@ title: With Cloudflare Worker
description: In this guide, you'll learn how to use LlamaIndex with CloudFlare Worker
---
import {
SiNodedotjs,
SiDeno,
SiBun,
SiCloudflareworkers,
} from "@icons-pack/react-simple-icons";
Before you start, make sure you have try LlamaIndex.TS in Node.js to make sure you understand the basics.
<Card
@@ -3,46 +3,17 @@ title: Installation
description: How to install llamaindex packages.
---
import {
SiNodedotjs,
SiTypescript,
SiNextdotjs,
SiCloudflareworkers,
SiVite
} from "@icons-pack/react-simple-icons";
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
To install llamaindex, run the following command:
<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
```
</Tabs>
```package-install
npm i llamaindex
```
In most cases, you'll also need an LLM package to use LlamaIndex. For example, to use the OpenAI LLM, you would install the following:
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install @llamaindex/openai
```
```shell tab="yarn"
yarn add @llamaindex/openai
```
```shell tab="pnpm"
pnpm add @llamaindex/openai
```
</Tabs>
```package-install
npm i @llamaindex/openai
```
Go to [LLM APIs](/docs/llamaindex/modules/models/llms) to find out how to use other LLMs.
@@ -3,8 +3,6 @@ title: With Node.js/Bun/Deno
description: In this guide, you'll learn how to use LlamaIndex with Node.js, Bun, and Deno.
---
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
## Adding environment variables
By default, LlamaIndex uses OpenAI provider, which requires an API key. You can set the `OPENAI_API_KEY` environment variable to authenticate with OpenAI.
@@ -28,19 +26,9 @@ For more information, see the [How to read environment variables from Node.js](h
By the default, we are using `js-tiktoken` for tokenization. You can install `gpt-tokenizer` which is then automatically used by LlamaIndex to get a 60x speedup for tokenization:
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install gpt-tokenizer
```
```shell tab="yarn"
yarn add gpt-tokenizer
```
```shell tab="pnpm"
pnpm add gpt-tokenizer
```
</Tabs>
```package-install
npm i gpt-tokenizer
```
**Note**: This only works for Node.js
@@ -45,7 +45,7 @@ We recommend using `bundler` or `nodenext`, but due to popularity of `node`, we
So you may encounter type errors when importing sub paths from the `llamaindex` package like:
```ts
import { Settings } from "llamaindex/Settings";
import { Settings } from "llamaindex";
```
The simplest way to fix this without changing `moduleResolution` is to import directly from `llamaindex`:
@@ -3,13 +3,6 @@ title: What is LlamaIndex.TS
description: LlamaIndex is the leading data framework for building LLM applications
---
import {
SiNodedotjs,
SiDeno,
SiBun,
SiCloudflareworkers,
} from "@icons-pack/react-simple-icons";
LlamaIndex is a framework for building context-augmented generative AI applications with LLMs including agents and workflows.
The TypeScript implementation is designed for JavaScript server side applications using <SiNodedotjs className="inline" color="#5FA04E" /> Node.js, <SiDeno className="inline" color="#70FFAF" /> Deno, <SiBun className="inline" /> Bun, <SiCloudflareworkers className="inline" color="#F38020" /> Cloudflare Workers, and more.
@@ -2,7 +2,6 @@
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.
@@ -10,19 +9,9 @@ Enhance your observability with Langtrace, a robust open-source tool supports Op
- 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>
```package-install
npm i @langtrase/typescript-sdk
```
## Initialize
@@ -2,27 +2,15 @@
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>
```package-install
npm i @traceloop/node-server-sdk
```
```js
import * as traceloop from "@traceloop/node-server-sdk";
@@ -11,8 +11,8 @@ LlamaIndex provides integration with Vercel's AI SDK, allowing you to create pow
First, install the required dependencies:
```bash
npm install @llamaindex/vercel ai
```package-install
npm i @llamaindex/vercel ai
```
## Using Vercel AI's Model Providers
@@ -2,8 +2,6 @@
title: Migrating from v0.8 to v0.9
---
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
Version 0.9 of LlamaIndex.TS introduces significant architectural changes to improve package size and runtime compatibility. The main goals of this release are:
1. Reduce the package size of the main `llamaindex` package by moving dependencies into provider packages, making it more suitable for serverless environments
@@ -33,19 +31,9 @@ import { OpenAI } from "@llamaindex/openai";
> Note: This examples requires installing the `@llamaindex/openai` package:
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install @llamaindex/openai
```
```shell tab="yarn"
yarn add @llamaindex/openai
```
```shell tab="pnpm"
pnpm add @llamaindex/openai
```
</Tabs>
```package-install
npm i @llamaindex/openai
```
For more details on available AI model providers and their configuration, see the [LLMs documentation](/docs/llamaindex/modules/models/llms) and the [Embedding Models documentation](/docs/llamaindex/modules/models/embeddings).
@@ -2,9 +2,6 @@
title: Workflows
---
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
import CodeSource from "!raw-loader!@/examples/workflow/joke.ts";
A `Workflow` in LlamaIndexTS 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 in LlamaIndexTS work by defining step functions that handle specific event types and emit new events.
@@ -13,27 +10,16 @@ When a step function is added to a workflow, you need to specify the input and o
You can create a `Workflow` to do anything! Build an agent, a RAG flow, an extraction flow, or anything else you want.
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>
```package-install
npm i @llamaindex/workflow
```
## Getting Started
As an illustrative example, let's consider a naive workflow where a joke is generated and then critiqued.
<DynamicCodeBlock lang="ts" code={CodeSource} />
<include cwd>../../examples/workflow/joke.ts</include>
There's a few moving pieces here, so let's go through this piece by piece.
@@ -3,10 +3,6 @@ title: Managed Index
description: Managed index using LlamaCloud
---
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
import CodeSource from "!raw-loader!@/examples/cloud/chat.ts";
import CodeSource2 from "!raw-loader!@/examples/cloud/from-documents.ts";
LlamaCloud is a new generation of managed parsing, ingestion, and retrieval services, designed to bring production-grade context-augmentation to your LLM and RAG applications.
LlamaCloud supports
@@ -22,13 +18,13 @@ Visit [LlamaCloud](https://cloud.llamaindex.ai) to sign in and get an API key.
Here's an example of how to create a managed index by ingesting a couple of documents:
<DynamicCodeBlock lang="ts" code={CodeSource2} />
<include cwd>../../examples/cloud/chat.ts</include>
## Use a Managed Index
Here's an example of how to use a managed index together with a chat engine:
<DynamicCodeBlock lang="ts" code={CodeSource} />
<include cwd>../../examples/cloud/from-documents.ts</include>
## API Reference
@@ -7,21 +7,9 @@ These `Transformations` are applied to your input data, and the resulting nodes
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai @llamaindex/qdrant
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai @llamaindex/qdrant
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai @llamaindex/qdrant
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai @llamaindex/qdrant
```
## Usage Pattern
@@ -2,8 +2,6 @@
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.tsx';
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
Node parsers are a simple abstraction that take a list of `Document` objects, 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](/docs/llamaindex/modules/data).
@@ -151,8 +149,6 @@ 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.
@@ -2,9 +2,6 @@
title: DiscordReader
---
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
import CodeSource from "!raw-loader!@/examples/readers/src/discord";
DiscordReader is a simple data loader that reads all messages in a given Discord channel and returns them as Document objects.
It uses the [@discordjs/rest](https://github.com/discordjs/discord.js/tree/main/packages/rest) library to fetch the messages.
@@ -15,7 +12,7 @@ In your Discord Application, go to the `OAuth2` tab and generate an invite URL b
This will invite the bot with the necessary permissions to read messages.
Copy the URL in your browser and select the server you want your bot to join.
<DynamicCodeBlock lang="ts" code={CodeSource} />
<include cwd>../../examples/readers/src/discord.ts</include>
### Params
@@ -3,12 +3,6 @@ title: Loading Data
description: Loading data using Readers into Documents
---
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
import CodeSource from "!raw-loader!@/examples/readers/src/simple-directory-reader";
import CodeSource2 from "!raw-loader!@/examples/readers/src/custom-simple-directory-reader";
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
Before you can start indexing your documents, you need to load them into memory.
A reader is a module that loads data from a file into a `Document` object.
@@ -19,20 +13,9 @@ To install readers call:
If you want to use the reader module, you need to install `@llamaindex/readers`
<Tabs groupId="install-llamaindex" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install @llamaindex/readers
```
```shell tab="yarn"
yarn add @llamaindex/readers
```
```shell tab="pnpm"
pnpm add @llamaindex/readers
```
</Tabs>
```package-install
npm i @llamaindex/readers
```
</Accordion>
</Accordions>
@@ -67,7 +50,7 @@ LlamaIndex.TS supports easy loading of files from folders using the `SimpleDirec
It is a simple reader that reads all files from a directory and its subdirectories and delegates the actual reading to the reader specified in the `fileExtToReader` map.
<DynamicCodeBlock lang="ts" code={CodeSource} />
<include cwd>../../examples/readers/src/simple-directory-reader.ts</include>
Currently, the following readers are mapped to specific file types:
@@ -89,7 +72,7 @@ SimpleDirectoryReader supports up to 9 concurrent requests. Use the `numWorkers`
### Example
<DynamicCodeBlock lang="ts" code={CodeSource2} />
<include cwd>../../examples/readers/src/custom-simple-directory-reader.ts</include>
## Tips when using in non-Node.js environments
@@ -8,21 +8,9 @@ Supports streaming of large JSON data using [@discoveryjs/json-ext](https://gith
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/readers
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/readers
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/readers
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/readers
```
## Usage
@@ -6,21 +6,9 @@ LlamaParse `json` mode supports extracting any images found in a page object by
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/cloud @llamaindex/openai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/cloud @llamaindex/openai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/cloud @llamaindex/openai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/cloud @llamaindex/openai
```
## Usage
@@ -2,10 +2,6 @@
title: LlamaParse
---
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
import CodeSource from "!raw-loader!@/examples/readers/src/llamaparse";
import CodeSource2 from "!raw-loader!@/examples/readers/src/simple-directory-reader-with-llamaparse.ts";
LlamaParse is an API created by LlamaIndex to efficiently parse files, e.g. it's great at converting PDF tables into markdown.
To use it, first login and get an API key from https://cloud.llamaindex.ai. Make sure to store the key as `apiKey` parameter or in the environment variable `LLAMA_CLOUD_API_KEY`.
@@ -17,7 +13,7 @@ Official documentation for LlamaParse can be found [here](https://docs.cloud.lla
You can then use the `LlamaParseReader` class to load local files and convert them into a parsed document that can be used by LlamaIndex.
See [reader.ts](https://github.com/run-llama/LlamaIndexTS/blob/main/packages/cloud/src/reader.ts) for a list of supported file types:
<DynamicCodeBlock lang="ts" code={CodeSource} />
<include cwd>../../examples/readers/src/llamaparse.ts</include>
### Params
@@ -60,7 +56,7 @@ They can be divided into two groups.
Below a full example of `LlamaParse` integrated in `SimpleDirectoryReader` with additional options.
<DynamicCodeBlock lang="ts" code={CodeSource2} />
<include cwd>../../examples/readers/src/simple-directory-reader-with-llamaparse.ts</include>
## API Reference
@@ -6,21 +6,9 @@ In JSON mode, LlamaParse will return a data structure representing the parsed ob
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/cloud
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/cloud
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/cloud
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/cloud
```
## Usage
@@ -13,21 +13,9 @@ Check the [LlamaIndexTS Github](https://github.com/run-llama/LlamaIndexTS) for t
## Using PostgreSQL as Document Store
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/postgres
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/postgres
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/postgres
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/postgres
```
You can configure the `schemaName`, `tableName`, `namespace`, and
`connectionString`. If a `connectionString` is not
@@ -13,21 +13,9 @@ Check the [LlamaIndexTS Github](https://github.com/run-llama/LlamaIndexTS) for t
## Using PostgreSQL as Index Store
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/postgres
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/postgres
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/postgres
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/postgres
```
You can configure the `schemaName`, `tableName`, `namespace`, and
`connectionString`. If a `connectionString` is not
@@ -13,21 +13,9 @@ docker run -p 6333:6333 qdrant/qdrant
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/qdrant
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/qdrant
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/qdrant
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/qdrant
```
## Importing the modules
@@ -8,21 +8,9 @@ To use this vector store, you need a Supabase project. You can create one at [su
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/supabase
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/supabase
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/supabase
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/supabase
```
## Database Setup
@@ -10,21 +10,9 @@ This is useful for measuring if the response was correct. The evaluator returns
Firstly, you need to install the package:
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai
```
Set the OpenAI API key:
@@ -12,22 +12,9 @@ This is useful for measuring if the response was hallucinated. The evaluator ret
Firstly, you need to install the package:
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai
```
Set the OpenAI API key:
@@ -10,22 +10,9 @@ It is useful for measuring if the response was relevant to the query. The evalua
Firstly, you need to install the package:
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai
```
Set the OpenAI API key:
@@ -7,21 +7,9 @@ Check out available embedding models [here](https://deepinfra.com/models/embeddi
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/deepinfra
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/deepinfra
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/deepinfra
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/deepinfra
```
```ts
import { Document, Settings, VectorStoreIndex } from "llamaindex";
@@ -6,21 +6,9 @@ To use Gemini embeddings, you need to import `GeminiEmbedding` from `@llamaindex
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/google
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/google
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/google
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/google
```
```ts
import { Document, Settings, VectorStoreIndex } from "llamaindex";
@@ -6,21 +6,9 @@ To use HuggingFace embeddings, you need to import `HuggingFaceEmbedding` from `@
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/huggingface
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/huggingface
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/huggingface
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/huggingface
```
```ts
import { Document, Settings, VectorStoreIndex } from "llamaindex";
@@ -8,21 +8,9 @@ This can be explicitly updated through `Settings.embedModel`.
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai
```
```typescript
import { OpenAIEmbedding } from "@llamaindex/openai";
@@ -6,21 +6,9 @@ To use MistralAI embeddings, you need to import `MistralAIEmbedding` from `@llam
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/mistral
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/mistral
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/mistral
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/mistral
```
```ts
import { Document, Settings, VectorStoreIndex } from "llamaindex";
@@ -14,22 +14,9 @@ To find out more about the latest features, updates, and available models, visit
## Setup
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/mixedbread
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/mixedbread
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/mixedbread
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/mixedbread
```
Next, sign up for an API key at [mixedbread.ai](https://mixedbread.ai/). Once you have your API key, you can import the necessary modules and create a new instance of the `MixedbreadAIEmbeddings` class.
@@ -14,21 +14,9 @@ ollama pull nomic-embed-text
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/ollama
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/ollama
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/ollama
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/ollama
```
```ts
import { OllamaEmbedding } from "@llamaindex/ollama";
@@ -6,21 +6,9 @@ To use OpenAI embeddings, you need to import `OpenAIEmbedding` from `@llamaindex
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai
```
```ts
import { OpenAIEmbedding } from "@llamaindex/openai";
@@ -6,21 +6,9 @@ To use VoyageAI embeddings, you need to import `VoyageAIEmbedding` from `@llamai
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/voyage-ai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/voyage-ai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/voyage-ai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/voyage-ai
```
```ts
import { VoyageAIEmbedding } from "@llamaindex/voyage-ai";
@@ -4,21 +4,9 @@ title: Anthropic
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/anthropic
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/anthropic
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/anthropic
```
</Tabs>
```shell tab="npm"
npm i llamaindex @llamaindex/anthropic
```
## Usage
@@ -16,21 +16,9 @@ export AZURE_OPENAI_DEPLOYMENT="gpt-4" # or some other deployment name
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai
```
## Usage
@@ -4,21 +4,9 @@ title: Bedrock
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/community
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/community
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/community
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/community
```
## Usage
@@ -57,6 +45,7 @@ META_LLAMA3_2_1B_INSTRUCT = "meta.llama3-2-1b-instruct-v1:0"; // only available
META_LLAMA3_2_3B_INSTRUCT = "meta.llama3-2-3b-instruct-v1:0"; // only available via inference endpoints (see below)
META_LLAMA3_2_11B_INSTRUCT = "meta.llama3-2-11b-instruct-v1:0"; // only available via inference endpoints (see below), multimodal and function call supported
META_LLAMA3_2_90B_INSTRUCT = "meta.llama3-2-90b-instruct-v1:0"; // only available via inference endpoints (see below), multimodal and function call supported
AMAZON_NOVA_PREMIER_1 = "amazon.nova-premier-v1:0";
AMAZON_NOVA_PRO_1 = "amazon.nova-pro-v1:0";
AMAZON_NOVA_LITE_1 = "amazon.nova-lite-v1:0";
AMAZON_NOVA_MICRO_1 = "amazon.nova-micro-v1:0";
@@ -76,6 +65,7 @@ US_META_LLAMA_3_2_1B_INSTRUCT = "us.meta.llama3-2-1b-instruct-v1:0";
US_META_LLAMA_3_2_3B_INSTRUCT = "us.meta.llama3-2-3b-instruct-v1:0";
US_META_LLAMA_3_2_11B_INSTRUCT = "us.meta.llama3-2-11b-instruct-v1:0";
US_META_LLAMA_3_2_90B_INSTRUCT = "us.meta.llama3-2-90b-instruct-v1:0";
US_AMAZON_NOVA_PRO_1 = "us.amazon.nova-premier-v1:0";
US_AMAZON_NOVA_PRO_1 = "us.amazon.nova-pro-v1:0";
US_AMAZON_NOVA_LITE_1 = "us.amazon.nova-lite-v1:0";
US_AMAZON_NOVA_MICRO_1 = "us.amazon.nova-micro-v1:0";
@@ -86,6 +76,10 @@ EU_ANTHROPIC_CLAUDE_3_SONNET = "eu.anthropic.claude-3-sonnet-20240229-v1:0";
EU_ANTHROPIC_CLAUDE_3_5_SONNET = "eu.anthropic.claude-3-5-sonnet-20240620-v1:0";
EU_META_LLAMA_3_2_1B_INSTRUCT = "eu.meta.llama3-2-1b-instruct-v1:0";
EU_META_LLAMA_3_2_3B_INSTRUCT = "eu.meta.llama3-2-3b-instruct-v1:0";
EU_AMAZON_NOVA_PRO_1 = "eu.amazon.nova-premier-v1:0";
EU_AMAZON_NOVA_PRO_1 = "eu.amazon.nova-pro-v1:0";
EU_AMAZON_NOVA_LITE_1 = "eu.amazon.nova-lite-v1:0";
EU_AMAZON_NOVA_MICRO_1 = "eu.amazon.nova-micro-v1:0";
```
Sonnet, Haiku and Opus are multimodal, image_url only supports base64 data url format, e.g. `data:image/jpeg;base64,SGVsbG8sIFdvcmxkIQ==`
@@ -6,21 +6,9 @@ Check out available LLMs [here](https://deepinfra.com/models/text-generation).
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/deepinfra
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/deepinfra
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/deepinfra
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/deepinfra
```
```ts
import { DeepInfra } from "@llamaindex/deepinfra";
@@ -4,21 +4,9 @@ title: Gemini
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/google
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/google
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/google
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/google
```
## Usage
@@ -69,7 +57,7 @@ const gemini = new Gemini({
To authenticate for local development:
```bash
npm install @google-cloud/vertexai
npm i @google-cloud/vertexai
gcloud auth application-default login
```
@@ -2,26 +2,11 @@
title: Groq
---
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
import CodeSource from "!raw-loader!@/examples/groq.ts";
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/groq
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/groq
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/groq
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/groq
```
## Usage
@@ -70,7 +55,7 @@ const results = await queryEngine.query({
## Full Example
<DynamicCodeBlock lang="ts" code={CodeSource} />
<include cwd>../../examples/groq.ts</include>
## API Reference
@@ -8,21 +8,9 @@ The LLM can be explicitly updated through `Settings`.
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai
```
```typescript
import { OpenAI } from "@llamaindex/openai";
@@ -4,21 +4,9 @@ title: LLama2
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/replicate
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/replicate
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/replicate
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/replicate
```
## Usage
@@ -4,21 +4,9 @@ title: Mistral
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/mistral
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/mistral
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/mistral
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/mistral
```
## Usage
@@ -4,22 +4,9 @@ title: Ollama
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/ollama
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/ollama
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/ollama
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/ollama
```
## Usage
@@ -4,22 +4,9 @@ title: OpenAI
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai
```
```ts
import { OpenAI } from "@llamaindex/openai";
@@ -4,21 +4,9 @@ title: Perplexity LLM
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install @llamaindex/perplexity
```
```shell tab="yarn"
yarn add @llamaindex/perplexity
```
```shell tab="pnpm"
pnpm add @llamaindex/perplexity
```
</Tabs>
```package-install
npm i @llamaindex/perplexity
```
## Usage
@@ -4,22 +4,9 @@ title: Portkey LLM
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/portkey-ai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/portkey-ai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/portkey-ai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/portkey-ai
```
## Usage
@@ -4,21 +4,9 @@ title: Together LLM
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install @llamaindex/together
```
```shell tab="yarn"
yarn add @llamaindex/together
```
```shell tab="pnpm"
pnpm add @llamaindex/together
```
</Tabs>
```package-install
npm i @llamaindex/together
```
## Usage
@@ -41,5 +41,5 @@ for await (const chunk of stream) {
## Api References
- [ContextChatEngine](/docs/api/classes/ContextChatEngine)
- [CondenseQuestionChatEngine](/docs/api/classes/ContextChatEngine)
- [CondenseQuestionChatEngine](/docs/api/classes/CondenseQuestionChatEngine)
- [SimpleChatEngine](/docs/api/classes/SimpleChatEngine)
@@ -8,21 +8,9 @@ The Cohere Reranker is a postprocessor that uses the Cohere API to rerank the re
Firstly, you will need to install the `llamaindex` package.
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/cohere @llamaindex/openai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/cohere @llamaindex/openai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/cohere @llamaindex/openai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/cohere @llamaindex/openai
```
Now, you will need to sign up for an API key at [Cohere](https://cohere.ai/). Once you have your API key you can import the necessary modules and create a new instance of the `CohereRerank` class.
@@ -4,21 +4,9 @@ title: Node Postprocessors
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/cohere @llamaindex/openai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/cohere @llamaindex/openai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/cohere @llamaindex/openai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/cohere @llamaindex/openai
```
## Concept
@@ -8,22 +8,9 @@ The Jina AI Reranker is a postprocessor that uses the Jina AI Reranker API to re
Firstly, you will need to install the `llamaindex` package.
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai
```
Now, you will need to sign up for an API key at [Jina AI](https://jina.ai/reranker). Once you have your API key you can import the necessary modules and create a new instance of the `JinaAIReranker` class.
@@ -17,22 +17,9 @@ To find out more about the latest features and updates, visit the [mixedbread.ai
First, you will need to install the `llamaindex` package.
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai @llamaindex/mixedbread
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai @llamaindex/mixedbread
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai @llamaindex/mixedbread
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai @llamaindex/mixedbread
```
Next, sign up for an API key at [mixedbread.ai](https://mixedbread.ai/). Once you have your API key, you can import the necessary modules and create a new instance of the `MixedbreadAIReranker` class.
@@ -10,21 +10,9 @@ You can also check our multi-tenancy blog post to see how metadata filtering can
Firstly if you haven't already, you need to install the `llamaindex` package:
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai @llamaindex/chroma
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai @llamaindex/chroma
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai @llamaindex/chroma
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai @llamaindex/chroma
```
Then you can import the necessary modules from `llamaindex`:
@@ -8,21 +8,9 @@ In this tutorial, we define a custom router query engine that selects one out of
First, we need to install import the necessary modules from `llamaindex`:
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai @llamaindex/readers
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai @llamaindex/readers
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai @llamaindex/readers
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai @llamaindex/readers
```
```ts
import {
@@ -2,7 +2,6 @@
title: Using API Route
description: Chat interface for your LlamaIndexTS application using API Route
---
import { ChatDemo } from '../../../../../components/demo/chat/api/demo';
Using [chat-ui](https://github.com/run-llama/chat-ui), it's easy to add a chat interface to your LlamaIndexTS application.
You just need to create an API route that provides an `api/chat` endpoint and a chat component to consume the API.
@@ -16,7 +16,7 @@ npx shadcn@latest add https://ui.llamaindex.ai/r/chat.json
To install the package, run the following command in your project directory:
```sh
npm install @llamaindex/chat-ui
npm i @llamaindex/chat-ui
```
For more information, check out the [github.comrun-llama/chat-ui](https://github.com/run-llama/chat-ui)
@@ -0,0 +1,153 @@
---
title: Using LlamaIndex Server
description: Running LlamaIndex workflows with both API endpoints and a user interface for interaction
---
# LlamaIndex Server
LlamaIndexServer is a Next.js-based application that allows you to quickly launch your [LlamaIndex Workflows](https://ts.llamaindex.ai/docs/llamaindex/modules/agents/workflows) and [Agent Workflows](https://ts.llamaindex.ai/docs/llamaindex/modules/agents/agent_workflow) as an API server with an optional chat UI. It provides a complete environment for running LlamaIndex workflows with both API endpoints and a user interface for interaction.
## Features
- Serving a workflow as a chatbot
- Built on Next.js for high performance and easy API development
- Optional built-in chat UI with extendable UI components
- Prebuilt development code
## Installation
```package-install
npm i @llamaindex/server
```
## Quick Start
Create index.ts file and add the following code:
```ts
import { LlamaIndexServer } from "@llamaindex/server";
import { wiki } from "@llamaindex/tools"; // or any other tool
const createWorkflow = () => agent({ tools: [wiki()] })
new LlamaIndexServer({
workflow: createWorkflow,
uiConfig: {
appTitle: "LlamaIndex App",
starterQuestions: ["Who is the first president of the United States?"],
},
}).start();
```
## Running the Server
In the same directory as `index.ts`, run the following command to start the server:
```bash
tsx index.ts
```
The server will start at `http://localhost:3000`
You can also make a request to the server:
```bash
curl -X POST "http://localhost:3000/api/chat" -H "Content-Type: application/json" -d '{"message": "Who is the first president of the United States?"}'
```
## Configuration Options
The LlamaIndexServer accepts the following configuration
- `workflow`: A callable function that creates a workflow instance for each request
- `uiConfig`: An object to configure the chat UI containing the following properties:
- `appTitle`: The title of the application (default: `"LlamaIndex App"`)
- `starterQuestions`: List of starter questions for the chat UI (default: `[]`)
- `componentsDir`: The directory for custom UI components rendering events emitted by the workflow. The default is undefined, which does not render custom UI components.
- `llamaCloudIndexSelector`: Whether to show the LlamaCloud index selector in the chat UI (requires `LLAMA_CLOUD_API_KEY` to be set in the environment variables) (default: `false`)
LlamaIndexServer accepts all the configuration options from Nextjs Custom Server such as `port`, `hostname`, `dev`, etc.
See all Nextjs Custom Server options [here](https://nextjs.org/docs/app/building-your-application/configuring/custom-server).
## Default Endpoints and Features
### Chat Endpoint
The server includes a default chat endpoint at `/api/chat` for handling chat interactions.
### Chat UI
The server always provides a chat interface at the root path (`/`) with:
- Configurable starter questions
- Real-time chat interface
- API endpoint integration
### Static File Serving
- The server automatically mounts the `data` and `output` folders at `{server_url}{api_prefix}/files/data` (default: `/api/files/data`) and `{server_url}{api_prefix}/files/output` (default: `/api/files/output`) respectively.
- Your workflows can use both folders to store and access files. As a convention, the `data` folder is used for documents that are ingested and the `output` folder is used for documents that are generated by the workflow.
## Custom UI Components
The LlamaIndex server provides support for rendering workflow events using custom UI components, allowing you to extend and customize the chat interface.
### Overview
Custom UI components are a powerful feature that enables you to:
- Add custom interface elements to the chat UI using React JSX or TSX files
- Extend the default chat interface functionality
- Create specialized visualizations or interactions
### Configuration
Your workflow must emit events that fit this structure, allowing the LlamaIndex server to display the right UI components based on the event type.
```json
{
"type": "<event_name>",
"data": <data model>
}
```
### Server Setup
1. Initialize the LlamaIndex server with a component directory:
```ts
new LlamaIndexServer({
workflow: createWorkflow,
uiConfig: {
appTitle: "LlamaIndex App",
componentsDir: "components",
},
}).start();
```
2. Add the custom component code to the directory following the naming pattern:
- File Extension: `.jsx` and `.tsx` for React components
- File Name: Should match the event type from your workflow (e.g., `deep_research_event.jsx` for handling `deep_research_event` type that you defined in your workflow). If there are TSX and JSX files with the same name, the TSX file will be used.
- Component Name: Export a default React component named `Component` that receives props from the event data
Example component structure:
```jsx
function Component({ events }) {
// Your component logic here
return (
// Your UI code here
);
}
```
## Best Practices
1. Always provide a workflow factory that creates fresh workflow instances
2. Use environment variables for sensitive configuration
3. Use starter questions to guide users in the chat UI
## Getting Started with a New Project
Want to start a new project with LlamaIndexServer? Check out our [create-llama](https://github.com/run-llama/create-llama) tool to quickly generate a new project with LlamaIndexServer.
@@ -2,5 +2,5 @@
"title": "Chat UI",
"description": "Use chat-ui to add a chat interface to your LlamaIndexTS application.",
"defaultOpen": false,
"pages": ["install", "chat", "rsc"]
"pages": ["install", "chat", "rsc", "llamaindex-server"]
}
@@ -2,7 +2,6 @@
title: Using Next.js RSC
description: Chat interface for your LlamaIndexTS application using Next.js RSC
---
import { ChatDemoRSC } from '../../../../../components/demo/chat/rsc/demo';
Using [chat-ui](https://github.com/run-llama/chat-ui), it's easy to add a chat interface to your LlamaIndexTS application using [Next.js RSC](https://nextjs.org/docs/app/building-your-application/rendering/server-components) and [Vercel AI RSC](https://sdk.vercel.ai/docs/ai-sdk-rsc/overview).
@@ -3,13 +3,6 @@ title: More
description: More
---
import {
SiGithub,
SiNpm,
SiX,
SiDiscord,
} from "@icons-pack/react-simple-icons";
## 🗺️ Ecosystem
To download or contribute, find LlamaIndex on:
@@ -8,14 +8,14 @@ In this guide we'll walk you through the process of building an Agent in JavaScr
In LlamaIndex, an agent is a semi-autonomous piece of software powered by an LLM that is given a task and executes a series of steps towards solving that task. It is given a set of tools, which can be anything from arbitrary functions up to full LlamaIndex query engines, and it selects the best available tool to complete each step. When each step is completed, the agent judges whether the task is now complete, in which case it returns a result to the user, or whether it needs to take another step, in which case it loops back to the start.
![agent flow](./images/agent_flow.png)
![agent flow](/images/agent_flow.png)
## Install LlamaIndex.TS
You'll need to have a recent version of [Node.js](https://nodejs.org/en) installed. Then you can install LlamaIndex.TS by running
```bash
npm install llamaindex @llamaindex/openai @llamaindex/readers @llamaindex/huggingface
```package-install
npm i llamaindex @llamaindex/openai @llamaindex/readers @llamaindex/huggingface
```
## Choose your model
@@ -33,7 +33,7 @@ OPENAI_API_KEY=sk-XXXXXXXXXXXXXXXXXXXXXXXX
We'll use `dotenv` to pull the API key out of that .env file, so also run:
```bash
npm install dotenv
npm i dotenv
```
Now you're ready to [create your agent](2_create_agent).
@@ -15,22 +15,9 @@ We're going to start with the same agent we [built in step 1](https://github.com
## Installation
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install llamaindex @llamaindex/openai @llamaindex/huggingface
```
```shell tab="yarn"
yarn add llamaindex @llamaindex/openai @llamaindex/huggingface
```
```shell tab="pnpm"
pnpm add llamaindex @llamaindex/openai @llamaindex/huggingface
```
</Tabs>
```package-install
npm i llamaindex @llamaindex/openai @llamaindex/huggingface
```
### New dependencies
@@ -2,9 +2,6 @@
title: Basic Agent
---
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
import CodeSource from "!raw-loader!@/examples/agent/openai";
We have a comprehensive, step-by-step [guide to building agents in LlamaIndex.TS](/docs/llamaindex/tutorials/agents/1_setup) that we recommend to learn what agents are and how to build them for production. But building a basic agent is simple:
## Set up
@@ -13,7 +10,7 @@ In a new folder:
```bash npm2yarn
npm init
npm install -D typescript @types/node
npm i -D typescript @types/node
```
## Run agent
@@ -27,7 +24,7 @@ Create the file `example.ts`. This code will:
- Give an example of the data structure we wish to generate
- Prompt the LLM with instructions and the example, plus a sample transcript
<DynamicCodeBlock lang="ts" code={CodeSource} />
<include cwd>../../examples/agent/openai.ts</include>
To run the code:
@@ -2,8 +2,6 @@
title: Local LLMs
---
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
LlamaIndex.TS supports OpenAI and [other remote LLM APIs](/docs/llamaindex/modules/models/llms). You can also run a local LLM on your machine!
## Using a local model via Ollama
@@ -28,19 +26,9 @@ The first time you run it will also automatically download and install the model
To switch the LLM in your code, you first need to make sure to install the package for the Ollama model provider:
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install @llamaindex/ollama
```
```shell tab="yarn"
yarn add @llamaindex/ollama
```
```shell tab="pnpm"
pnpm add @llamaindex/ollama
```
</Tabs>
```package-install
npm i @llamaindex/ollama
```
Then, to tell LlamaIndex to use a local LLM, use the `Settings` object:
@@ -59,19 +47,9 @@ If you're doing retrieval-augmented generation, LlamaIndex.TS will also call out
First install the Huggingface model provider package:
<Tabs groupId="install" items={["npm", "yarn", "pnpm"]} persist>
```shell tab="npm"
npm install @llamaindex/huggingface
```
```shell tab="yarn"
yarn add @llamaindex/huggingface
```
```shell tab="pnpm"
pnpm add @llamaindex/huggingface
```
</Tabs>
```package-install
npm i @llamaindex/huggingface
```
And then set the embedding model in your code:
@@ -2,10 +2,6 @@
title: Retrieval Augmented Generation (RAG)
---
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
import CodeSource from "!raw-loader!@/examples/vectorIndex";
import TSConfigSource from "!!raw-loader!@/examples/tsconfig.json";
One of the most common use-cases for LlamaIndex is Retrieval-Augmented Generation or RAG, in which your data is indexed and selectively retrieved to be given to an LLM as source material for responding to a query. You can learn more about the [concepts behind RAG](/docs/llamaindex/tutorials/rag/concepts).
## Set up the project
@@ -14,7 +10,7 @@ In a new folder, run:
```bash npm2yarn
npm init
npm install -D typescript @types/node
npm i -D typescript @types/node
```
Then, check out the [installation](/docs/llamaindex/getting_started/installation) steps to install LlamaIndex.TS and prepare an OpenAI key.
@@ -30,11 +26,11 @@ Create the file `example.ts`. This code will
- index it (which creates embeddings using OpenAI)
- create a query engine to answer questions about the data
<DynamicCodeBlock lang="ts" code={CodeSource} />
<include cwd>../../examples/vectorIndex.ts</include>
Create a `tsconfig.json` file in the same folder:
<DynamicCodeBlock lang="json" code={TSConfigSource} />
<include cwd>../../examples/tsconfig.json</include>
Now you can run the code with
@@ -2,9 +2,6 @@
title: Structured data extraction
---
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
import CodeSource from "!raw-loader!@/examples/jsonExtract";
Make sure you have installed LlamaIndex.TS and have an OpenAI key. If you haven't, check out the [installation](/docs/llamaindex/getting_started/installation) guide.
You can use [other LLMs](/docs/llamaindex/modules/models/llms) via their APIs; if you would prefer to use local models check out our [local LLM example](/docs/llamaindex/tutorials/local_llm).
@@ -15,7 +12,7 @@ In a new folder:
```bash npm2yarn
npm init
npm install -D typescript @types/node
npm i -D typescript @types/node
```
## Extract data
@@ -26,7 +23,7 @@ Create the file `example.ts`. This code will:
- Give an example of the data structure we wish to generate
- Prompt the LLM with instructions and the example, plus a sample transcript
<DynamicCodeBlock lang="ts" code={CodeSource} />
<include cwd>../../examples/jsonExtract.ts</include>
To run the code:
@@ -0,0 +1,530 @@
---
title: Advanced Event Handling
description: Master complex event patterns and middleware with Workflows
---
This guide explores advanced event handling techniques and patterns you can use with Workflows to build more sophisticated patterns.
## Event Composition
Workflows allow you to work with different event types and compose them in powerful ways:
### Multiple Event Types
You can define multiple event types for different kinds of data flowing through your workflow:
```ts
import { createWorkflow, workflowEvent } from "llamaindex";
// Define different event types
const textEvent = workflowEvent<string>();
const numberEvent = workflowEvent<number>();
const booleanEvent = workflowEvent<boolean>();
const complexEvent = workflowEvent<{ id: string; value: number }>();
// Create a workflow that can process different event types
const workflow = createWorkflow();
// Handle text events
workflow.handle([textEvent], (event) => {
console.log(`Processing text: ${event.data}`);
return numberEvent.with(event.data.length);
});
// Handle number events
workflow.handle([numberEvent], (event) => {
const isEven = event.data % 2 === 0;
console.log(`Number ${event.data} is ${isEven ? 'even' : 'odd'}`);
return booleanEvent.with(isEven);
});
// Handle boolean events
workflow.handle([booleanEvent], (event) => {
return complexEvent.with({
id: crypto.randomUUID(),
value: event.data ? 100 : 0
});
});
```
### Event Branching and Merging
You can create complex event flows with branching and merging patterns:
```ts
import { createWorkflow, workflowEvent, until, collect } from "llamaindex";
// Define events for a data processing pipeline
const inputEvent = workflowEvent<string>();
const validateEvent = workflowEvent<string>();
const processEvent = workflowEvent<string>();
const errorEvent = workflowEvent<Error>();
const resultEvent = workflowEvent<string>();
const completeEvent = workflowEvent<string[]>();
// Create workflow
const workflow = createWorkflow();
// Branch based on input validation
workflow.handle([inputEvent], (event) => {
if (event.data && event.data.trim().length > 0) {
return validateEvent.with(event.data.trim());
} else {
return errorEvent.with(new Error("Empty input"));
}
});
// Process valid inputs
workflow.handle([validateEvent], (event) => {
return processEvent.with(event.data.toUpperCase());
});
// Handle processing
workflow.handle([processEvent], (event) => {
return resultEvent.with(`Processed: ${event.data}`);
});
// Handle errors
workflow.handle([errorEvent], (event) => {
return resultEvent.with(`Error: ${event.data.message}`);
});
// Merge results: collect multiple results into a single completion event
workflow.handle([inputEvent], (start) => {
const { sendEvent, stream } = getContext();
// Process all inputs
const inputs = start.data.split(',').map(s => s.trim());
inputs.forEach(input => sendEvent(inputEvent.with(input)));
// Collect all results
const results = await collect(
until(stream, result => resultEvent.include(result))
.filter(ev => resultEvent.include(ev))
.take(inputs.length)
);
return completeEvent.with(results.map(r => r.data));
});
```
## Event Filtering and Transformation
You can filter and transform events to build sophisticated data processing pipelines:
```ts
import { createWorkflow, workflowEvent } from "llamaindex";
// Define events
const dataEvent = workflowEvent<number>();
const evenEvent = workflowEvent<number>();
const oddEvent = workflowEvent<number>();
const transformedEvent = workflowEvent<string>();
const resultEvent = workflowEvent<string[]>();
// Create workflow
const workflow = createWorkflow();
// Filter even numbers
workflow.handle([dataEvent], (event) => {
if (event.data % 2 === 0) {
return evenEvent.with(event.data);
} else {
return oddEvent.with(event.data);
}
});
// Transform even numbers
workflow.handle([evenEvent], (event) => {
return transformedEvent.with(`Even: ${event.data}`);
});
// Transform odd numbers
workflow.handle([oddEvent], (event) => {
return transformedEvent.with(`Odd: ${event.data}`);
});
// Collect and organize results
workflow.handle([dataEvent], (start) => {
const { sendEvent, stream } = getContext();
// Generate a sequence of numbers
for (let i = 1; i <= 10; i++) {
sendEvent(dataEvent.with(i));
}
// Collect transformed events
const results = await collect(
until(stream)
.filter(ev => transformedEvent.include(ev))
.take(10)
);
return resultEvent.with(results.map(r => r.data));
});
```
## Working with `withTraceEvents` Middleware
The `withTraceEvents` middleware adds powerful tracing capabilities to your workflows:
```ts
import {
createWorkflow,
workflowEvent,
withTraceEvents,
runOnce,
createHandlerDecorator
} from "llamaindex";
// Define events
const startEvent = workflowEvent<string>();
const processEvent = workflowEvent<string>();
const resultEvent = workflowEvent<string>();
// Create workflow with tracing
const workflow = withTraceEvents(createWorkflow());
// Create a custom handler decorator that logs execution time
const measureTime = createHandlerDecorator({
debugLabel: "measureTime",
getInitialValue: () => performance.now(),
onBeforeHandler: (handler, context, startTime) => {
console.log(`Starting handler execution at ${new Date().toISOString()}`);
return handler;
},
onAfterHandler: (result, context, startTime) => {
const duration = performance.now() - startTime;
console.log(`Handler executed in ${duration.toFixed(2)}ms`);
return startTime; // Return the initial value for next execution
}
});
// Run a specific handler only once
workflow.handle(
[startEvent],
runOnce((event) => {
console.log("This handler will only run once per workflow context");
return processEvent.with(event.data);
})
);
// Measure the execution time of this handler
workflow.handle(
[processEvent],
measureTime((event) => {
// Simulate processing time
const start = Date.now();
while (Date.now() - start < 100) {
// Busy wait for 100ms
}
return resultEvent.with(`Processed: ${event.data}`);
})
);
```
### Debugging with Substreams
You can use the `substream` feature to debug specific event flows:
```ts
import { createWorkflow, workflowEvent, withTraceEvents } from "llamaindex";
// Define events
const queryEvent = workflowEvent<string>();
const fetchEvent = workflowEvent<string>();
const resultEvent = workflowEvent<string>();
// Create workflow with tracing
const workflow = withTraceEvents(createWorkflow());
// Query handler
workflow.handle([queryEvent], (event) => {
const { sendEvent, stream } = getContext();
// Create a specific fetch event for this query
const fetchInstance = fetchEvent.with(event.data);
sendEvent(fetchInstance);
// Create a substream to only track events related to this fetch
const substream = workflow.substream(fetchInstance, stream);
// Listen for results in the substream
(async () => {
for await (const event of substream) {
console.log(`Event in substream: ${event.type}`);
}
})();
return resultEvent.with(`Querying: ${event.data}`);
});
// Fetch handler
workflow.handle([fetchEvent], (event) => {
console.log(`Fetching data for: ${event.data}`);
// Actual fetch logic would go here
return resultEvent.with(`Results for: ${event.data}`);
});
```
## Advanced Validation and Type Safety
The `withValidation` middleware ensures your workflow connections are both type-safe and runtime-safe:
```ts
import { createWorkflow, workflowEvent, withValidation } from "llamaindex";
// Define events with explicit types
const inputEvent = workflowEvent<string, "input">();
const validateEvent = workflowEvent<string, "validate">();
const processEvent = workflowEvent<string, "process">();
const resultEvent = workflowEvent<string, "result">();
const errorEvent = workflowEvent<Error, "error">({
debugLabel: "errorEvent" // Add debug labels for better error messages
});
// Define the allowed event flow paths
const workflow = withValidation(
createWorkflow(),
[
[[inputEvent], [validateEvent, errorEvent]], // inputEvent can lead to validateEvent or errorEvent
[[validateEvent], [processEvent, errorEvent]], // validateEvent can lead to processEvent or errorEvent
[[processEvent], [resultEvent, errorEvent]], // processEvent can lead to resultEvent or errorEvent
[[errorEvent], [resultEvent]] // errorEvent can lead to resultEvent
]
);
// Now use strictHandle to get compile-time validation
workflow.strictHandle([inputEvent], (sendEvent, event) => {
try {
if (!event.data || event.data.trim().length === 0) {
throw new Error("Empty input");
}
// This is allowed by our validation rules
sendEvent(validateEvent.with(event.data.trim()));
// This would cause a compile-time error:
// sendEvent(resultEvent.with("Result")); // ❌ Not allowed by validation rules
} catch (err) {
// This is allowed by our validation rules
sendEvent(errorEvent.with(err instanceof Error ? err : new Error(String(err))));
}
});
// The rest of the workflow with strict validation
workflow.strictHandle([validateEvent], (sendEvent, event) => {
// Validation logic here
sendEvent(processEvent.with(event.data));
});
workflow.strictHandle([processEvent], (sendEvent, event) => {
// Processing logic here
sendEvent(resultEvent.with(`Processed: ${event.data}`));
});
workflow.strictHandle([errorEvent], (sendEvent, event) => {
// Error handling logic here
sendEvent(resultEvent.with(`Error handled: ${event.data.message}`));
});
```
## Creating Custom Middleware
You can create your own middleware to extend the workflow capabilities:
```ts
import { createWorkflow, workflowEvent } from "llamaindex";
// Create a logging middleware
function withLogging(workflow) {
const originalHandle = workflow.handle;
workflow.handle = function(eventTypes, handler) {
return originalHandle.call(workflow, eventTypes, async function(...args) {
const eventType = eventTypes.map(e => e.name || 'AnonymousEvent').join(',');
console.log(`[${new Date().toISOString()}] Handling ${eventType}`);
try {
const result = await handler(...args);
console.log(`[${new Date().toISOString()}] Completed ${eventType}`);
return result;
} catch (error) {
console.error(`[${new Date().toISOString()}] Error in ${eventType}:`, error);
throw error;
}
});
};
return workflow;
}
// Create a retry middleware
function withRetry(maxRetries = 3, workflow) {
const originalHandle = workflow.handle;
workflow.handle = function(eventTypes, handler) {
return originalHandle.call(workflow, eventTypes, async function(...args) {
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await handler(...args);
} catch (error) {
lastError = error;
console.warn(`Attempt ${attempt}/${maxRetries} failed:`, error);
if (attempt < maxRetries) {
// Exponential backoff
await new Promise(resolve =>
setTimeout(resolve, Math.pow(2, attempt - 1) * 100)
);
}
}
}
throw lastError;
});
};
return workflow;
}
// Use the custom middleware
const workflow = withRetry(3, withLogging(createWorkflow()));
// Define events
const startEvent = workflowEvent<string>();
const resultEvent = workflowEvent<string>();
// Add handlers
workflow.handle([startEvent], (event) => {
// This handler might fail but will be retried
if (Math.random() < 0.7) {
throw new Error("Random failure");
}
return resultEvent.with(`Processed: ${event.data}`);
});
```
## Integrating with External Systems
You can extend your workflows to integrate with external systems:
```ts
import { createWorkflow, workflowEvent } from "llamaindex";
// Define events
const fetchEvent = workflowEvent<string>();
const successEvent = workflowEvent<any>();
const failureEvent = workflowEvent<Error>();
// Create workflow
const workflow = createWorkflow();
// Handle external API calls with proper error handling
workflow.handle([fetchEvent], async (event) => {
const { signal } = getContext();
try {
// Use AbortSignal for cancellation support
const response = await fetch(event.data, { signal });
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const data = await response.json();
return successEvent.with(data);
} catch (error) {
if (error.name === 'AbortError') {
return failureEvent.with(new Error('Request was aborted'));
}
return failureEvent.with(error instanceof Error ? error : new Error(String(error)));
}
});
// Database integration example
const dbQueryEvent = workflowEvent<{ collection: string; query: any }>();
const dbResultEvent = workflowEvent<any[]>();
workflow.handle([dbQueryEvent], async (event) => {
// Connect to database (pseudo-code)
const db = await connectToDatabase();
try {
const results = await db.collection(event.data.collection)
.find(event.data.query)
.toArray();
return dbResultEvent.with(results);
} catch (error) {
return failureEvent.with(error);
} finally {
await db.close();
}
});
```
## Handling Complex Asynchronous Patterns
LlamaIndex workflows excel at managing complex asynchronous patterns:
```ts
import { createWorkflow, workflowEvent, until, collect } from "llamaindex";
// Events for an orchestration workflow
const orchestrateEvent = workflowEvent<string[]>();
const taskEvent = workflowEvent<string>();
const progressEvent = workflowEvent<{ task: string; progress: number }>();
const taskCompleteEvent = workflowEvent<string>();
const aggregateEvent = workflowEvent<any>();
// Create workflow
const workflow = createWorkflow();
// Orchestrator: distribute tasks and collect results
workflow.handle([orchestrateEvent], async (event) => {
const { sendEvent, stream } = getContext();
const tasks = event.data;
// Start all tasks
tasks.forEach(task => sendEvent(taskEvent.with(task)));
// Track progress
let completed = 0;
const results = {};
// Process task completion and progress events
for await (const event of until(stream, () => completed === tasks.length)) {
if (progressEvent.include(event)) {
console.log(`Task ${event.data.task}: ${event.data.progress}%`);
} else if (taskCompleteEvent.include(event)) {
completed++;
results[event.data] = `Completed ${event.data}`;
console.log(`Completed ${completed}/${tasks.length} tasks`);
}
}
return aggregateEvent.with(results);
});
// Task processor
workflow.handle([taskEvent], async (event) => {
const { sendEvent } = getContext();
const task = event.data;
// Simulate task processing with progress updates
for (let progress = 0; progress <= 100; progress += 20) {
sendEvent(progressEvent.with({ task, progress }));
await new Promise(resolve => setTimeout(resolve, 200));
}
return taskCompleteEvent.with(task);
});
```
## Next Steps
Now that you've explored advanced event handling with workflows, you're ready to build sophisticated applications:
- [Integrating Workflows with other LlamaIndex Features](./llamaindex-integration.mdx)
@@ -0,0 +1,263 @@
---
title: Basic Workflow Patterns
description: Learn common patterns and techniques for building effective workflows
---
This guide explores common patterns you can use to build more complex workflows with workflows.
## Fan-out (Parallelism)
One of the most powerful features of workflows is the ability to run tasks in parallel:
```ts
import { createWorkflow, workflowEvent, until, collect } from "llamaindex";
// Define events
const startEvent = workflowEvent<string>();
const processItemEvent = workflowEvent<number>();
const resultEvent = workflowEvent<string>();
const completeEvent = workflowEvent<string[]>();
// Create workflow
const workflow = createWorkflow();
// Process start event: fan out to multiple processItemEvent events
workflow.handle([startEvent], (start) => {
const { sendEvent, stream } = getContext();
// Emit multiple events to be processed in parallel
for (let i = 0; i < 10; i++) {
sendEvent(processItemEvent.with(i));
}
// Collect all resultEvents and emit a final completeEvent
let condition = false;
const results = collect(
until(stream, () => condition)
.filter((ev) => resultEvent.includes(ev))
);
return completeEvent.with(results.map(event => event.data));
});
// Process each item
workflow.handle([processItemEvent], (event) => {
// Process the item
const processedValue = `Processed: ${event.data}`;
// If this is the last item, set the condition to stop collecting
if (event.data === 9) {
condition = true;
}
return resultEvent.with(processedValue);
});
```
This pattern allows you to:
1. Emit multiple events to be processed in parallel
2. Collect results as they come in
3. Complete once all parallel tasks are finished
## Conditional Branching
You can implement conditional logic in your workflows:
```ts
import { createWorkflow, workflowEvent } from "llamaindex";
const inputEvent = workflowEvent<number>();
const evenNumberEvent = workflowEvent<string>();
const oddNumberEvent = workflowEvent<string>();
const resultEvent = workflowEvent<string>();
const workflow = createWorkflow();
// Branch based on whether the number is even or odd
workflow.handle([inputEvent], (event) => {
if (event.data % 2 === 0) {
return evenNumberEvent.with(`${event.data} is even`);
} else {
return oddNumberEvent.with(`${event.data} is odd`);
}
});
// Handle even numbers
workflow.handle([evenNumberEvent], (event) => {
return resultEvent.with(`Even result: ${event.data}`);
});
// Handle odd numbers
workflow.handle([oddNumberEvent], (event) => {
return resultEvent.with(`Odd result: ${event.data}`);
});
```
## Using Middleware
LlamaIndex workflows provide middleware that can enhance your workflows:
### `withStore` Middleware
The `withStore` middleware adds a persistent store to your workflow context:
```ts
import { createWorkflow, workflowEvent, withStore } from "llamaindex";
const startEvent = workflowEvent<void>();
const incrementEvent = workflowEvent<number>();
const resultEvent = workflowEvent<number>();
// Create a workflow with store middleware
const workflow = withStore(
() => ({
count: 0,
history: [] as number[],
}),
createWorkflow()
);
// Increment the counter
workflow.handle([startEvent], () => {
const store = workflow.getStore();
store.count += 1;
store.history.push(store.count);
return incrementEvent.with(store.count);
});
// Return the current count
workflow.handle([incrementEvent], (event) => {
const store = workflow.getStore();
return resultEvent.with(store.count);
});
```
### `withValidation` Middleware
The `withValidation` middleware adds compile-time and runtime validation to your workflows:
```ts
import { createWorkflow, workflowEvent, withValidation } from "llamaindex";
const startEvent = workflowEvent<string, "start">();
const processEvent = workflowEvent<number, "process">();
const resultEvent = workflowEvent<string, "result">();
const disallowedEvent = workflowEvent<void, "disallowed">();
// Create a workflow with validation middleware
// Define allowed event paths
const workflow = withValidation(
createWorkflow(),
[
[[startEvent], [processEvent]], // startEvent can only lead to processEvent
[[processEvent], [resultEvent]], // processEvent can only lead to resultEvent
]
);
// This will pass validation
workflow.strictHandle([startEvent], (sendEvent, start) => {
sendEvent(processEvent.with(123)); // ✅ This is allowed
});
// This would fail at compile time and runtime
workflow.strictHandle([startEvent], (sendEvent, start) => {
// sendEvent(disallowedEvent.with()); // ❌ This would cause an error
// sendEvent(resultEvent.with("result")); // ❌ This would also cause an error
});
```
## Error Handling
LlamaIndex workflows provide built-in mechanisms for handling errors:
```ts
import { createWorkflow, workflowEvent } from "llamaindex";
const startEvent = workflowEvent<string>();
const processEvent = workflowEvent<number>();
const errorEvent = workflowEvent<Error>();
const resultEvent = workflowEvent<string>();
const workflow = createWorkflow();
workflow.handle([startEvent], (start) => {
try {
const num = Number.parseInt(start.data, 10);
if (isNaN(num)) {
throw new Error("Invalid number");
}
return processEvent.with(num);
} catch (err) {
return errorEvent.with(err instanceof Error ? err : new Error(String(err)));
}
});
workflow.handle([processEvent], (event) => {
return resultEvent.with(`Result: ${event.data * 2}`);
});
workflow.handle([errorEvent], (event) => {
return resultEvent.with(`Error: ${event.data.message}`);
});
```
You can also use the signal in `getContext()` to handle errors:
```ts
workflow.handle([processEvent], () => {
const { signal } = getContext();
signal.onabort = () => {
console.error("Process aborted:", signal.reason);
// Clean up resources
};
// Your processing logic here
});
```
## Connecting with Server Endpoints
Workflow can be used as middleware in server frameworks like Express, Hono, or Fastify:
```ts
import { Hono } from "hono";
import { serve } from "@hono/node-server";
import { createWorkflow, workflowEvent, createHonoHandler } from "llamaindex";
// Define events
const queryEvent = workflowEvent<string>();
const responseEvent = workflowEvent<string>();
// Create workflow
const workflow = createWorkflow();
workflow.handle([queryEvent], (event) => {
const response = `Processed: ${event.data}`;
return responseEvent.with(response);
});
// Create Hono app
const app = new Hono();
// Set up workflow endpoint
app.post(
"/workflow",
createHonoHandler(
workflow,
async (ctx) => queryEvent.with(await ctx.req.text()),
responseEvent
)
);
// Start server
serve(app, ({ port }) => {
console.log(`Server started at http://localhost:${port}`);
});
```
## Next Steps
Now that you've learned about basic workflow patterns, explore more advanced topics:
- [Streaming with Workflows](./streaming.mdx)
- [Advanced Event Handling](./advanced-events.mdx)
@@ -1,8 +1,18 @@
---
title: Inputs / Outputs
description: Learn how to use different inputs and outputs in your workflows.
title: Inputs / Outputs (Outdated)
description: This page has been replaced with newer documentation
---
# ⚠️ Outdated Documentation
This documentation is for an older version of the workflow API. Please refer to the new llama-flow documentation:
- [Getting Started with llama-flow](./index.mdx)
- [Basic Workflow Patterns](./basic-workflow.mdx)
- [Advanced Event Handling](./advanced-events.mdx)
The new API provides a more lightweight and flexible approach to building 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.
@@ -164,8 +174,6 @@ This step means that it requires either `AEvent` or `BEvent`. It will return a `
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.
@@ -1,208 +1,111 @@
---
title: Basic Usage
description: Learn how to use the LlamaIndex workflow.
title: Getting Started with Workflows
description: Learn how to use LlamaIndex's lightweight workflow engine for TypeScript
---
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 a simple and lightweight engine for TypeScript. Built with ❤️ by LlamaIndex.
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>();
// ^?
- Minimal core API (\<\=2kb)
- 100% Type safe
- Event-driven, stream oriented programming
- Support for multiple JS runtimes/frameworks
## Installation
It's directly included with the `llamaindex` package:
```shell
npm i llamaindex
```
First, we define a workflow with 3 generic types: `ContextData`, `Input`, and `Output`.
But can also be installed separately:
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.
```shell
npm i @llama-flow/core
In you code logic, you should **share state between steps via `ContextData`**.
# or with yarn
yarn add @llama-flow/core
```ts twoslash
import { Workflow, StartEvent, StopEvent } from '@llamaindex/workflow';
# or with pnpm
pnpm add @llama-flow/core
```
type ContextData = {
counter: number;
}
## Key Concepts
const contextData: ContextData = { counter: 0 };
- **Events**: Data carriers that flow through the workflow
- **Handlers**: Functions that process events and emit new events
- **Workflow**: Connects events and handlers together
- **Context**: Runtime environment for a workflow execution
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}!`);
## Basic Usage
Let's build a simple workflow that processes a text input:
### 1. Define events
First, we need to define the events that will flow through our workflow:
```ts
import { workflowEvent } from "llamaindex";
// Define input and output events
const startEvent = workflowEvent<string>(); // Takes a string input
const convertEvent = workflowEvent<Number>(); // Intermediate event
const stopEvent = workflowEvent<1 | -1>(); // Final output event, returns 1 or -1
```
### 2. Create a workflow and connect events
Next, we'll create our workflow and define how events are processed:
```ts
import { createWorkflow } from "llamaindex";
const workflow = createWorkflow();
// Handle the start event: convert the string to a number
workflow.handle([startEvent], (start) => {
return convertEvent.with(Number.parseInt(start.data, 10));
});
// Handle the convert event: determine if number is positive or negative
workflow.handle([convertEvent], (convert) => {
return stopEvent.with(convert.data > 0 ? 1 : -1);
});
```
In the workflow, we add a step that listens to `StartEvent<string>` and emits `StopEvent<string>`.
### 3. Run the workflow
The step is an async function that takes two arguments: `context` and `event`.
Finally, we can execute our workflow:
### `context` type
```ts
// Create a workflow context and send the initial event
const { stream, sendEvent } = workflow.createContext();
sendEvent(startEvent.with("42"));
<AutoTypeTable path="./src/deps/type.ts" name="HandlerContext" />
// Process the stream to get the result
import { pipeline } from "node:stream/promises";
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}!`);
const result = await pipeline(stream, async function (source) {
for await (const event of source) {
if (stopEvent.include(event)) {
return `Result: ${event.data === 1 ? 'positive' : 'negative'}`;
}
}
});
// ---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!
}
console.log(result); // "Result: positive"
```
Context is shared between runs, so the counter will be increased.
Or using the stream utilities:
Ideally, it should be serializable to make sure it can be recovered from HTTP requests or other storage.
```ts
import { collect, until } from "llamaindex";
### Full example
// Collect all events until we get a stopEvent
const allEvents = await collect(until(stream, stopEvent));
const finalEvent = allEvents[allEvents.length - 1];
console.log(`Result: ${finalEvent.data === 1 ? 'positive' : 'negative'}`);
```
<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" />
Ready to learn more? Check out our [detailed examples](./basic-workflow.mdx) to see llama-flow in action!
@@ -0,0 +1,288 @@
---
title: Integrating with LlamaIndex
description: Build AI applications by combining Workflows with other LlamaIndex features
---
This guide demonstrates how to combine the power of the workflow engine with LlamaIndex's retrieval and reasoning capabilities to build sophisticated AI applications.
## Basic RAG Workflow
Let's build a simple Retrieval-Augmented Generation (RAG) workflow:
```ts
import { createWorkflow, workflowEvent } from "llamaindex";
import { Document, serviceContextFromDefaults, VectorStoreIndex } from "llamaindex";
import { OpenAI, OpenAIEmbedding } from "@llamaindex/openai";
import { Settings } from "@llamaindex/core/global"
// Define events
const queryEvent = workflowEvent<string>();
const retrieveEvent = workflowEvent<{ query: string; documents: Document[] }>();
const generateEvent = workflowEvent<{ query: string; context: string }>();
const responseEvent = workflowEvent<string>();
// Create workflow
const workflow = createWorkflow();
// Set default global llm
Settings.llm = new OpenAI({
model: "gpt-4.1-mini",
temperature: 0.2
});
// Set the default global embedModel
Settings.embedModel = new OpenAIEmbedding({
model: "text-embedding-3-small",
});
// Sample documents
const documents = [
new Document({
text: "LlamaIndex is a data framework for LLM applications to ingest, structure, and access private or domain-specific data.",
}),
new Document({
text: "LlamaIndex workflows are a lightweight workflow engine for TypeScript, designed to create event-driven processes.",
}),
];
// Create vector store index
const index = await VectorStoreIndex.fromDocuments(documents);
// Handle query: Retrieve relevant documents
workflow.handle([queryEvent], (event) => {
const query = event.data;
console.log(`Processing query: ${query}`);
// Retrieve relevant documents
const retriever = index.asRetriever();
const nodes = retriever.retrieve(query);
return retrieveEvent.with({
query,
documents: nodes.map(node => node.node),
});
});
// Handle retrieval results: Generate response
workflow.handle([retrieveEvent], async (event) => {
const { query, documents } = event.data;
// Combine document content as context
const context = documents.map(doc => doc.text).join('\n\n');
return generateEvent.with({ query, context });
});
// Handle generation: Produce final response
workflow.handle([generateEvent], async (event) => {
const { query, context } = event.data;
// Create a prompt with the context and query
const prompt = `
Context information:
${context}
Based on the context information and no other knowledge, answer the following query:
${query}
`;
// Generate response with LLM
const response = await Settings.llm.complete({ prompt });
return responseEvent.with(response.text);
});
// Execute the workflow
const { stream, sendEvent } = workflow.createContext();
sendEvent(queryEvent.with("What is LlamaIndex?"));
// Process the stream
for await (const event of stream) {
if (responseEvent.include(event)) {
console.log("Final response:", event.data);
break;
}
}
```
## Building a Chat Application
Let's create a more complex chat application that maintains conversation history:
```ts
import { createWorkflow, workflowEvent, withStore } from "llamaindex";
import { OpenAI, OpenAIEmbedding } from "@llamaindex/openai";
import { Document, serviceContextFromDefaults, VectorStoreIndex } from "llamaindex";
import { Settings } from "@llamaindex/core/global"
// Set default global llm
Settings.llm = new OpenAI({
model: "gpt-4.1-mini",
temperature: 0.2
});
// Set the default global embedModel
Settings.embedModel = new OpenAIEmbedding({
model: "text-embedding-3-small",
});
// Define store type
type ChatStore = {
history: Array<{ role: string; content: string }>;
documents: Document[];
index: VectorStoreIndex | null;
};
// Define events
const initEvent = workflowEvent<Document[]>();
const indexCreatedEvent = workflowEvent<VectorStoreIndex>();
const userMessageEvent = workflowEvent<string>();
const retrievalEvent = workflowEvent<{ query: string; nodes: any[] }>();
const responseEvent = workflowEvent<{ message: { content: string } }>();
// Create workflow with store
const workflow = withStore<ChatStore>(
() => ({
history: [],
documents: [],
index: null,
}),
createWorkflow()
);
// Initialize the chat context
workflow.handle([initEvent], async (event) => {
const store = workflow.getStore();
store.documents = event.data;
// Create index from documents
const index = await VectorStoreIndex.fromDocuments(store.documents);
store.index = index;
return indexCreatedEvent.with(index);
});
// Process user message
workflow.handle([userMessageEvent], (event) => {
const userMessage = event.data;
const store = workflow.getStore();
// Add user message to history
store.history.push({
role: "user",
content: userMessage,
});
if (!store.index) {
throw new Error("Index not initialized yet");
}
// Retrieve relevant context
const retriever = store.index.asRetriever();
const nodes = retriever.retrieve(userMessage);
return retrievalEvent.with({
query: userMessage,
nodes,
});
});
// Generate response from retrieval results
workflow.handle([retrievalEvent], async (event) => {
const { query, nodes } = event.data;
const store = workflow.getStore();
// Context from retrieved nodes
const context = nodes.map(node => node.node.text).join('\n\n');
// Create the system message with context
const systemMessage = {
role: "system",
content: `You are a helpful assistant. Use the following information to answer the user's question:
${context}
Only use the information provided above to answer. If you don't know, say so.`,
};
// Create full conversation history for the chat
const messages = [
systemMessage,
...store.history,
];
// Generate response
const response = await Settings.llm.chat({
messages,
});
// Add assistant response to history
store.history.push({
role: "assistant",
content: response.message.content,
});
return responseEvent.with(response);
});
// Example usage
async function runChat() {
// Sample documents
const documents = [
new Document({
text: "LlamaIndex is a data framework for LLM applications to ingest, structure, and access private or domain-specific data.",
}),
new Document({
text: "LlamaIndex Workflows are a lightweight workflow engine for TypeScript, designed to create event-driven processes.",
}),
];
// Initialize the chat
const { stream, sendEvent } = workflow.createContext();
sendEvent(initEvent.with(documents));
// Wait for index creation
for await (const event of stream) {
if (indexCreatedEvent.include(event)) {
console.log("Index created successfully");
break;
}
}
// Start conversation
async function sendUserMessage(message: string) {
sendEvent(userMessageEvent.with(message));
for await (const event of stream) {
if (responseEvent.include(event)) {
console.log("Assistant:", event.data.message.content);
return event.data.message.content;
}
}
}
await sendUserMessage("What is LlamaIndex?");
await sendUserMessage("Can you tell me about LlamaIndex workflows?");
await sendUserMessage("How might these two technologies work together?");
}
runChat();
```
## Building an Tool Calling Agent
[TODO]
## Conclusion
By combining the lightweight, event-driven workflow engine with LlamaIndex's powerful document indexing and querying capabilities, you can build sophisticated AI applications with clean, maintainable code.
The event-driven architecture allows you to:
1. Break complex processes into manageable steps
2. Create reusable components for common AI workflows
3. Easily debug and monitor each phase of execution
4. Scale your applications by isolating resource-intensive steps
5. Build more resilient systems with better error handling
As you build your own applications, consider how the patterns shown here can be adapted to your specific use cases.
@@ -1,6 +1,12 @@
{
"title": "Workflow",
"description": "See how to use @llamaindex/workflow",
"title": "Workflows",
"description": "Event-driven workflow engine for TypeScript",
"defaultOpen": false,
"pages": ["index", "different-inputs-outputs", "streaming"]
"pages": [
"index",
"basic-workflow",
"streaming",
"advanced-events",
"llamaindex-integration"
]
}
@@ -1,199 +1,371 @@
---
title: Streaming
description: Learn how to use the LlamaIndex workflow with streaming.
title: Streaming with Workflows
description: Learn how to build streaming workflows
---
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.
LlamaIndex workflows are designed from the ground up to work with streaming data. The streaming capabilities make it perfect for:
Each `workflow.run` call returns `WorkflowContext`, which implements `AsyncIterable` interface. You can use it to stream data.
- Building real-time applications
- Handling large datasets incrementally
- Creating responsive UIs that update as data becomes available
- Implementing long-running tasks with partial results
```ts twoslash
import { Workflow, WorkflowEvent, StartEvent, StopEvent } from '@llamaindex/workflow';
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
## Basic Streaming
Every workflow context provides a stream of events:
```ts
import { createWorkflow, workflowEvent } from "llamaindex";
// Define events
const startEvent = workflowEvent<string>();
const intermediateEvent = workflowEvent<string>();
const resultEvent = workflowEvent<string>();
// Create workflow
const workflow = createWorkflow();
workflow.handle([startEvent], (event) => {
const { sendEvent } = getContext();
// Emit multiple intermediate events
for (let i = 0; i < 5; i++) {
sendEvent(intermediateEvent.with(`Progress: ${i * 20}%`));
}
return resultEvent.with("Completed");
});
// Run the workflow
const { stream, sendEvent } = workflow.createContext();
sendEvent(startEvent.with("Start processing"));
// Process events as they arrive
for await (const event of stream) {
if (intermediateEvent.include(event)) {
console.log(event.data); // Show progress updates
} else if (resultEvent.include(event)) {
console.log("Final result:", event.data);
break; // Exit the loop when done
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
```
## Using the Stream Utilities
Workflows provide utility functions to make working with streams easier:
```ts
import { createWorkflow, workflowEvent, until, collect } from "llamaindex";
const startEvent = workflowEvent<void>();
const progressEvent = workflowEvent<number>();
const resultEvent = workflowEvent<string>();
const workflow = createWorkflow();
workflow.handle([startEvent], () => {
const { sendEvent } = getContext();
// Emit progress events
for (let i = 0; i < 100; i += 10) {
sendEvent(progressEvent.with(i));
}
return resultEvent.with("Complete");
});
// Run the workflow and collect events until a condition is met
const { stream, sendEvent } = workflow.createContext();
sendEvent(startEvent.with());
// Collect all events until resultEvent is encountered
const events = await collect(until(stream, (event) => resultEvent.include(event)));
// Filter only progress events
const progressEvents = events.filter(event => progressEvent.include(event));
console.log(`Received ${progressEvents.length} progress updates`);
```
## Conditional Stream Processing
You can conditionally process events and even stop the stream early:
```ts
import { createWorkflow, workflowEvent } from "llamaindex";
const startEvent = workflowEvent<number>();
const dataEvent = workflowEvent<number>();
const thresholdEvent = workflowEvent<void>();
const resultEvent = workflowEvent<number[]>();
const workflow = createWorkflow();
workflow.handle([startEvent], (event) => {
const { sendEvent } = getContext();
const max = event.data;
for (let i = 0; i < max; i++) {
sendEvent(dataEvent.with(i));
if (i >= 10) {
// Signal that we've hit a threshold
sendEvent(thresholdEvent.with());
}
}
return resultEvent.with(Array.from({ length: max }, (_, i) => i));
});
// Run the workflow
const { stream, sendEvent } = workflow.createContext();
sendEvent(startEvent.with(100)); // Generate 100 numbers
const results = [];
let hitThreshold = false;
// Process the stream
for await (const event of stream) {
if (dataEvent.include(event)) {
results.push(event.data);
} else if (thresholdEvent.include(event)) {
hitThreshold = true;
break; // Stop processing early
}
}
type ContextData = {
sum: number;
}
console.log(`Collected ${results.length} items before ${hitThreshold ? 'hitting threshold' : 'completion'}`);
```
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);
## Integration with UI Frameworks
Workflow streams can be easily integrated with UI frameworks like React to create responsive interfaces:
```tsx
// In a React component
import { useEffect, useState } from 'react';
import { createWorkflow, workflowEvent } from "llamaindex";
function StreamingComponent() {
const [updates, setUpdates] = useState([]);
const [isComplete, setIsComplete] = useState(false);
useEffect(() => {
// Set up workflow
const startEvent = workflowEvent<void>();
const updateEvent = workflowEvent<string>();
const completeEvent = workflowEvent<void>();
const workflow = createWorkflow();
workflow.handle([startEvent], () => {
const { sendEvent } = getContext();
// Simulate async updates
const intervals = [
setTimeout(() => sendEvent(updateEvent.with("First update")), 500),
setTimeout(() => sendEvent(updateEvent.with("Second update")), 1000),
setTimeout(() => sendEvent(updateEvent.with("Final update")), 1500),
setTimeout(() => sendEvent(completeEvent.with()), 2000)
];
// Cleanup function
getContext().signal.onabort = () => {
intervals.forEach(clearTimeout);
};
});
// Run the workflow
const { stream, sendEvent } = workflow.createContext();
sendEvent(startEvent.with());
// Process events
const processEvents = async () => {
for await (const event of stream) {
if (updateEvent.include(event)) {
setUpdates(prev => [...prev, event.data]);
} else if (completeEvent.include(event)) {
setIsComplete(true);
break;
}
}
};
processEvents();
// Cleanup
return () => {
// The workflow will be aborted when the component unmounts
};
}, []);
return (
<div>
<h2>Streaming Updates</h2>
<ul>
{updates.map((update, i) => (
<li key={i}>{update}</li>
))}
</ul>
{isComplete && <div>Process complete!</div>}
</div>
);
}
```
## Server-Sent Events (SSE)
Workflows are also suitable for implementing Server-Sent Events:
```ts
import { createWorkflow, workflowEvent } from "llamaindex";
import express from 'express';
// Define events
const startEvent = workflowEvent<void>();
const dataEvent = workflowEvent<string>();
// Create workflow
const workflow = createWorkflow();
workflow.handle([startEvent], () => {
const { sendEvent } = getContext();
// Send periodic updates
const intervals = [
setInterval(() => {
sendEvent(dataEvent.with(`Update: ${new Date().toISOString()}`));
}, 1000)
];
// Cleanup
getContext().signal.onabort = () => {
intervals.forEach(clearInterval);
};
});
// Set up Express server
const app = express();
app.get('/events', (req, res) => {
// Set headers for SSE
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
// Run workflow
const { stream, sendEvent } = workflow.createContext();
sendEvent(startEvent.with());
// Handle client disconnect
req.on('close', () => {
// This will trigger the abort signal in the workflow
});
// Process and send events
(async () => {
for await (const event of stream) {
if (dataEvent.include(event)) {
res.write(`data: ${JSON.stringify(event.data)}\n\n`);
}
}
})();
});
app.listen(3000, () => {
console.log('SSE server running on port 3000');
});
```
We define a parallel computation workflow that computes the sum of numbers from 0 to `total`.
## Advanced Techniques
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`.
### Flow Control
What if we want cutoff if the sum exceeds a certain value?
You can implement flow control with backpressure in your streaming workflows:
## Streaming
```ts
import { createWorkflow, workflowEvent } from "llamaindex";
```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);
}
}
// This example shows how to process items with controlled concurrency
const processItems = async (items, maxConcurrency = 3) => {
const startEvent = workflowEvent<string[]>();
const processItemEvent = workflowEvent<string>();
const itemProcessedEvent = workflowEvent<string>();
const resultEvent = workflowEvent<string[]>();
const workflow = createWorkflow();
// Handler to process individual items
workflow.handle([processItemEvent], async (event) => {
// Simulate processing time
await new Promise(resolve => setTimeout(resolve, 100));
return itemProcessedEvent.with(`Processed: ${event.data}`);
});
// Main workflow handler
workflow.handle([startEvent], async (event) => {
const { sendEvent, stream } = getContext();
const results = [];
// Process with controlled concurrency
const items = event.data;
let inProgress = 0;
let itemIndex = 0;
// Start initial batch of items
while (inProgress < maxConcurrency && itemIndex < items.length) {
sendEvent(processItemEvent.with(items[itemIndex++]));
inProgress++;
}
// Process items and collect results
for await (const event of stream) {
if (itemProcessedEvent.include(event)) {
results.push(event.data);
inProgress--;
// Add next item if available
if (itemIndex < items.length) {
sendEvent(processItemEvent.with(items[itemIndex++]));
inProgress++;
} else if (inProgress === 0) {
// All done
break;
}
}
}
return resultEvent.with(results);
});
// Run the workflow
const { stream, sendEvent } = workflow.createContext();
sendEvent(startEvent.with(items));
// Wait for final result
for await (const event of stream) {
if (resultEvent.include(event)) {
return event.data;
}
}
return [];
};
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);
}
// Usage
const results = await processItems(
Array.from({ length: 20 }, (_, i) => `Item ${i}`)
);
// ---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;
}
console.log(results);
```
<WorkflowStreamingDemo />
This pattern allows you to:
1. Process large datasets without overwhelming system resources
2. Control the level of concurrency
3. Process data as it becomes available
4. Create efficient data pipelines
## Next Steps
Now that you've learned about streaming with workflows, explore more advanced topics:
- [Advanced Event Handling](./advanced-events.mdx)
- [Integration Workflows with other LlamaIndex features](./llamaindex-integration.mdx)
+1 -1
View File
@@ -1,3 +1,3 @@
{
"pages": ["llamaindex", "cloud", "api"]
"pages": ["llamaindex", "llamaflow", "cloud", "api"]
}
+1 -1
View File
@@ -1,2 +1,2 @@
// when we are ready, change to /docs/llamaindex
export const LEGACY_DOCUMENT_URL = '/docs/llamaindex'
export const DOCUMENT_URL = '/docs/llamaindex'
@@ -1,5 +1,30 @@
# @llamaindex/cloudflare-worker-agent-test
## 0.0.155
### Patch Changes
- llamaindex@0.10.1
## 0.0.154
### Patch Changes
- Updated dependencies [6cf928f]
- llamaindex@0.10.0
## 0.0.153
### Patch Changes
- llamaindex@0.9.19
## 0.0.152
### Patch Changes
- llamaindex@0.9.18
## 0.0.151
### Patch Changes

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