some docs fixes (#128)

This commit is contained in:
Logan
2025-07-18 14:01:24 -06:00
committed by GitHub
parent be1b526b24
commit a11656fe6b
6 changed files with 160 additions and 127 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@llamaindex/workflow-docs": patch
---
Ensure examples can run
+14 -12
View File
@@ -46,17 +46,21 @@ workflow.handle([booleanEvent], (event) => {
});
});
// Run the workflow
const { stream, sendEvent } = workflow.createContext();
const main = async () => {
// Run the workflow
const { stream, sendEvent } = workflow.createContext();
sendEvent(textEvent.with("Hello, world!"));
sendEvent(textEvent.with("Hello, world!"));
for await (const event of stream) {
if (complexEvent.include(event)) {
console.log(event.data);
break;
for await (const event of stream) {
if (complexEvent.include(event)) {
console.log(event.data);
break;
}
}
}
};
void main().catch(console.error);
```
### Event Branching and Merging
@@ -240,13 +244,11 @@ workflow.handle([initEvent], async (event) => {
}
// Collect transformed events
const limit = event.data;
let numResults = 0;
const results = await stream
.filter(transformedEvent)
.until((event) => {
numResults++;
return numResults >= event.data;
})
.until(() => ++numResults >= limit)
.toArray();
return resultEvent.with(results.map((r) => r.data));
+12 -5
View File
@@ -157,6 +157,7 @@ LlamaIndex workflows provide middleware that can enhance your workflows:
The `withState` middleware adds a persistent state to your workflow context:
```ts
import { createWorkflow, workflowEvent } from "@llamaindex/workflow-core";
import { createStatefulMiddleware } from "@llamaindex/workflow-core/middleware/state";
// Define your state type
@@ -165,11 +166,17 @@ type CounterState = {
history: number[];
};
// Create a workflow with state middleware
const { withState } = createStatefulMiddleware<CounterState>(() => ({
count: 0,
history: [],
}));
// Define events
const startEvent = workflowEvent<void>();
const incrementEvent = workflowEvent<number>();
const resultEvent = workflowEvent<number>();
const { withState, getContext } = createStatefulMiddleware<CounterState>(
() => ({
count: 0,
history: [],
}),
);
const workflow = withState(createWorkflow());
+28 -21
View File
@@ -37,30 +37,34 @@ With [workflowEvent](#) and [createWorkflow](#), you can create a simple workflo
import { OpenAI } from "openai";
import { createWorkflow, workflowEvent } from "@llamaindex/workflow-core";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
const startEvent = workflowEvent<string>();
const stopEvent = workflowEvent<string>();
const workflow = createWorkflow();
workflow.handle([startEvent], async (event) => {
const response = await openai.chat.completions.create({
// ...
messages: [{ role: "user", content: event.data }],
const main = async () => {
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
return stopEvent(response.choices[0].message.content);
});
const startEvent = workflowEvent<string>();
const stopEvent = workflowEvent<string>();
workflow.handle([stopEvent], (event) => {
console.log("Response:", event.data);
});
const workflow = createWorkflow();
const { sendEvent } = workflow.createContext();
sendEvent(startEvent.with("Hello, Workflows!"));
workflow.handle([startEvent], async (event) => {
const response = await openai.chat.completions.create({
model: "gpt-4.1-mini",
messages: [{ role: "user", content: event.data }],
});
return stopEvent.with(response.choices[0].message.content ?? "");
});
workflow.handle([stopEvent], (event) => {
console.log("Response:", event.data);
});
const { sendEvent } = workflow.createContext();
sendEvent(startEvent.with("Hello, Workflows!"));
};
void main().catch(console.error);
```
## Parallel processing with async handlers
@@ -71,7 +75,11 @@ Tool calls are a common pattern in LLM applications, where the model generates a
Workflows provide [abort signals](#) and [parallel processing](#) out of the box.
For example, imagine you have a workflow handler for calling tools that an agent has selection:
```ts
import { getContext } from "@llamaindex/workflow-core";
workflow.handle([toolCallEvent], ({ data: { id, name, args } }) => {
const { signal, sendEvent } = getContext();
signal.onabort = () =>
@@ -82,7 +90,6 @@ workflow.handle([toolCallEvent], ({ data: { id, name, args } }) => {
content: "ERROR WHILE CALLING FUNCTION" + signal.reason.message,
}),
);
const result = callFunction(name, args);
return toolCallResultEvent.with({
role: "tool",
+68 -64
View File
@@ -24,15 +24,6 @@ import {
} from "llamaindex";
import { OpenAI, OpenAIEmbedding } from "@llamaindex/openai";
// Define events
const queryEvent = workflowEvent<string>();
const retrieveEvent = workflowEvent<{ query: string; nodes: BaseNode[] }>();
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",
@@ -44,76 +35,89 @@ 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.",
}),
];
const main = async () => {
// Define events
const queryEvent = workflowEvent<string>();
const retrieveEvent = workflowEvent<{ query: string; nodes: BaseNode[] }>();
const generateEvent = workflowEvent<{ query: string; context: string }>();
const responseEvent = workflowEvent<string>();
// Create vector store index
const index = await VectorStoreIndex.fromDocuments(documents);
// Create workflow
const workflow = createWorkflow();
// Handle query: Retrieve relevant documents
workflow.handle([queryEvent], async (event) => {
const query = event.data;
console.log(`Processing query: ${query}`);
// 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.",
}),
];
// Retrieve relevant documents
const retriever = index.asRetriever();
const nodes = await retriever.retrieve(query);
// Create vector store index
const index = await VectorStoreIndex.fromDocuments(documents);
return retrieveEvent.with({
query,
nodes: nodes.map((node) => node.node),
// Handle query: Retrieve relevant documents
workflow.handle([queryEvent], async (event) => {
const query = event.data;
console.log(`Processing query: ${query}`);
// Retrieve relevant documents
const retriever = index.asRetriever();
const nodes = await retriever.retrieve(query);
return retrieveEvent.with({
query,
nodes: nodes.map((node) => node.node),
});
});
});
// Handle retrieval results: Generate response
workflow.handle([retrieveEvent], async (event) => {
const { query, nodes } = event.data;
// Handle retrieval results: Generate response
workflow.handle([retrieveEvent], async (event) => {
const { query, nodes } = event.data;
// Combine document content as context
const context = nodes
.map((node) => node.getContent(MetadataMode.NONE))
.join("\n\n");
// Combine document content as context
const context = nodes
.map((node) => node.getContent(MetadataMode.NONE))
.join("\n\n");
return generateEvent.with({ query, context });
});
return generateEvent.with({ query, context });
});
// Handle generation: Produce final response
workflow.handle([generateEvent], async (event) => {
const { query, context } = event.data;
// 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}
// 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}
`;
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 });
// Generate response with LLM
const response = await Settings.llm.complete({ prompt });
return responseEvent.with(response.text);
});
return responseEvent.with(response.text);
});
// Execute the workflow
const { stream, sendEvent } = workflow.createContext();
sendEvent(queryEvent.with("What is LlamaIndex?"));
// 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;
// Process the stream
for await (const event of stream) {
if (responseEvent.include(event)) {
console.log("Final response:", event.data);
break;
}
}
}
};
void main().catch(console.error);
```
## Building an Tool Calling Agent
@@ -126,10 +130,10 @@ import {
Settings,
Document,
VectorStoreIndex,
agent, // Import the agent factory
tool, // Import the tool factory
QueryEngineTool, // Specific tool type for query engines
} from "llamaindex";
import { agent } from "@llamaindex/workflow"; // Import the agent factory
import { OpenAI, OpenAIEmbedding } from "@llamaindex/openai";
// import { SimpleDirectoryReader } from "@llamaindex/readers/directory"; // If loading from files
import { z } from "zod"; // For defining tool parameters
+33 -25
View File
@@ -83,16 +83,20 @@ workflow.handle([startEvent], () => {
return resultEvent.with("Complete");
});
// Run the workflow and collect events until a condition is met
const { stream, sendEvent } = workflow.createContext();
sendEvent(startEvent.with());
const main = async () => {
// 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 progressEvents = await stream
.until(resultEvent)
.filter(progressEvent)
.toArray();
console.log(`Received ${progressEvents.length} progress updates`);
// Collect all events until resultEvent is encountered
const progressEvents = await stream
.until(resultEvent)
.filter(progressEvent)
.toArray();
console.log(`Received ${progressEvents.length} progress updates`);
};
void main().catch(console.error);
```
## Conditional Stream Processing
@@ -128,26 +132,30 @@ workflow.handle([startEvent], (event) => {
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 main = async () => {
// Run the workflow
const { stream, sendEvent } = workflow.createContext();
sendEvent(startEvent.with(100)); // Generate 100 numbers
const results = [];
let hitThreshold = false;
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
// 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
}
}
}
console.log(
`Collected ${results.length} items before ${hitThreshold ? "hitting threshold" : "completion"}`,
);
console.log(
`Collected ${results.length} items before ${hitThreshold ? "hitting threshold" : "completion"}`,
);
};
void main().catch(console.error);
```
## Integration with UI Frameworks