Compare commits

...

10 Commits

Author SHA1 Message Date
github-actions[bot] 3b45191228 Release 0.10.4 (#1901)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-05-07 11:11:11 +07:00
Marcus Schiesser aaf2f8b2db docs: fix docs for agents (#1914) 2025-05-07 11:03:08 +07:00
Marcus Schiesser 6ddf1c1b1f chore: fixes for workflows before release (#1908) 2025-05-07 09:29:09 +07:00
Marcus Schiesser a8717d5ece chore: ensure pinning workflow version (#1907) 2025-05-06 12:51:13 +07:00
Huu Le 7e8e4549f2 chore: update @llama-flow/core to version 0.4.1 and export stream api (#1906)
Co-authored-by: Marcus Schiesser <mail@marcusschiesser.de>
2025-05-05 16:06:44 +07:00
Alex Yang cc3fe92a22 docs: update llama-flow 2025-05-04 02:28:04 -07:00
Alex Yang 63ab0dba4e chore: drop node.js 18 support (#1904) 2025-05-02 11:51:18 -07:00
Alex Yang 2225ffd1d4 feat: bump llama cloud sdk (#1903) 2025-05-01 13:30:52 -07:00
Marcus Schiesser bc5334249b chore: migrate agentworkflows to llama-flow (#1895)
Co-authored-by: leehuwuj <leehuwuj@gmail.com>
2025-04-30 18:14:17 +07:00
Thuc Pham 41953a3ef9 fix: node10 module resolution fail in sub llamaindex packages (#1900) 2025-04-29 17:47:50 +07:00
111 changed files with 4110 additions and 6541 deletions
+2 -2
View File
@@ -23,7 +23,7 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: [18.x, 20.x, 22.x, 23.x]
node-version: [20.x, 22.x, 23.x]
name: E2E on Node.js ${{ matrix.node-version }}
runs-on: ubuntu-latest
steps:
@@ -53,7 +53,7 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: [18.x, 20.x, 22.x, 23.x]
node-version: [20.x, 22.x, 23.x]
name: Test on Node.js ${{ matrix.node-version }}
runs-on: ubuntu-latest
steps:
+1 -1
View File
@@ -1 +1 @@
20
22
+13
View File
@@ -1,5 +1,18 @@
# @llamaindex/doc
## 0.2.16
### Patch Changes
- Updated dependencies [7e8e454]
- Updated dependencies [2225ffd]
- Updated dependencies [6ddf1c1]
- Updated dependencies [bc53342]
- Updated dependencies [41953a3]
- @llamaindex/workflow@1.1.0
- @llamaindex/cloud@4.0.5
- llamaindex@0.10.4
## 0.2.15
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/doc",
"version": "0.2.15",
"version": "0.2.16",
"private": true,
"scripts": {
"postinstall": "fumadocs-mdx",
@@ -15,7 +15,7 @@
"dependencies": {
"@huggingface/transformers": "^3.5.0",
"@icons-pack/react-simple-icons": "^10.1.0",
"@llama-flow/docs": "0.0.5",
"@llama-flow/docs": "0.0.8",
"@llamaindex/chat-ui": "0.2.0",
"@llamaindex/cloud": "workspace:*",
"@llamaindex/core": "workspace:*",
+4 -3
View File
@@ -26,7 +26,7 @@ const llm = openai();
const response = await llm.chat({
messages: [{ content: "Tell me a joke.", role: "user" }],
});`,
`import { agent } from "llamaindex";
`import { agent } from "@llamaindex/workflow";
import { openai } from "@llamaindex/openai";
const analyseAgent = agent({
@@ -36,7 +36,7 @@ const analyseAgent = agent({
});
const response = await analyseAgent.run(\`Analyse the given data:
\${data}\`);`,
`import { agent, multiAgent } from "llamaindex";
`import { agent, multiAgent } from "@llamaindex/workflow";
import { openai } from "@llamaindex/openai";
const analyseAgent = agent({
@@ -113,8 +113,9 @@ export default function HomePage() {
description="Truly powerful retrieval-augmented generation applications use agentic techniques, and LlamaIndex.TS makes it easy to build them."
>
<CodeBlock
code={`import { agent, SimpleDirectoryReader, VectorStoreIndex } from "llamaindex";
code={`import { SimpleDirectoryReader, VectorStoreIndex } from "llamaindex";
import { openai } from "@llamaindex/openai";
import { agent } from "@llamaindex/workflow";
// load documents from current directoy into an index
const reader = new SimpleDirectoryReader();
@@ -40,19 +40,7 @@ Make sure to set [moduleResolution](https://www.typescriptlang.org/docs/handbook
}
```
We recommend using `bundler` or `nodenext`, but due to popularity of `node`, we still added support for it, but with import path limitations.
So you may encounter type errors when importing sub paths from the `llamaindex` package like:
```ts
import { Settings } from "llamaindex";
```
The simplest way to fix this without changing `moduleResolution` is to import directly from `llamaindex`:
```ts
import { Settings } from "llamaindex";
```
We recommend using `bundler` or `nodenext`, but due to popularity of `node`, we still added support for it.
## Enable AsyncIterable for `Web Stream` API
@@ -68,7 +56,8 @@ Some modules uses `Web Stream` API like `ReadableStream` and `WritableStream`, y
```
```typescript
import { agent, tool } from 'llamaindex'
import { tool } from 'llamaindex'
import { agent } from "@llamaindex/workflow";
import { openai } from "@llamaindex/openai";
Settings.llm = openai({
@@ -12,7 +12,8 @@ Agent Workflows are a powerful system that enables you to create and orchestrate
The simplest use case is creating a single agent with specific tools. Here's an example of creating an assistant that tells jokes:
```typescript
import { agent, tool } from "llamaindex";
import { tool } from "llamaindex";
import { agent } from "@llamaindex/workflow";
import { openai } from "@llamaindex/openai";
// Define a joke-telling tool
@@ -40,17 +41,17 @@ console.log(result); // Baby Llama is called cria
Agent Workflows provide a unified interface for event streaming, making it easy to track and respond to different events during execution:
```typescript
import { AgentToolCall, AgentStream } from "llamaindex";
import { agentToolCallEvent, agentStreamEvent } from "@llamaindex/workflow";
// Get the workflow execution context
const context = workflow.run("Tell me something funny");
const events = workflow.runStream("Tell me something funny");
// Stream and handle events
for await (const event of context) {
if (event instanceof AgentToolCall) {
for await (const event of events) {
if (agentToolCallEvent.include(event)) {
console.log(`Tool being called: ${event.data.toolName}`);
}
if (event instanceof AgentStream) {
if (agentStreamEvent.include(event)) {
process.stdout.write(event.data.delta);
}
}
@@ -68,7 +69,8 @@ An Agent Workflow can orchestrate multiple agents, enabling complex interactions
Here's an example of a multi-agent system that combines joke-telling and weather information:
```typescript
import { multiAgent, agent, tool } from "llamaindex";
import { tool } from "llamaindex";
import { multiAgent, agent } from "@llamaindex/workflow";
import { openai } from "@llamaindex/openai";
import { z } from "zod";
@@ -17,7 +17,8 @@ The `parameters` field in the tool configuration is defined using `zod`, a TypeS
Example:
```ts
import { agent, tool } from "llamaindex";
import { tool } from "llamaindex";
import { agent } from "@llamaindex/workflow";
import { z } from "zod";
// first arg is LLM input, second is bound arg
@@ -46,7 +47,7 @@ In this example, `z.object` is used to define a schema for the `parameters` wher
You can import built-in tools from the `@llamaindex/tools` package.
```ts
import { agent } from "llamaindex";
import { agent } from "@llamaindex/workflow";
import { wiki } from "@llamaindex/tools";
const researchAgent = agent({
@@ -64,7 +65,7 @@ If you have a MCP server running, you can fetch tools from the server and use th
```ts
// 1. Import MCP tools adapter
import { mcp } from "@llamaindex/tools";
import { agent } from "llamaindex";
import { agent } from "@llamaindex/workflow";
// 2. Initialize a MCP client
// by npx
@@ -114,7 +115,8 @@ Note: calling the `bind` method will return a new `FunctionTool` instance, witho
Example to pass a `userToken` as additional argument:
```ts
import { agent, tool } from "llamaindex";
import { tool } from "llamaindex";
import { agent } from "@llamaindex/workflow";
// first arg is LLM input, second is bound arg
const queryKnowledgeBase = async ({ question }, { userToken }) => {
@@ -7,101 +7,14 @@ A `Workflow` in LlamaIndex is a lightweight, event-driven abstraction used to ch
Workflows are designed to be flexible and can be used to build agents, RAG flows, extraction flows, or anything else you want to implement.
```package-install
npm i @llama-flow/core @llamaindex/openai
npm i @llamaindex/workflow @llamaindex/openai
```
## Getting Started
Let's explore a simple workflow example where a joke is generated and then critiqued and iterated on:
```typescript
import { OpenAI } from "@llamaindex/openai";
import { createWorkflow, workflowEvent } from "@llama-flow/core";
import { withStore } from "@llama-flow/core/middleware/store";
// Create LLM instance
const llm = new OpenAI({ model: "gpt-4.1-mini", apiKey: "..."});
// Define our workflow events
const startEvent = workflowEvent<string>(); // Input topic for joke
const jokeEvent = workflowEvent<{ joke: string }>(); // Intermediate joke
const critiqueEvent = workflowEvent<{ joke: string, critique: string }>(); // Intermediate critique
const resultEvent = workflowEvent<{ joke: string, critique: string }>(); // Final joke + critique
// Create our workflow
const jokeFlow = withStore(
() => ({
numIterations: 0,
maxIterations: 3,
}),
createWorkflow()
);
// Define handlers for each step
jokeFlow.handle([startEvent], async (event) => {
// Prompt the LLM to write a joke
const prompt = `Write your best joke about ${event.data}. Write the joke between <joke> and </joke> tags.`;
const response = await llm.complete({ prompt });
// Parse the joke from the response
const joke = response.text.match(/<joke>([\s\S]*?)<\/joke>/)?.[1]?.trim() ?? response.text;
return jokeEvent.with({ joke: joke });
});
jokeFlow.handle([jokeEvent], async (event) => {
// Prompt the LLM to critique the joke
const prompt = `Give a thorough critique of the following joke. If the joke needs improvement, put "IMPROVE" somewhere in the critique: ${event.data.joke}`;
const response = await llm.complete({ prompt });
// If the critique includes "IMPROVE", keep iterating, else, return the result
if (response.text.includes("IMPROVE")) {
return critiqueEvent.with({ joke: event.data.joke, critique: response.text });
}
return resultEvent.with({ joke: event.data.joke, critique: response.text });
});
jokeFlow.handle([critiqueEvent], async (event) => {
// Keep track of the number of iterations
const store = jokeFlow.getStore();
store.numIterations++;
// Write a new joke based on the previous joke and critique
const prompt = `Write a new joke based on the following critique and the original joke. Write the joke between <joke> and </joke> tags.\n\nJoke: ${event.data.joke}\n\nCritique: ${event.data.critique}`;
const response = await llm.complete({ prompt });
// Parse the joke from the response
const joke = response.text.match(/<joke>([\s\S]*?)<\/joke>/)?.[1]?.trim() ?? response.text;
// If we've done less than the max number of iterations, keep iterating
// else, return the result
if (store.numIterations < store.maxIterations) {
return jokeEvent.with({ joke: joke });
}
return resultEvent.with({ joke: joke, critique: event.data.critique });
});
// Usage
async function main() {
const { stream, sendEvent } = jokeFlow.createContext();
sendEvent(startEvent.with("pirates"));
let result: { joke: string, critique: string } | undefined;
for await (const event of stream) {
// console.log(event.data); optionally log the event data
if (resultEvent.include(event)) {
result = event.data;
break; // Stop when we get the final result
}
}
console.log(result);
}
main().catch(console.error);
```
<include cwd>../../examples/agents/workflow/joke.ts</include>
There are a few moving pieces here, so let's go through this step by step.
@@ -110,8 +23,8 @@ There are a few moving pieces here, so let's go through this step by step.
```typescript
const startEvent = workflowEvent<string>(); // Input topic for joke
const jokeEvent = workflowEvent<{ joke: string }>(); // Intermediate joke
const critiqueEvent = workflowEvent<{ joke: string, critique: string }>(); // Intermediate critique
const resultEvent = workflowEvent<{ joke: string, critique: string }>(); // Final joke + critique
const critiqueEvent = workflowEvent<{ joke: string; critique: string }>(); // Intermediate critique
const resultEvent = workflowEvent<{ joke: string; critique: string }>(); // Final joke + critique
```
Events are defined using the `workflowEvent` function and contain arbitrary data provided as a generic type. In this example, we have four events:
@@ -120,23 +33,21 @@ Events are defined using the `workflowEvent` function and contain arbitrary data
- `critiqueEvent`: Contains both the joke and its critique, used for the feedback loop
- `resultEvent`: Contains the final joke and critique after any iterations
### Setting up the Workflow with Store Middleware
### Setting up the Workflow with Stateful Middleware
```typescript
const jokeFlow = withStore(
() => ({
numIterations: 0,
maxIterations: 3,
}),
createWorkflow()
);
const { withState, getContext } = createStatefulMiddleware(() => ({
numIterations: 0,
maxIterations: 3,
}));
const jokeFlow = withState(createWorkflow());
```
Our workflow is implemented using the `createWorkflow()` function, enhanced with the `withStore` middleware. The store provides shared state across all handlers, which in this case tracks:
Our workflow is implemented using the `createWorkflow()` function, enhanced with the `withState` middleware. This middleware provides shared state across all handlers, which in this case tracks:
- `numIterations`: Counts how many iterations of joke improvement we've done
- `maxIterations`: Sets a limit to prevent infinite loops
This store will be accesible within workflows by using the `jokeFlow.getStore()` function.
This state will be accessible within workflows by using the `getContext().state` function.
### Adding Handlers with Loops
@@ -149,9 +60,11 @@ jokeFlow.handle([startEvent], async (event) => {
// Prompt the LLM to write a joke
const prompt = `Write your best joke about ${event.data}. Write the joke between <joke> and </joke> tags.`;
const response = await llm.complete({ prompt });
// Parse the joke from the response
const joke = response.text.match(/<joke>([\s\S]*?)<\/joke>/)?.[1]?.trim() ?? response.text;
const joke =
response.text.match(/<joke>([\s\S]*?)<\/joke>/)?.[1]?.trim() ??
response.text;
return jokeEvent.with({ joke: joke });
});
```
@@ -165,12 +78,15 @@ jokeFlow.handle([jokeEvent], async (event) => {
// Prompt the LLM to critique the joke
const prompt = `Give a thorough critique of the following joke. If the joke needs improvement, put "IMPROVE" somewhere in the critique: ${event.data.joke}`;
const response = await llm.complete({ prompt });
// If the critique includes "IMPROVE", keep iterating, else, return the result
if (response.text.includes("IMPROVE")) {
return critiqueEvent.with({ joke: event.data.joke, critique: response.text });
return critiqueEvent.with({
joke: event.data.joke,
critique: response.text,
});
}
return resultEvent.with({ joke: event.data.joke, critique: response.text });
});
```
@@ -182,22 +98,24 @@ jokeFlow.handle([jokeEvent], async (event) => {
```typescript
jokeFlow.handle([critiqueEvent], async (event) => {
// Keep track of the number of iterations
const store = jokeFlow.getStore();
store.numIterations++;
const state = getContext().state;
state.numIterations++;
// Write a new joke based on the previous joke and critique
const prompt = `Write a new joke based on the following critique and the original joke. Write the joke between <joke> and </joke> tags.\n\nJoke: ${event.data.joke}\n\nCritique: ${event.data.critique}`;
const response = await llm.complete({ prompt });
// Parse the joke from the response
const joke = response.text.match(/<joke>([\s\S]*?)<\/joke>/)?.[1]?.trim() ?? response.text;
const joke =
response.text.match(/<joke>([\s\S]*?)<\/joke>/)?.[1]?.trim() ??
response.text;
// If we've done less than the max number of iterations, keep iterating
// else, return the result
if (store.numIterations < store.maxIterations) {
if (state.numIterations < state.maxIterations) {
return jokeEvent.with({ joke: joke });
}
return resultEvent.with({ joke: joke, critique: event.data.critique });
});
```
@@ -232,26 +150,23 @@ To run the workflow, we:
### Using Stream Utilities
Workflows provide utility functions to make working with event streams easier:
The `stream` returned by `createContext` contains utility functions to make working with event streams easier:
```typescript
import { collect } from "@llama-flow/core/stream/consumer";
import { until } from "@llama-flow/core/stream/until";
// Create a workflow context and send the initial event
const { stream, sendEvent } = jokeFlow.createContext();
sendEvent(startEvent.with("pirates"));
// Collect all events until we get a resultEvent
const allEvents = await collect(until(stream, resultEvent));
const allEvents = await stream.until(resultEvent).toArray();
// The last event will be the resultEvent
const finalEvent = allEvents[allEvents.length - 1];
const finalEvent = allEvents.at(-1);
console.log(finalEvent.data); // Output the joke and critique
```
The stream utilities make it easier to work with the asynchronous event flow. In this example, we use:
- `collect`: Aggregates all events into an array
- `toArray`: Aggregates all events into an array
- `until`: Creates a stream that emits events until a condition is met (in this case, until a resultEvent is received)
You can combine these utilities with other stream operators like `filter` and `map` to create powerful processing pipelines.
@@ -120,11 +120,11 @@ async function main() {
```ts
import { BEDROCK_MODELS, Bedrock } from "@llamaindex/community";
import { FunctionTool, LLMAgent } from "llamaindex";
import { tool } from "llamaindex";
import { agent } from "@llamaindex/workflow";
import { z } from "zod";
const sumNumbers = FunctionTool.from(
({ a, b }: { a: number; b: number }) => `${a + b}`,
const sumNumbers = tool(
{
name: "sumNumbers",
description: "Use this function to sum two numbers",
@@ -136,11 +136,11 @@ const sumNumbers = FunctionTool.from(
description: "The second number",
}),
}),
execute: ({ a, b }: { a: number; b: number }) => `${a + b}`,
},
);
const divideNumbers = FunctionTool.from(
({ a, b }: { a: number; b: number }) => `${a / b}`,
const divideNumbers = tool(
{
name: "divideNumbers",
description: "Use this function to divide two numbers",
@@ -152,6 +152,7 @@ const divideNumbers = FunctionTool.from(
description: "The divisor b to divide by",
}),
}),
execute: ({ a, b }: { a: number; b: number }) => `${a / b}`,
},
);
@@ -161,15 +162,15 @@ const bedrock = new Bedrock({
});
async function main() {
const agent = new LLMAgent({
const myAgent = agent({
llm: bedrock,
tools: [sumNumbers, divideNumbers],
});
const response = await agent.chat({
message: "How much is 5 + 5? then divide by 2",
});
const response = await myAgent.run(
"How much is 5 + 5? then divide by 2",
);
console.log(response.message);
console.log(response);
}
```
@@ -15,7 +15,7 @@ In LlamaIndex, an agent is a semi-autonomous piece of software powered by an LLM
You'll need to have a recent version of [Node.js](https://nodejs.org/en) installed. Then you can install LlamaIndex.TS by running
```package-install
npm i llamaindex @llamaindex/openai @llamaindex/readers @llamaindex/huggingface
npm i llamaindex @llamaindex/openai @llamaindex/readers @llamaindex/huggingface @llamaindex/workflow
```
## Choose your model
@@ -35,11 +35,16 @@ First we'll need to pull in our dependencies. These are:
import "dotenv/config";
import {
agent,
AgentStream,
tool,
agentStreamEvent,
openai,
} from "@llamaindex/workflow";
import {
tool,
Settings,
} from "llamaindex";
import {
openai,
} from "@llamaindex/openai";
import { z } from "zod";
```
@@ -108,11 +113,10 @@ const myAgent = agent({ tools });
### Ask the agent a question
We can use the `chat` interface to ask our agent a question, and it will use the tools we've defined to find an answer.
We can use the `run` method to ask our agent a question, and it will use the tools we've defined to find an answer.
```javascript
const context = myAgent.run("Sum 101 and 303");
const result = await context;
const result = await myAgent.run("Sum 101 and 303");
console.log(result.data);
```
You will see the following output:
@@ -123,12 +127,13 @@ You will see the following output:
{ result: 'The sum of 101 and 303 is 404.' }
```
To stream the response, you can use the `AgentStream` event which provides chunks of the response as they become available. This allows you to display the response incrementally rather than waiting for the full response:
To stream the response, you need to call `runStream`, which returns a stream of events.
The `agentStreamEvent` provides chunks of the response as they become available. This allows you to display the response incrementally rather than waiting for the full response:
```javascript
const context = myAgent.run("Add 101 and 303");
for await (const event of context) {
if (event instanceof AgentStream) {
const events = myAgent.runStream("Add 101 and 303");
for await (const event of events) {
if (agentStreamEvent.include(event)) {
process.stdout.write(event.data.delta);
}
}
@@ -140,18 +145,18 @@ for await (const event of context) {
The sum of 101 and 303 is 404.
```
Note that we're filtering for `agentStreamEvent` as an agent might return other events - more about that in the following section.
### Logging workflow events
To log the workflow events, you can check the event type and log the event data.
```javascript
const context = myAgent.run("Sum 202 and 404");
for await (const event of context) {
if (event instanceof AgentStream) {
const events = myAgent.runStream("Sum 202 and 404");
for await (const event of events) {
if (agentStreamEvent.include(event)) {
// Stream the response
for (const chunk of event.data.delta) {
process.stdout.write(chunk);
}
process.stdout.write(event.data.delta);
} else {
// Log other events
console.log("\nWorkflow event:", JSON.stringify(event, null, 2));
@@ -30,16 +30,16 @@ Settings.llm = ollama({
### Run local agent
You can also create local agent by importing `agent` from `llamaindex`.
You can also create local agent by importing `agent` from `@llamaindex/workflow`.
```javascript
import { agent } from "llamaindex";
import { agent } from "@llamaindex/workflow";
const workflow = agent({
tools: [getWeatherTool],
});
const workflowContext = workflow.run(
const resutl = workflow.run(
"What's the weather like in San Francisco?",
);
```
@@ -25,7 +25,8 @@ We'll be bringing in `SimpleDirectoryReader`, `HuggingFaceEmbedding`, `VectorSto
```javascript
import { QueryEngineTool, Settings, VectorStoreIndex } from "llamaindex";
import { OpenAI, OpenAIAgent } from "@llamaindex/openai";
import { agent } from "@llamaindex/workflow";
import { openai } from "@llamaindex/openai";
import { HuggingFaceEmbedding } from "@llamaindex/huggingface";
import { SimpleDirectoryReader } from "@llamaindex/readers/directory";
```
@@ -1,5 +1,14 @@
# @llamaindex/cloudflare-worker-agent-test
## 0.0.158
### Patch Changes
- Updated dependencies [2225ffd]
- Updated dependencies [6ddf1c1]
- Updated dependencies [41953a3]
- llamaindex@0.10.4
## 0.0.157
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/cloudflare-worker-agent-test",
"version": "0.0.157",
"version": "0.0.158",
"type": "module",
"private": true,
"scripts": {
@@ -1,5 +1,12 @@
# @llamaindex/llama-parse-browser-test
## 0.0.60
### Patch Changes
- Updated dependencies [2225ffd]
- @llamaindex/cloud@4.0.5
## 0.0.59
### Patch Changes
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/llama-parse-browser-test",
"private": true,
"version": "0.0.59",
"version": "0.0.60",
"type": "module",
"scripts": {
"dev": "vite",
+9
View File
@@ -1,5 +1,14 @@
# @llamaindex/next-agent-test
## 0.1.158
### Patch Changes
- Updated dependencies [2225ffd]
- Updated dependencies [6ddf1c1]
- Updated dependencies [41953a3]
- llamaindex@0.10.4
## 0.1.157
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/next-agent-test",
"version": "0.1.157",
"version": "0.1.158",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,5 +1,14 @@
# test-edge-runtime
## 0.1.157
### Patch Changes
- Updated dependencies [2225ffd]
- Updated dependencies [6ddf1c1]
- Updated dependencies [41953a3]
- llamaindex@0.10.4
## 0.1.156
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/nextjs-edge-runtime-test",
"version": "0.1.156",
"version": "0.1.157",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,5 +1,14 @@
# @llamaindex/next-node-runtime
## 0.1.25
### Patch Changes
- Updated dependencies [2225ffd]
- Updated dependencies [6ddf1c1]
- Updated dependencies [41953a3]
- llamaindex@0.10.4
## 0.1.24
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/next-node-runtime-test",
"version": "0.1.24",
"version": "0.1.25",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,5 +1,14 @@
# vite-import-llamaindex
## 0.0.24
### Patch Changes
- Updated dependencies [2225ffd]
- Updated dependencies [6ddf1c1]
- Updated dependencies [41953a3]
- llamaindex@0.10.4
## 0.0.23
### Patch Changes
@@ -1,7 +1,7 @@
{
"name": "vite-import-llamaindex",
"private": true,
"version": "0.0.23",
"version": "0.0.24",
"type": "module",
"scripts": {
"build": "vite build",
@@ -1,5 +1,14 @@
# @llamaindex/waku-query-engine-test
## 0.0.158
### Patch Changes
- Updated dependencies [2225ffd]
- Updated dependencies [6ddf1c1]
- Updated dependencies [41953a3]
- llamaindex@0.10.4
## 0.0.157
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/waku-query-engine-test",
"version": "0.0.157",
"version": "0.0.158",
"type": "module",
"private": true,
"scripts": {
@@ -1,12 +1,12 @@
import { tool } from "@llamaindex/core/tools";
import { openai } from "@llamaindex/openai";
import fs from "fs";
import {
agent,
AgentToolCall,
AgentToolCallResult,
agentToolCallEvent,
agentToolCallResultEvent,
multiAgent,
tool,
} from "llamaindex";
} from "@llamaindex/workflow";
import fs from "fs";
import os from "os";
import { z } from "zod";
@@ -56,19 +56,19 @@ async function main() {
rootAgent: researchAgent,
});
const context = workflow.run("Write a blog post about history of LLM");
const events = workflow.runStream("Write a blog post about history of LLM");
let finalResult;
for await (const event of context) {
if (event instanceof AgentToolCall) {
for await (const event of events) {
if (agentToolCallEvent.include(event)) {
console.log(
`[Agent ${event.displayName}] executing tool ${event.data.toolName} with parameters ${JSON.stringify(
`[Agent ${event.data.agentName}] executing tool ${event.data.toolName} with parameters ${JSON.stringify(
event.data.toolKwargs,
)}`,
);
} else if (event instanceof AgentToolCallResult) {
} else if (agentToolCallResultEvent.include(event)) {
console.log(
`[Agent ${event.displayName}] executed tool ${event.data.toolName} with result ${event.data.toolOutput.result}`,
`[Tool ${event.data.toolName}] executed with result ${event.data.toolOutput.result}`,
);
}
finalResult = event;
@@ -1,5 +1,6 @@
import { OpenAI } from "@llamaindex/openai";
import { FunctionTool, agent } from "llamaindex";
import { agent } from "@llamaindex/workflow";
import { tool } from "llamaindex";
import { z } from "zod";
const csvData =
@@ -11,24 +12,22 @@ const userQuestion = "which are the best comedies after 2010?";
// The agent will succeed if we increase `maxTokens` to 1024
const llm = new OpenAI({ model: "gpt-4-turbo", maxTokens: 1024 });
const interpreterTool = FunctionTool.from(
({ code }) => {
const interpreterTool = tool({
name: "interpreter",
description:
"Execute python code in a Jupyter notebook cell and return any result, stdout, stderr, display_data, and error.",
parameters: z.object({
code: z.string({
description: "The python code to execute in a single cell.",
}),
}),
execute: ({ code }) => {
console.log(
`To answer the user's question, call the following code:\n${code}`,
);
return code;
},
{
name: "interpreter",
description:
"Execute python code in a Jupyter notebook cell and return any result, stdout, stderr, display_data, and error.",
parameters: z.object({
code: z.string({
description: "The python code to execute in a single cell.",
}),
}),
},
);
});
const systemPrompt =
"You are a Python interpreter.\n - You are given tasks to complete and you run python code to solve them.\n - The python code runs in a Jupyter notebook. Every time you call $(interpreter) tool, the python code is executed in a separate cell. It's okay to make multiple calls to $(interpreter).\n - Display visualizations using matplotlib or any other visualization library directly in the notebook. Shouldn't save the visualizations to a file, just return the base64 encoded data.\n - You can install any pip package (if it exists) if you need to but the usual packages for data analysis are already preinstalled.\n - You can run any python code you want in a secure environment.";
@@ -1,6 +1,6 @@
import { openai } from "@llamaindex/openai";
import { mcp } from "@llamaindex/tools";
import { agent } from "llamaindex";
import { agent } from "@llamaindex/workflow";
async function main() {
// Create an MCP server for filesystem tools
@@ -6,15 +6,15 @@
import { openai } from "@llamaindex/openai";
import {
agent,
AgentInput,
AgentOutput,
AgentStream,
AgentToolCall,
AgentToolCallResult,
agentInputEvent,
agentOutputEvent,
agentStreamEvent,
agentToolCallEvent,
agentToolCallResultEvent,
multiAgent,
StopEvent,
tool,
} from "llamaindex";
stopAgentEvent,
} from "@llamaindex/workflow";
import { tool } from "llamaindex";
import { z } from "zod";
const llm = openai({
@@ -79,21 +79,21 @@ async function multiWeatherAgent() {
});
// Ask the agent to get the weather in a city
const context = workflow.run(
const events = workflow.runStream(
"What is the weather in San Francisco in Celsius?",
);
// Stream the events
for await (const event of context) {
// These events might be useful for UI
for await (const event of events) {
// These events are useful for reporting the current state to the user in the UI
if (
event instanceof AgentToolCall ||
event instanceof AgentToolCallResult ||
event instanceof AgentOutput ||
event instanceof AgentInput ||
event instanceof StopEvent
agentToolCallEvent.include(event) ||
agentToolCallResultEvent.include(event) ||
agentOutputEvent.include(event) ||
agentInputEvent.include(event) ||
stopAgentEvent.include(event)
) {
console.log(event);
} else if (event instanceof AgentStream) {
} else if (agentStreamEvent.include(event)) {
for (const chunk of event.data.delta) {
process.stdout.write(chunk);
}
@@ -1,5 +1,6 @@
import { openai } from "@llamaindex/openai";
import { agent, tool } from "llamaindex";
import { agent } from "@llamaindex/workflow";
import { tool } from "llamaindex";
import { z } from "zod";
const sumNumbers = tool({
@@ -1,11 +1,9 @@
import {
AgentStream,
AgentToolCallResult,
Document,
VectorStoreIndex,
agent,
openai,
} from "llamaindex";
agentStreamEvent,
agentToolCallResultEvent,
} from "@llamaindex/workflow";
import { Document, VectorStoreIndex, openai } from "llamaindex";
async function main() {
const index = await VectorStoreIndex.fromDocuments([
@@ -30,15 +28,15 @@ async function main() {
],
});
const context = myAgent.run("The fact about cats");
const events = myAgent.runStream("The fact about cats");
for await (const event of context) {
if (event instanceof AgentToolCallResult) {
for await (const event of events) {
if (agentToolCallResultEvent.include(event)) {
console.log(
"Using these retrieved information to answer the question:\n",
event.data.toolOutput.result,
);
} else if (event instanceof AgentStream) {
} else if (agentStreamEvent.include(event)) {
for (const chunk of event.data.delta) {
process.stdout.write(chunk);
}
@@ -2,8 +2,8 @@
* This example shows how to use a single agent with a tool
*/
import { openai } from "@llamaindex/openai";
import { agent } from "llamaindex";
import { getWeatherTool } from "../agent/utils/tools";
import { agent } from "@llamaindex/workflow";
import { getWeatherTool } from "../deprecated/utils/tools";
async function main() {
const weatherAgent = agent({
@@ -14,14 +14,14 @@ async function main() {
verbose: false,
});
// Run the agent and keep the context
const context = weatherAgent.run("What's the weather like in San Francisco?");
const result = await context;
const result = await weatherAgent.run(
"What's the weather like in San Francisco?",
);
console.log(`${JSON.stringify(result, null, 2)}`);
// Reuse the context from the previous run
// Reuse the state from the previous run
const caResult = await weatherAgent.run("Compare it with California?", {
context: context.data,
state: result.data.state,
});
console.log(`${JSON.stringify(caResult, null, 2)}`);
}
@@ -1,6 +1,6 @@
import { OpenAI } from "@llamaindex/openai";
import { wiki } from "@llamaindex/tools";
import { AgentStream, agent } from "llamaindex";
import { agent, agentStreamEvent } from "@llamaindex/workflow";
async function main() {
const llm = new OpenAI({ model: "gpt-4-turbo" });
@@ -12,10 +12,10 @@ async function main() {
});
// Chat with the agent
const context = workflow.run("Who was Goethe?");
const events = workflow.runStream("Who was Goethe?");
for await (const event of context) {
if (event instanceof AgentStream) {
for await (const event of events) {
if (agentStreamEvent.include(event)) {
for (const chunk of event.data.delta) {
process.stdout.write(chunk);
}
@@ -1,11 +1,11 @@
import fs from "fs";
import {
agent,
AgentToolCall,
AgentToolCallResult,
agentToolCallEvent,
agentToolCallResultEvent,
multiAgent,
tool,
} from "llamaindex";
} from "@llamaindex/workflow";
import fs from "fs";
import { tool } from "llamaindex";
import { z } from "zod";
import { anthropic } from "@llamaindex/anthropic";
@@ -81,21 +81,21 @@ async function main() {
rootAgent: researchAgent,
});
const context = workflow.run(
const events = workflow.runStream(
"Write a report about New York weather and inflation",
);
let finalResult;
for await (const event of context) {
if (event instanceof AgentToolCall) {
for await (const event of events) {
if (agentToolCallEvent.include(event)) {
console.log(
`[Agent ${event.displayName}] executing tool ${event.data.toolName} with parameters ${JSON.stringify(
`[Agent ${event.data.agentName}] executing tool ${event.data.toolName} with parameters ${JSON.stringify(
event.data.toolKwargs,
)}`,
);
} else if (event instanceof AgentToolCallResult) {
} else if (agentToolCallResultEvent.include(event)) {
console.log(
`[Agent ${event.displayName}] executed tool ${event.data.toolName} with result ${event.data.toolOutput.result}`,
`[Agent executed tool ${event.data.toolName} with result ${event.data.toolOutput.result}`,
);
}
finalResult = event;
@@ -1,6 +1,6 @@
import { ollama } from "@llamaindex/ollama";
import { agent } from "llamaindex";
import { getWeatherTool } from "../agent/utils/tools";
import { agent } from "@llamaindex/workflow";
import { getWeatherTool } from "../deprecated/utils/tools";
async function main() {
const myAgent = agent({
+94
View File
@@ -0,0 +1,94 @@
import { openai } from "@llamaindex/openai";
import {
createStatefulMiddleware,
createWorkflow,
workflowEvent,
} from "@llamaindex/workflow";
// Create LLM instance
const llm = openai({ model: "gpt-4.1-mini" });
// Define our workflow events
const startEvent = workflowEvent<string>(); // Input topic for joke
const jokeEvent = workflowEvent<{ joke: string }>(); // Intermediate joke
const critiqueEvent = workflowEvent<{ joke: string; critique: string }>(); // Intermediate critique
const resultEvent = workflowEvent<{ joke: string; critique: string }>(); // Final joke + critique
// Create our workflow
const { withState, getContext } = createStatefulMiddleware(() => ({
numIterations: 0,
maxIterations: 3,
}));
const jokeFlow = withState(createWorkflow());
// Define handlers for each step
jokeFlow.handle([startEvent], async (event) => {
// Prompt the LLM to write a joke
const prompt = `Write your best joke about ${event.data}. Write the joke between <joke> and </joke> tags.`;
const response = await llm.complete({ prompt });
// Parse the joke from the response
const joke =
response.text.match(/<joke>([\s\S]*?)<\/joke>/)?.[1]?.trim() ??
response.text;
return jokeEvent.with({ joke: joke });
});
jokeFlow.handle([jokeEvent], async (event) => {
// Prompt the LLM to critique the joke
const prompt = `Give a thorough critique of the following joke. If the joke needs improvement, put "IMPROVE" somewhere in the critique: ${event.data.joke}`;
const response = await llm.complete({ prompt });
// If the critique includes "IMPROVE", keep iterating, else, return the result
if (response.text.includes("IMPROVE")) {
return critiqueEvent.with({
joke: event.data.joke,
critique: response.text,
});
}
return resultEvent.with({ joke: event.data.joke, critique: response.text });
});
jokeFlow.handle([critiqueEvent], async (event) => {
// Keep track of the number of iterations
const state = getContext().state;
state.numIterations++;
// Write a new joke based on the previous joke and critique
const prompt = `Write a new joke based on the following critique and the original joke. Write the joke between <joke> and </joke> tags.\n\nJoke: ${event.data.joke}\n\nCritique: ${event.data.critique}`;
const response = await llm.complete({ prompt });
// Parse the joke from the response
const joke =
response.text.match(/<joke>([\s\S]*?)<\/joke>/)?.[1]?.trim() ??
response.text;
// If we've done less than the max number of iterations, keep iterating
// else, return the result
if (state.numIterations < state.maxIterations) {
return jokeEvent.with({ joke: joke });
}
return resultEvent.with({ joke: joke, critique: event.data.critique });
});
// Usage
async function main() {
const { stream, sendEvent } = jokeFlow.createContext();
sendEvent(startEvent.with("pirates"));
let result: { joke: string; critique: string } | undefined;
for await (const event of stream) {
// console.log(event.data); optionally log the event data
if (resultEvent.include(event)) {
result = event.data;
break; // Stop when we get the final result
}
}
console.log(result);
}
main().catch(console.error);
+2 -1
View File
@@ -1,6 +1,7 @@
import { anthropic } from "@llamaindex/anthropic";
import { wiki } from "@llamaindex/tools";
import { agent, tool } from "llamaindex";
import { agent } from "@llamaindex/workflow";
import { tool } from "llamaindex";
import { z } from "zod";
const workflow = agent({
+2 -1
View File
@@ -1,5 +1,6 @@
import { gemini, GEMINI_MODEL } from "@llamaindex/google";
import { agent, tool } from "llamaindex";
import { agent } from "@llamaindex/workflow";
import { tool } from "llamaindex";
import { z } from "zod";
const sumNumbers = tool({
-17
View File
@@ -1,17 +0,0 @@
# Run LlamaIndex Server with simple steps
1. Setup environment variables
```bash
export OPENAI_API_KEY=<your-openai-api-key>
```
2. Run the server
```bash
npx tsx llamaindex-server/simple-workflow/index.ts
```
3. Open the app at `http://localhost:4000` and start chatting with the agent
![Screenshot](./screenshot.png)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

@@ -1,19 +0,0 @@
import { OpenAI } from "@llamaindex/openai";
import { LlamaIndexServer } from "@llamaindex/server";
import { weather } from "@llamaindex/tools";
import "dotenv/config";
import { agent } from "llamaindex";
const weatherAgent = agent({
tools: [weather()],
llm: new OpenAI({ model: "gpt-4o-mini" }),
});
new LlamaIndexServer({
workflow: () => weatherAgent,
uiConfig: {
appTitle: "Weather Agent",
starterQuestions: ["Ho Chi Minh city weather", "New York weather"],
},
port: 4000,
}).start();
+3 -1
View File
@@ -1,6 +1,8 @@
import { mistral } from "@llamaindex/mistral";
import { wiki } from "@llamaindex/tools";
import { agent, tool } from "llamaindex";
import { agent } from "@llamaindex/workflow";
import { tool } from "llamaindex";
import { z } from "zod";
const workflow = agent({
-32
View File
@@ -1,32 +0,0 @@
import { StartEvent, StopEvent, Workflow } from "llamaindex";
type ContextData = {
counter: number;
};
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
workflow.addStep(
{
inputs: [StartEvent<string>],
},
async (context, startEvent) => {
const input = startEvent.data;
context.data.counter++;
return new StopEvent(`Hello, ${input}!`);
},
);
{
const ret = await workflow.run("Alex", contextData);
console.log(ret.data); // Hello, Alex!
}
{
const ret = await workflow.run("World", contextData);
console.log(ret.data); // Hello, World!
}
console.log(contextData.counter); // 2
+2 -1
View File
@@ -1,6 +1,7 @@
import { openaiResponses } from "@llamaindex/openai";
import { wiki } from "@llamaindex/tools";
import { agent, tool } from "llamaindex";
import { agent } from "@llamaindex/workflow";
import { tool } from "llamaindex";
import { z } from "zod";
const workflow = agent({
-1
View File
@@ -50,7 +50,6 @@
"@llamaindex/together": "^0.0.13",
"@llamaindex/jinaai": "^0.0.13",
"@llamaindex/perplexity": "^0.0.10",
"@llamaindex/server": "^0.1.6",
"@llamaindex/supabase": "^0.1.2",
"@llamaindex/tools": "^0.0.8",
"@notionhq/client": "^2.2.15",
+3 -2
View File
@@ -15,9 +15,10 @@
"circular-check": "madge --circular ./packages/**/**/dist/index.js",
"release": "pnpm run build && changeset publish",
"release-snapshot": "pnpm run build && changeset publish --tag snapshot",
"new-version": "changeset version && pnpm format:write && pnpm run build",
"new-version": "changeset version && pnpm postversion && pnpm format:write && pnpm run build",
"new-snapshot": "pnpm run build && changeset version --snapshot",
"lint-staged": "lint-staged"
"lint-staged": "lint-staged",
"postversion": "node scripts/repin-workflow.mjs"
},
"devDependencies": {
"@changesets/cli": "^2.27.5",
+9
View File
@@ -1,5 +1,14 @@
# @llamaindex/autotool
## 7.0.4
### Patch Changes
- Updated dependencies [2225ffd]
- Updated dependencies [6ddf1c1]
- Updated dependencies [41953a3]
- llamaindex@0.10.4
## 7.0.3
### Patch Changes
@@ -1,5 +1,15 @@
# @llamaindex/autotool-01-node-example
## 0.0.105
### Patch Changes
- Updated dependencies [2225ffd]
- Updated dependencies [6ddf1c1]
- Updated dependencies [41953a3]
- llamaindex@0.10.4
- @llamaindex/autotool@7.0.4
## 0.0.104
### Patch Changes
@@ -13,5 +13,5 @@
"scripts": {
"start": "node --import tsx --import @llamaindex/autotool/node ./src/index.ts"
},
"version": "0.0.104"
"version": "0.0.105"
}
+1 -1
View File
@@ -6,7 +6,7 @@
"url": "git+https://github.com/run-llama/LlamaIndexTS.git",
"directory": "packages/autotool"
},
"version": "7.0.3",
"version": "7.0.4",
"description": "auto transpile your JS function to LLM Agent compatible",
"files": [
"dist",
+6
View File
@@ -1,5 +1,11 @@
# @llamaindex/cloud
## 4.0.5
### Patch Changes
- 2225ffd: feat: bump llama cloud sdk
## 4.0.4
### Patch Changes
-9
View File
@@ -2,15 +2,6 @@
> 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.
## Usage
```ts
import { OpenAPI } from "@llamaindex/cloud/api";
OpenAPI.TOKEN = "YOUR_API_KEY";
OpenAPI.BASE = "https://api.cloud.llamaindex.ai/";
// ...
```
For more information, see the [API documentation](https://docs.cloud.llamaindex.ai/).
## License
+4 -7
View File
@@ -1,22 +1,19 @@
import { defineConfig } from "@hey-api/openapi-ts";
import { defaultPlugins, defineConfig } from "@hey-api/openapi-ts";
export default defineConfig({
// you can download this file to get the latest version of the OpenAPI document
// @link https://api.cloud.llamaindex.ai/api/openapi.json
input: "./openapi.json",
client: "@hey-api/client-fetch",
output: {
path: "./src/client",
format: "prettier",
lint: "eslint",
},
plugins: [
"@hey-api/schemas",
"@hey-api/sdk",
...defaultPlugins,
"@hey-api/client-fetch",
{
enums: "javascript",
identifierCase: "preserve",
name: "@hey-api/typescript",
name: "@hey-api/sdk",
},
],
});
+2975 -4384
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/cloud",
"version": "4.0.4",
"version": "4.0.5",
"type": "module",
"license": "MIT",
"scripts": {
@@ -55,8 +55,8 @@
"directory": "packages/cloud"
},
"devDependencies": {
"@hey-api/client-fetch": "^0.6.0",
"@hey-api/openapi-ts": "^0.61.0",
"@hey-api/client-fetch": "^0.10.0",
"@hey-api/openapi-ts": "^0.66.7",
"@llamaindex/core": "workspace:*",
"@llamaindex/env": "workspace:*"
},
+10
View File
@@ -1 +1,11 @@
import { client } from "./client/client.gen";
client.setConfig({
baseUrl: "https://api.cloud.llamaindex.ai/",
headers: {
"X-SDK-Name": "llamaindex-ts",
},
});
export * from "./client";
export { client };
+26 -15
View File
@@ -4,7 +4,8 @@ import { Document, FileReader } from "@llamaindex/core/schema";
import { fs, getEnv, path } from "@llamaindex/env";
import pRetry from "p-retry";
import {
type Body_upload_file_api_v1_parsing_upload_post,
type BodyUploadFileApiParsingUploadPost,
type FailPageMode,
type ParserLanguages,
type ParsingMode,
getJobApiV1ParsingJobJobIdGet,
@@ -162,6 +163,15 @@ export class LlamaParseReader extends FileReader {
content_guideline_instruction?: string | undefined;
adaptive_long_table?: boolean | undefined;
model?: string | undefined;
auto_mode_configuration_json?: string | undefined;
compact_markdown_table?: boolean | undefined;
markdown_table_multiline_header_separator?: string | undefined;
page_error_tolerance?: number | undefined;
replace_failed_page_mode?: FailPageMode | undefined;
replace_failed_page_with_error_message_prefix?: string | undefined;
replace_failed_page_with_error_message_suffix?: string | undefined;
save_images?: boolean | undefined;
preset?: string | undefined;
constructor(
params: Partial<Omit<LlamaParseReader, "language" | "apiKey">> & {
@@ -331,11 +341,23 @@ export class LlamaParseReader extends FileReader {
content_guideline_instruction: this.content_guideline_instruction,
adaptive_long_table: this.adaptive_long_table,
model: this.model,
auto_mode_configuration_json: this.auto_mode_configuration_json,
compact_markdown_table: this.compact_markdown_table,
markdown_table_multiline_header_separator:
this.markdown_table_multiline_header_separator,
page_error_tolerance: this.page_error_tolerance,
replace_failed_page_mode: this.replace_failed_page_mode,
replace_failed_page_with_error_message_prefix:
this.replace_failed_page_with_error_message_prefix,
replace_failed_page_with_error_message_suffix:
this.replace_failed_page_with_error_message_suffix,
save_images: this.save_images,
preset: this.preset,
} satisfies {
[Key in keyof Body_upload_file_api_v1_parsing_upload_post]-?:
| Body_upload_file_api_v1_parsing_upload_post[Key]
[Key in keyof BodyUploadFileApiParsingUploadPost]-?:
| BodyUploadFileApiParsingUploadPost[Key]
| undefined;
} as unknown as Body_upload_file_api_v1_parsing_upload_post;
} as unknown as BodyUploadFileApiParsingUploadPost;
const response = await uploadFileApiV1ParsingUploadPost({
client: this.#client,
@@ -382,10 +404,6 @@ export class LlamaParseReader extends FileReader {
client: this.#client,
throwOnError: true,
path: { job_id: jobId },
query: {
project_id: this.project_id ?? null,
organization_id: this.organization_id ?? null,
},
signal: AbortSignal.timeout(this.maxTimeout * 1000),
}),
{
@@ -431,7 +449,6 @@ export class LlamaParseReader extends FileReader {
throwOnError: true,
path: { job_id: jobId },
query: {
project_id: this.project_id ?? null,
organization_id: this.organization_id ?? null,
},
signal: AbortSignal.timeout(this.maxTimeout * 1000),
@@ -445,7 +462,6 @@ export class LlamaParseReader extends FileReader {
throwOnError: true,
path: { job_id: jobId },
query: {
project_id: this.project_id ?? null,
organization_id: this.organization_id ?? null,
},
signal: AbortSignal.timeout(this.maxTimeout * 1000),
@@ -459,7 +475,6 @@ export class LlamaParseReader extends FileReader {
throwOnError: true,
path: { job_id: jobId },
query: {
project_id: this.project_id ?? null,
organization_id: this.organization_id ?? null,
},
signal: AbortSignal.timeout(this.maxTimeout * 1000),
@@ -689,10 +704,6 @@ export class LlamaParseReader extends FileReader {
job_id: jobId,
name: imageName,
},
query: {
project_id: this.project_id ?? null,
organization_id: this.organization_id ?? null,
},
});
if (response.error) {
throw new Error(`Failed to download image: ${response.error.detail}`);
+9
View File
@@ -1,5 +1,14 @@
# @llamaindex/experimental
## 0.0.174
### Patch Changes
- Updated dependencies [2225ffd]
- Updated dependencies [6ddf1c1]
- Updated dependencies [41953a3]
- llamaindex@0.10.4
## 0.0.173
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/experimental",
"description": "Experimental package for LlamaIndexTS",
"version": "0.0.173",
"version": "0.0.174",
"type": "module",
"types": "dist/type/index.d.ts",
"main": "dist/cjs/index.js",
+13
View File
@@ -1,5 +1,18 @@
# llamaindex
## 0.10.4
### Patch Changes
- 2225ffd: feat: bump llama cloud sdk
- 6ddf1c1: Show warning to use @llamaindex/workflow when using depracted workflows
- 41953a3: fix: node10 module resolution fail in sub llamaindex packages
- Updated dependencies [7e8e454]
- Updated dependencies [2225ffd]
- Updated dependencies [bc53342]
- @llamaindex/workflow@1.1.0
- @llamaindex/cloud@4.0.5
## 0.10.3
### Patch Changes
+8
View File
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
+8
View File
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
+8
View File
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
+8
View File
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
+8
View File
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
+8
View File
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "llamaindex",
"version": "0.10.3",
"version": "0.10.4",
"license": "MIT",
"type": "module",
"keywords": [
@@ -25,7 +25,7 @@
"@llamaindex/env": "workspace:*",
"@llamaindex/node-parser": "workspace:*",
"@llamaindex/openai": "workspace:*",
"@llamaindex/workflow": "1.0.4",
"@llamaindex/workflow": "1.0.3",
"@types/lodash": "^4.17.7",
"@types/node": "^22.9.0",
"ajv": "^8.17.1",
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
@@ -1,5 +1,5 @@
import {
addFilesToPipelineApiV1PipelinesPipelineIdFilesPut,
addFilesToPipelineApiApiV1PipelinesPipelineIdFilesPut,
getPipelineFileStatusApiV1PipelinesPipelineIdFilesFileIdStatusGet,
listPipelineFilesApiV1PipelinesPipelineIdFilesGet,
listProjectsApiV1ProjectsGet,
@@ -56,7 +56,7 @@ export class LLamaCloudFileService {
custom_metadata: { file_id: file.id, ...customMetadata },
},
];
await addFilesToPipelineApiV1PipelinesPipelineIdFilesPut({
await addFilesToPipelineApiApiV1PipelinesPipelineIdFilesPut({
path: {
pipeline_id: pipelineId,
},
@@ -18,7 +18,7 @@ import {
deletePipelineDocumentApiV1PipelinesPipelineIdDocumentsDocumentIdDelete,
getPipelineDocumentStatusApiV1PipelinesPipelineIdDocumentsDocumentIdStatusGet,
getPipelineStatusApiV1PipelinesPipelineIdStatusGet,
type PipelineCreate,
type PipelineCreateReadable,
searchPipelinesApiV1PipelinesGet,
upsertBatchPipelineDocumentsApiV1PipelinesPipelineIdDocumentsPut,
upsertPipelineApiV1PipelinesPut,
@@ -182,8 +182,8 @@ export class LlamaCloudIndex {
verbose?: boolean;
} & CloudConstructorParams,
config?: {
embedding: PipelineCreate["embedding_config"];
transform: PipelineCreate["transform_config"];
embedding: PipelineCreateReadable["embedding_config"];
transform: PipelineCreateReadable["transform_config"];
},
): Promise<LlamaCloudIndex> {
const index = new LlamaCloudIndex({ ...params });
@@ -348,8 +348,8 @@ export class LlamaCloudIndex {
}
public async ensureIndex(config?: {
embedding?: PipelineCreate["embedding_config"];
transform?: PipelineCreate["transform_config"];
embedding?: PipelineCreateReadable["embedding_config"];
transform?: PipelineCreateReadable["transform_config"];
verbose?: boolean;
}): Promise<void> {
const projectId = await this.getProjectId();
+1 -1
View File
@@ -68,7 +68,6 @@ export * from "@llamaindex/core/storage/index-store";
export * from "@llamaindex/core/storage/kv-store";
export * from "@llamaindex/core/utils";
export * from "@llamaindex/openai";
export * from "@llamaindex/workflow";
export * from "./agent/index.js";
export * from "./cloud/index.js";
export * from "./engines/index.js";
@@ -86,4 +85,5 @@ export * from "./selectors/index.js";
export * from "./storage/StorageContext.js";
export * from "./tools/index.js";
export * from "./types.js";
export * from "./workflow.js";
export { Settings };
+19
View File
@@ -0,0 +1,19 @@
import { Workflow as OriginalWorkflow } from "@llamaindex/workflow";
export * from "@llamaindex/workflow";
/**
* @deprecated The Workflow class is deprecated. Please import directly from "@llamaindex/workflow" in the future.
*/
export class Workflow<ContextData, Start, Stop> extends OriginalWorkflow<
ContextData,
Start,
Stop
> {
constructor(...args: any[]) {
// Need to figure out the constructor args for Workflow
console.warn(
"The Workflow class exported from 'llamaindex' is deprecated. Please use workflows directly from '@llamaindex/workflow' in the future. See https://ts.llamaindex.ai/docs/llamaindex/modules/agents/workflows for usage.",
);
super(...args);
}
}
+8
View File
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
+8
View File
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
@@ -0,0 +1,8 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
+10
View File
@@ -1,5 +1,15 @@
# @llamaindex/workflow
## 1.1.0
### Minor Changes
- bc53342: Update workflows to llama-flow syntax
### Patch Changes
- 7e8e454: Bump llama-flow@0.4.1
## 1.0.4
### Patch Changes
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/workflow",
"description": "Workflow API",
"version": "1.0.4",
"version": "1.1.0",
"type": "module",
"types": "dist/index.d.ts",
"module": "dist/index.js",
@@ -48,6 +48,6 @@
"zod": "^3.23.8"
},
"dependencies": {
"@llama-flow/llamaindex": "^0.0.12"
"@llama-flow/core": "^0.4.1"
}
}
+207 -169
View File
@@ -1,23 +1,32 @@
import {
StartEvent,
type StepContext,
StopEvent,
Workflow,
WorkflowEvent,
} from "@llama-flow/llamaindex";
import type { ChatMessage } from "@llamaindex/core/llms";
createWorkflow,
getContext,
workflowEvent,
type Handler,
type Workflow,
type WorkflowContext,
type WorkflowEvent,
type WorkflowEventData,
} from "@llama-flow/core";
import { createStatefulMiddleware } from "@llama-flow/core/middleware/state";
import { Settings } from "@llamaindex/core/global";
import type { ChatMessage, MessageContent } from "@llamaindex/core/llms";
import { ChatMemoryBuffer } from "@llamaindex/core/memory";
import { PromptTemplate } from "@llamaindex/core/prompts";
import { FunctionTool } from "@llamaindex/core/tools";
import { stringifyJSONToMessageContent } from "@llamaindex/core/utils";
import { z } from "zod";
import type { AgentWorkflowContext, BaseWorkflowAgent } from "./base";
import type { AgentWorkflowState, BaseWorkflowAgent } from "./base";
import {
AgentInput,
AgentOutput,
AgentSetup,
AgentToolCall,
AgentToolCallResult,
agentInputEvent,
agentOutputEvent,
agentSetupEvent,
agentToolCallEvent,
agentToolCallResultEvent,
type AgentInput,
type AgentSetup,
type AgentToolCall,
type AgentToolCallResult,
} from "./events";
import { FunctionAgent, type FunctionAgentParams } from "./function-agent";
@@ -38,23 +47,42 @@ export type AgentInputData = {
userInput?: string | undefined;
chatHistory?: ChatMessage[] | undefined;
};
export const startAgentEvent = workflowEvent<
AgentInputData,
"llamaindex-start"
>({
debugLabel: "llamaindex-start",
});
export type AgentResultData = {
result: MessageContent;
state?: AgentWorkflowState | undefined;
};
export const stopAgentEvent = workflowEvent<AgentResultData, "llamaindex-stop">(
{
debugLabel: "llamaindex-stop",
},
);
// Wrapper events for multiple tool calls and results
export class ToolCallsEvent extends WorkflowEvent<{
export type ToolCalls = {
agentName: string;
toolCalls: AgentToolCall[];
}> {}
};
export const toolCallsEvent = workflowEvent<ToolCalls>();
export class ToolResultsEvent extends WorkflowEvent<{
export type ToolResults = {
agentName: string;
results: AgentToolCallResult[];
}> {}
};
export const toolResultsEvent = workflowEvent<ToolResults>();
export class AgentStepEvent extends WorkflowEvent<{
export type AgentStep = {
agentName: string;
response: ChatMessage;
toolCalls: AgentToolCall[];
}> {}
};
export const agentStepEvent = workflowEvent<AgentStep>();
export type SingleAgentParams = FunctionAgentParams & {
/**
@@ -112,14 +140,16 @@ export const agent = (params: SingleAgentParams): AgentWorkflow => {
* based on the LlamaIndexTS workflow system. It supports single agent workflows
* with multiple tools.
*/
export class AgentWorkflow {
private workflow: Workflow<AgentWorkflowContext, AgentInputData, string>;
export class AgentWorkflow implements Workflow {
private stateful = createStatefulMiddleware(
(state: AgentWorkflowState) => state,
);
private workflow = this.stateful.withState(createWorkflow());
private agents: Map<string, BaseWorkflowAgent> = new Map();
private verbose: boolean;
private rootAgentName: string;
constructor({ agents, rootAgent, verbose, timeout }: AgentWorkflowParams) {
this.workflow = new Workflow();
constructor({ agents, rootAgent, verbose }: AgentWorkflowParams) {
this.verbose = verbose ?? false;
// Handle AgentWorkflow cases for agents
@@ -162,6 +192,18 @@ export class AgentWorkflow {
}
this.addAgents(processedAgents);
this.setupWorkflowSteps();
}
handle<
const AcceptEvents extends WorkflowEvent<unknown>[],
Result extends ReturnType<WorkflowEvent<unknown>["with"]> | void,
>(accept: AcceptEvents, handler: Handler<AcceptEvents, Result>): void {
this.workflow.handle(accept, handler);
}
createContext(): WorkflowContext {
return this.workflow.createContext(this.createInitialState());
}
private addAgents(agents: BaseWorkflowAgent[]): void {
@@ -255,13 +297,13 @@ export class AgentWorkflow {
}
private handleInputStep = async (
ctx: StepContext<AgentWorkflowContext>,
event: StartEvent<AgentInputData>,
): Promise<AgentInput> => {
event: WorkflowEventData<AgentInputData>,
) => {
const { state } = this.stateful.getContext();
const { userInput, chatHistory } = event.data;
const memory = ctx.data.memory;
const memory = state.memory;
if (chatHistory) {
chatHistory.forEach((message) => {
chatHistory.forEach((message: ChatMessage) => {
memory.put(message);
});
}
@@ -279,21 +321,17 @@ export class AgentWorkflow {
"Either provide a user message or a chat history with a user message as the last message",
);
}
ctx.data.userInput = lastMessage.content as string;
} else {
throw new Error("No user message or chat history provided");
}
return new AgentInput({
return agentInputEvent.with({
input: await memory.getMessages(),
currentAgentName: this.rootAgentName,
});
};
private setupAgent = async (
ctx: StepContext<AgentWorkflowContext>,
event: AgentInput,
): Promise<AgentSetup> => {
private setupAgent = async (event: WorkflowEventData<AgentInput>) => {
const currentAgentName = event.data.currentAgentName;
const agent = this.agents.get(currentAgentName);
if (!agent) {
@@ -308,16 +346,14 @@ export class AgentWorkflow {
});
}
return new AgentSetup({
return agentSetupEvent.with({
input: llmInput,
currentAgentName: currentAgentName,
});
};
private runAgentStep = async (
ctx: StepContext<AgentWorkflowContext>,
event: AgentSetup,
) => {
private runAgentStep = async (event: WorkflowEventData<AgentSetup>) => {
const { sendEvent } = this.stateful.getContext();
const agent = this.agents.get(event.data.currentAgentName);
if (!agent) {
throw new Error("No valid agent found");
@@ -329,24 +365,32 @@ export class AgentWorkflow {
);
}
const output = await agent.takeStep(ctx, event.data.input, agent.tools);
const output = await agent.takeStep(
this.stateful.getContext(),
this.stateful.getContext().state,
event.data.input,
agent.tools,
);
ctx.sendEvent(
new AgentStepEvent({
sendEvent(
agentStepEvent.with({
agentName: agent.name,
response: output.data.response,
toolCalls: output.data.toolCalls,
response: output.response,
toolCalls: output.toolCalls,
}),
);
ctx.sendEvent(output);
sendEvent(agentOutputEvent.with(output));
};
private parseAgentOutput = async (
ctx: StepContext<AgentWorkflowContext>,
event: AgentStepEvent,
): Promise<ToolCallsEvent | StopEvent<{ result: string }>> => {
private parseAgentOutput = async (event: WorkflowEventData<AgentStep>) => {
const { agentName, response, toolCalls } = event.data;
const agent = this.agents.get(agentName);
if (!agent) {
throw new Error(
`parseAgentOutput failed: agent ${agentName} does not exist`,
);
}
// If no tool calls, return final response
if (!toolCalls || toolCalls.length === 0) {
@@ -355,31 +399,31 @@ export class AgentWorkflow {
`[Agent ${agentName}]: No tool calls to process, returning final response`,
);
}
const agentOutput = new AgentOutput({
const agentOutput = {
response,
toolCalls: [],
raw: response,
currentAgentName: agentName,
});
const content = await this.agents
.get(agentName)
?.finalize(ctx, agentOutput, ctx.data.memory);
};
const content = await agent.finalize(
this.stateful.getContext().state,
agentOutput,
);
return new StopEvent({
result: content?.data.response.content as string,
return stopAgentEvent.with({
result: content.response.content,
state: this.stateful.getContext().state,
});
}
return new ToolCallsEvent({
return toolCallsEvent.with({
agentName,
toolCalls,
});
};
private executeToolCalls = async (
ctx: StepContext<AgentWorkflowContext>,
event: ToolCallsEvent,
): Promise<ToolResultsEvent | StopEvent<{ result: string }>> => {
private executeToolCalls = async (event: WorkflowEventData<ToolCalls>) => {
const { sendEvent } = getContext();
const { agentName, toolCalls } = event.data;
const agent = this.agents.get(agentName);
if (!agent) {
@@ -391,44 +435,42 @@ export class AgentWorkflow {
// Execute each tool call
for (const toolCall of toolCalls) {
// Send single tool call event, useful for UI
ctx.sendEvent(toolCall);
const toolResult = new AgentToolCallResult({
toolName: toolCall.data.toolName,
toolKwargs: toolCall.data.toolKwargs,
toolId: toolCall.data.toolId,
sendEvent(agentToolCallEvent.with(toolCall));
const toolResult = {
toolName: toolCall.toolName,
toolKwargs: toolCall.toolKwargs,
toolId: toolCall.toolId,
toolOutput: {
id: toolCall.data.toolId,
id: toolCall.toolId,
result: "",
isError: false,
},
returnDirect: false,
raw: {},
});
};
try {
const output = await this.callTool(toolCall, ctx);
toolResult.data.raw = output;
toolResult.data.toolOutput.result =
stringifyJSONToMessageContent(output);
toolResult.data.returnDirect = toolCall.data.toolName === "handOff";
const output = await this.callTool(toolCall);
toolResult.raw = output;
toolResult.toolOutput.result = stringifyJSONToMessageContent(output);
toolResult.returnDirect = toolCall.toolName === "handOff";
} catch (error) {
toolResult.data.toolOutput.isError = true;
toolResult.data.toolOutput.result = `Error: ${error}`;
toolResult.toolOutput.isError = true;
toolResult.toolOutput.result = `Error: ${error}`;
}
results.push(toolResult);
// Send single tool result event, useful for UI
ctx.sendEvent(toolResult);
sendEvent(agentToolCallResultEvent.with(toolResult));
}
return new ToolResultsEvent({
return toolResultsEvent.with({
agentName,
results,
});
};
private processToolResults = async (
ctx: StepContext<AgentWorkflowContext>,
event: ToolResultsEvent,
): Promise<AgentInput | StopEvent<{ result: string }>> => {
event: WorkflowEventData<ToolResults>,
) => {
const { agentName, results } = event.data;
// Get agent
@@ -437,18 +479,23 @@ export class AgentWorkflow {
throw new Error(`Agent ${agentName} not found`);
}
await agent.handleToolCallResults(ctx, results);
await agent.handleToolCallResults(
this.stateful.getContext().state,
results,
);
const directResult = results.find((r) => r.data.returnDirect);
const directResult = results.find(
(r: AgentToolCallResult) => r.returnDirect,
);
if (directResult) {
const isHandoff = directResult.data.toolName === "handOff";
const isHandoff = directResult.toolName === "handOff";
const output =
typeof directResult.data.toolOutput.result === "string"
? directResult.data.toolOutput.result
: JSON.stringify(directResult.data.toolOutput.result);
typeof directResult.toolOutput.result === "string"
? directResult.toolOutput.result
: JSON.stringify(directResult.toolOutput.result);
const agentOutput = new AgentOutput({
const agentOutput = {
response: {
role: "assistant" as const,
content: output,
@@ -456,131 +503,122 @@ export class AgentWorkflow {
toolCalls: [],
raw: output,
currentAgentName: agent.name,
});
};
await agent.finalize(ctx, agentOutput, ctx.data.memory);
await agent.finalize(this.stateful.getContext().state, agentOutput);
if (isHandoff) {
const nextAgentName = ctx.data.nextAgentName;
const nextAgentName = this.stateful.getContext().state.nextAgentName;
console.log(
`[Agent ${agentName}]: Handoff to ${nextAgentName}: ${directResult.data.toolOutput.result}`,
`[Agent ${agentName}]: Handoff to ${nextAgentName}: ${directResult.toolOutput.result}`,
);
if (nextAgentName) {
ctx.data.currentAgentName = nextAgentName;
ctx.data.nextAgentName = null;
this.stateful.getContext().state.currentAgentName = nextAgentName;
this.stateful.getContext().state.nextAgentName = null;
const messages = await ctx.data.memory.getMessages();
return new AgentInput({
const messages = await this.stateful
.getContext()
.state.memory.getMessages();
return agentInputEvent.with({
input: messages,
currentAgentName: nextAgentName,
});
}
}
return new StopEvent({
return stopAgentEvent.with({
result: output,
state: this.stateful.getContext().state,
});
}
// Continue with another agent step
const messages = await ctx.data.memory.getMessages();
return new AgentInput({
const messages = await this.stateful
.getContext()
.state.memory.getMessages();
return agentInputEvent.with({
input: messages,
currentAgentName: agent.name,
});
};
private setupWorkflowSteps() {
this.workflow.addStep(
{
inputs: [StartEvent<AgentInputData>],
},
this.handleInputStep,
);
this.workflow.addStep(
{
inputs: [AgentInput],
},
this.setupAgent,
);
this.workflow.addStep(
{
inputs: [AgentSetup],
},
this.runAgentStep,
);
this.workflow.addStep(
{
inputs: [AgentStepEvent],
},
this.parseAgentOutput,
);
this.workflow.addStep(
{
inputs: [ToolCallsEvent],
},
this.executeToolCalls,
);
this.workflow.addStep(
{
inputs: [ToolResultsEvent],
},
this.processToolResults,
);
return this;
this.workflow.handle([startAgentEvent], this.handleInputStep);
this.workflow.handle([agentInputEvent], this.setupAgent);
this.workflow.handle([agentSetupEvent], this.runAgentStep);
this.workflow.handle([agentStepEvent], this.parseAgentOutput);
this.workflow.handle([toolCallsEvent], this.executeToolCalls);
this.workflow.handle([toolResultsEvent], this.processToolResults);
}
private callTool(
toolCall: AgentToolCall,
ctx: StepContext<AgentWorkflowContext>,
) {
private callTool(toolCall: AgentToolCall) {
const tool = this.agents
.get(toolCall.data.agentName)
?.tools.find((t) => t.metadata.name === toolCall.data.toolName);
.get(toolCall.agentName)
?.tools.find((t) => t.metadata.name === toolCall.toolName);
if (!tool) {
throw new Error(`Tool ${toolCall.data.toolName} not found`);
throw new Error(`Tool ${toolCall.toolName} not found`);
}
if (tool.metadata.requireContext) {
const input = { context: ctx.data, ...toolCall.data.toolKwargs };
const input = {
context: this.stateful.getContext().state,
...toolCall.toolKwargs,
};
return tool.call(input);
} else {
return tool.call(toolCall.data.toolKwargs);
return tool.call(toolCall.toolKwargs);
}
}
run(
userInput: string,
params?: {
chatHistory?: ChatMessage[];
context?: AgentWorkflowContext;
},
) {
if (this.agents.size === 0) {
throw new Error("No agents added to workflow");
}
this.setupWorkflowSteps();
const contextData: AgentWorkflowContext = params?.context ?? {
userInput: userInput,
memory: new ChatMemoryBuffer(),
private createInitialState(): AgentWorkflowState {
return {
memory: new ChatMemoryBuffer({
llm: this.agents.get(this.rootAgentName)?.llm ?? Settings.llm,
}),
scratchpad: [],
currentAgentName: this.rootAgentName,
agents: Array.from(this.agents.keys()),
nextAgentName: null,
};
}
return this.workflow.run(
{
runStream(
userInput: string,
params?: {
chatHistory?: ChatMessage[];
state?: AgentWorkflowState;
},
) {
if (this.agents.size === 0) {
throw new Error("No agents added to workflow");
}
const state = params?.state ?? this.createInitialState();
const { sendEvent, stream } = this.workflow.createContext(state);
sendEvent(
startAgentEvent.with({
userInput: userInput,
chatHistory: params?.chatHistory,
},
contextData,
}),
);
return stream.until(stopAgentEvent);
}
async run(
userInput: string,
params?: {
chatHistory?: ChatMessage[];
state?: AgentWorkflowState;
},
): Promise<WorkflowEventData<AgentResultData>> {
const finalEvent = (await this.runStream(userInput, params).toArray()).at(
-1,
);
if (!stopAgentEvent.include(finalEvent)) {
throw new Error(
`Agent stopped with unexpected ${finalEvent?.toString() ?? "unknown"} event.`,
);
}
return finalEvent;
}
}
@@ -598,7 +636,7 @@ const createHandoffTool = (agents: Map<string, BaseWorkflowAgent>) => {
toAgent,
reason,
}: {
context?: AgentWorkflowContext;
context?: AgentWorkflowState;
toAgent: string;
reason: string;
}) => {
+6 -7
View File
@@ -1,10 +1,9 @@
import type { StepContext } from "@llama-flow/llamaindex";
import type { WorkflowContext } from "@llama-flow/core";
import type { BaseToolWithCall, ChatMessage, LLM } from "@llamaindex/core/llms";
import { BaseMemory } from "@llamaindex/core/memory";
import type { AgentOutput, AgentToolCallResult } from "./events";
export type AgentWorkflowContext = {
userInput: string;
export type AgentWorkflowState = {
memory: BaseMemory;
scratchpad: ChatMessage[];
agents: string[];
@@ -28,7 +27,8 @@ export interface BaseWorkflowAgent {
* Using memory directly to get messages instead of requiring them to be passed in
*/
takeStep(
ctx: StepContext<AgentWorkflowContext>,
ctx: WorkflowContext,
state: AgentWorkflowState,
llmInput: ChatMessage[],
tools: BaseToolWithCall[],
): Promise<AgentOutput>;
@@ -37,7 +37,7 @@ export interface BaseWorkflowAgent {
* Handle results from tool calls
*/
handleToolCallResults(
ctx: StepContext<AgentWorkflowContext>,
state: AgentWorkflowState,
results: AgentToolCallResult[],
): Promise<void>;
@@ -45,8 +45,7 @@ export interface BaseWorkflowAgent {
* Finalize the agent's output
*/
finalize(
ctx: StepContext<AgentWorkflowContext>,
state: AgentWorkflowState,
output: AgentOutput,
memory: BaseMemory,
): Promise<AgentOutput>;
}
+18 -13
View File
@@ -1,43 +1,48 @@
import { WorkflowEvent } from "@llama-flow/llamaindex";
import { workflowEvent } from "@llama-flow/core";
import type { JSONValue } from "@llamaindex/core/global";
import type { ChatMessage, ToolResult } from "@llamaindex/core/llms";
export class AgentToolCall extends WorkflowEvent<{
export type AgentToolCall = {
agentName: string;
toolName: string;
toolKwargs: Record<string, JSONValue>;
toolId: string;
}> {}
};
export const agentToolCallEvent = workflowEvent<AgentToolCall>();
export class AgentToolCallResult extends WorkflowEvent<{
export type AgentToolCallResult = {
toolName: string;
toolKwargs: Record<string, JSONValue>;
toolId: string;
toolOutput: ToolResult;
returnDirect: boolean;
raw: JSONValue;
}> {}
};
export const agentToolCallResultEvent = workflowEvent<AgentToolCallResult>();
export class AgentInput extends WorkflowEvent<{
export type AgentInput = {
input: ChatMessage[];
currentAgentName: string;
}> {}
};
export const agentInputEvent = workflowEvent<AgentInput>();
export class AgentSetup extends WorkflowEvent<{
export type AgentSetup = {
input: ChatMessage[];
currentAgentName: string;
}> {}
};
export const agentSetupEvent = workflowEvent<AgentSetup>();
export class AgentStream extends WorkflowEvent<{
export const agentStreamEvent = workflowEvent<{
delta: string;
response: string;
currentAgentName: string;
raw: unknown;
}> {}
}>();
export class AgentOutput extends WorkflowEvent<{
export type AgentOutput = {
response: ChatMessage;
toolCalls: AgentToolCall[];
raw: unknown;
currentAgentName: string;
}> {}
};
export const agentOutputEvent = workflowEvent<AgentOutput>();

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