Compare commits

..

10 Commits

Author SHA1 Message Date
Marcus Schiesser 9aeea6f1ea feat: use ink to render workflow 2025-05-19 13:36:08 +07:00
Marcus Schiesser a882bbf9c8 chore: copied doc-workflow example from CL 2025-05-19 12:40:45 +07:00
github-actions[bot] f63b702bec Release 0.11.0 (#1950)
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-05-19 12:23:04 +07:00
Marcus Schiesser ccde88fe0b docs: update azure docs (#1958) 2025-05-19 11:49:18 +07:00
ANKIT VARSHNEY b0cd5301bb remove openai from llamaindex package and remove default setting for llm and embedModel (#1809)
Co-authored-by: Marcus Schiesser <marcus.schiesser@googlemail.com>
Co-authored-by: Marcus Schiesser <mail@marcusschiesser.de>
2025-05-19 11:12:57 +07:00
Marcus Schiesser 3e66ddc10d chore: Move Azure models to azure package (#1888) 2025-05-16 15:50:12 +07:00
Marcus Schiesser c719b968f3 Fix: broken links in docs (#1956)
Co-authored-by: Andrew Kostka <apkostka@gmail.com>
2025-05-15 16:49:05 +07:00
Anubhav Rana c73c659c6d chore: qdrant version updates (#1913)
Co-authored-by: Marcus Schiesser <mail@marcusschiesser.de>
2025-05-15 12:30:24 +07:00
Marcus Schiesser 361a685012 chore: remove old workflows (#1951) 2025-05-15 10:29:47 +07:00
Marcus Schiesser 680b529e94 chore: remove requireContext from tools (#1949) 2025-05-14 16:38:44 +07:00
201 changed files with 3176 additions and 1477 deletions
+16
View File
@@ -1,5 +1,21 @@
# @llamaindex/doc
## 0.2.19
### Patch Changes
- Updated dependencies [680b529]
- Updated dependencies [b0cd530]
- Updated dependencies [361a685]
- Updated dependencies [3e66ddc]
- @llamaindex/workflow@1.1.3
- @llamaindex/core@0.6.6
- llamaindex@0.11.0
- @llamaindex/openai@0.4.0
- @llamaindex/cloud@4.0.8
- @llamaindex/node-parser@2.0.6
- @llamaindex/readers@3.1.4
## 0.2.18
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/doc",
"version": "0.2.18",
"version": "0.2.19",
"private": true,
"scripts": {
"postinstall": "fumadocs-mdx",
+10 -7
View File
@@ -4,7 +4,6 @@ import matter from "gray-matter";
import path from "path";
const CONTENT_DIR = path.join(process.cwd(), "src/content/docs");
const BUILD_DIR = path.join(process.cwd(), ".next");
// Regular expression to find internal links
// This captures Markdown links [text](/docs/path) and href attributes href="/docs/path"
@@ -14,6 +13,8 @@ const INTERNAL_LINK_REGEX = /(?:(?:\]\(|\bhref=["'])\/docs\/([^")]+))/g;
// This captures relative links like [text](./path) or ![alt](../images/image.png)
const RELATIVE_LINK_REGEX = /(?:\]\()(?:\s*)(?:\.\.?)\//g;
const ALLOWED_LINKS = ["/docs/llamaflow"];
interface LinkValidationResult {
file: string;
invalidLinks: Array<{ link: string; line: number }>;
@@ -28,7 +29,7 @@ interface RelativeLinkResult {
* Get all valid documentation routes from the content directory
*/
async function getValidRoutes(): Promise<Set<string>> {
const mdxFiles = await glob("**/*.mdx?", { cwd: CONTENT_DIR });
const mdxFiles = await glob("**/*.{md,mdx}", { cwd: CONTENT_DIR });
const routes = new Set<string>();
@@ -124,14 +125,11 @@ function findRelativeLinksInFile(
return relativeLinks;
}
/**
* Validate internal links in all MDX files
*/
/**
* Find relative links in all MDX files
*/
async function findRelativeLinks(): Promise<RelativeLinkResult[]> {
const mdxFiles = await glob("**/*.mdx?", { cwd: CONTENT_DIR });
const mdxFiles = await glob("**/*.mdx", { cwd: CONTENT_DIR });
const results: RelativeLinkResult[] = [];
for (const file of mdxFiles) {
@@ -150,7 +148,7 @@ async function findRelativeLinks(): Promise<RelativeLinkResult[]> {
}
async function validateLinks(): Promise<LinkValidationResult[]> {
const mdxFiles = await glob("**/*.mdx?", { cwd: CONTENT_DIR });
const mdxFiles = await glob("**/*.mdx", { cwd: CONTENT_DIR });
const validRoutes = await getValidRoutes();
const results: LinkValidationResult[] = [];
@@ -160,6 +158,11 @@ async function validateLinks(): Promise<LinkValidationResult[]> {
const links = extractLinksFromFile(filePath);
const invalidLinks = links.filter(({ link }) => {
// Check if the link is in the allowed list
if (ALLOWED_LINKS.includes(`/docs/${link}`)) {
return false;
}
// Check if the link exists in valid routes
// First normalize the link (remove any query string or hash)
const baseLink = link.split("?")[0].split("#")[0];
@@ -12,7 +12,7 @@ To use workflows install this package:
npm i @llamaindex/workflow
```
This package is a stable, production-ready version of our [llama-flow](../../../llamaflow) project.
This package is a stable, production-ready version of our [llama-flow](/docs/llamaflow) project.
While you can still reference the llama-flow documentation for detailed information about the underlying concepts, we recommend using the `@llamaindex/workflow` package for all new projects to ensure stability and long-term availability.
@@ -18,7 +18,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.
<include cwd>../../examples/discord/reader.ts</include>
<include cwd>../../examples/readers/discord/reader.ts</include>
### Params
@@ -2,89 +2,43 @@
title: Azure OpenAI
---
To use Azure OpenAI, you only need to set a few environment variables together with the `OpenAI` class.
For example:
## Environment Variables
```
export AZURE_OPENAI_KEY="<YOUR KEY HERE>"
export AZURE_OPENAI_ENDPOINT="<YOUR ENDPOINT, see https://learn.microsoft.com/en-us/azure/ai-services/openai/quickstart?tabs=command-line%2Cpython&pivots=rest-api>"
export AZURE_OPENAI_DEPLOYMENT="gpt-4" # or some other deployment name
```
To use Azure OpenAI, you only need to install the `@llamaindex/azure` package:
## Installation
```package-install
npm i llamaindex @llamaindex/openai
npm i llamaindex @llamaindex/azure
```
## Usage
The class `AzureOpenAI` is used for setting the LLM and `AzureOpenAIEmbedding` is used for setting the embedding model, e.g.:
```ts
import { Settings } from "llamaindex";
import { OpenAI } from "@llamaindex/openai";
import { AzureOpenAI, AzureOpenAIEmbedding } from "@llamaindex/azure";
Settings.llm = new OpenAI({ model: "gpt-4", temperature: 0 });
```
## Load and index documents
For this example, we will use a single document. In a real-world scenario, you would have multiple documents to index.
```ts
const document = new Document({ text: essay, id_: "essay" });
const index = await VectorStoreIndex.fromDocuments([document]);
```
## Query
```ts
const queryEngine = index.asQueryEngine();
const query = "What is the meaning of life?";
const results = await queryEngine.query({
query,
Settings.llm = new AzureOpenAI({
apiKey: '[key]',
deployment: '[model]',
apiVersion: '[version]',
endpoint: `https://[deployment].openai.azure.com/`,
});
Settings.embedModel = new AzureOpenAIEmbedding({
apiKey: '[key]',
deployment: '[embedding-model]',
apiVersion: '[version]',
endpoint: `https://[deployment].openai.azure.com/`,
});
```
## Full Example
Instead of explicitly setting the API key, deployment, version, and endpoint in the constructor, you can use the following environment variables: `AZURE_OPENAI_DEPLOYMENT` for the model deployment name, `AZURE_OPENAI_KEY` for your API key, `AZURE_OPENAI_ENDPOINT` for your Azure endpoint URL, and `AZURE_OPENAI_API_VERSION` for the API version.
```ts
import { Document, VectorStoreIndex, Settings } from "llamaindex";
import { OpenAI } from "@llamaindex/openai";
## Examples
Settings.llm = new OpenAI({ model: "gpt-4", temperature: 0 });
async function main() {
const document = new Document({ text: essay, id_: "essay" });
// Load and index documents
const index = await VectorStoreIndex.fromDocuments([document]);
// get retriever
const retriever = index.asRetriever();
// Create a query engine
const queryEngine = index.asQueryEngine({
retriever,
});
const query = "What is the meaning of life?";
// Query
const response = await queryEngine.query({
query,
});
// Log the response
console.log(response.response);
}
```
See the [Azure examples](https://github.com/run-llama/LlamaIndexTS/tree/main/examples/storage/azure) for more examples of how to use Azure OpenAI.
## API Reference
- [OpenAI](/docs/api/classes/OpenAI)
- [AzureOpenAI](/docs/api/classes/AzureOpenAI)
- [AzureOpenAIEmbedding](/docs/api/classes/AzureOpenAIEmbedding)
@@ -55,7 +55,7 @@ const results = await queryEngine.query({
## Full Example
<include cwd>../../examples/groq.ts</include>
<include cwd>../../examples/models/groq.ts</include>
## API Reference
@@ -166,4 +166,4 @@ Want to start a new project with LlamaIndexServer? Check out our [create-llama](
## API Reference
- [LlamaIndexServer](/docs/api/classes/LlamaIndexServer)
- [LlamaIndexServer](https://github.com/run-llama/create-llama/blob/main/packages/server)
@@ -27,7 +27,7 @@ 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
<include cwd>../../examples/vectorIndex.ts</include>
<include cwd>../../examples/index/vectorIndex.ts</include>
Create a `tsconfig.json` file in the same folder:
@@ -24,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
<include cwd>../../examples/jsonExtract.ts</include>
<include cwd>../../examples/misc/jsonExtract.ts</include>
To run the code:
+14
View File
@@ -1,5 +1,19 @@
# @llamaindex/core-e2e
## 0.1.1
### Patch Changes
- b0cd530: # Breaking Change
## What Changed
Remove default setting of llm and embedModel in Settings
## Migration Guide
Set the llm provider and embed Model in the top of your code using Settings.llm = and Settings.embedModel
## 0.1.0
### Minor Changes
@@ -1,5 +1,13 @@
# @llamaindex/cloudflare-worker-agent-test
## 0.0.161
### Patch Changes
- Updated dependencies [b0cd530]
- Updated dependencies [361a685]
- llamaindex@0.11.0
## 0.0.160
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/cloudflare-worker-agent-test",
"version": "0.0.160",
"version": "0.0.161",
"type": "module",
"private": true,
"scripts": {
@@ -1,5 +1,11 @@
# @llamaindex/llama-parse-browser-test
## 0.0.63
### Patch Changes
- @llamaindex/cloud@4.0.8
## 0.0.62
### Patch Changes
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/llama-parse-browser-test",
"private": true,
"version": "0.0.62",
"version": "0.0.63",
"type": "module",
"scripts": {
"dev": "vite",
+8
View File
@@ -1,5 +1,13 @@
# @llamaindex/next-agent-test
## 0.1.161
### Patch Changes
- Updated dependencies [b0cd530]
- Updated dependencies [361a685]
- llamaindex@0.11.0
## 0.1.160
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/next-agent-test",
"version": "0.1.160",
"version": "0.1.161",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,7 +1,7 @@
"use server";
import { OpenAIAgent } from "@llamaindex/openai";
import { createStreamableUI } from "ai/rsc";
import type { ChatMessage } from "llamaindex";
import { OpenAIAgent } from "llamaindex";
export async function chatWithAgent(
question: string,
@@ -1,5 +1,13 @@
# test-edge-runtime
## 0.1.160
### Patch Changes
- Updated dependencies [b0cd530]
- Updated dependencies [361a685]
- llamaindex@0.11.0
## 0.1.159
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/nextjs-edge-runtime-test",
"version": "0.1.159",
"version": "0.1.160",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,5 +1,15 @@
# @llamaindex/next-node-runtime
## 0.1.28
### Patch Changes
- Updated dependencies [b0cd530]
- Updated dependencies [361a685]
- llamaindex@0.11.0
- @llamaindex/huggingface@0.1.10
- @llamaindex/readers@3.1.4
## 0.1.27
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/next-node-runtime-test",
"version": "0.1.27",
"version": "0.1.28",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,7 +1,8 @@
"use server";
import { HuggingFaceEmbedding } from "@llamaindex/huggingface";
import { OpenAI, OpenAIAgent } from "@llamaindex/openai";
import { SimpleDirectoryReader } from "@llamaindex/readers/directory";
import { OpenAI, OpenAIAgent, Settings, VectorStoreIndex } from "llamaindex";
import { Settings, VectorStoreIndex } from "llamaindex";
Settings.llm = new OpenAI({
apiKey: process.env.NEXT_PUBLIC_OPENAI_KEY ?? "FAKE_KEY_TO_PASS_TESTS",
@@ -1,5 +1,13 @@
# vite-import-llamaindex
## 0.0.27
### Patch Changes
- Updated dependencies [b0cd530]
- Updated dependencies [361a685]
- llamaindex@0.11.0
## 0.0.26
### Patch Changes
@@ -1,7 +1,7 @@
{
"name": "vite-import-llamaindex",
"private": true,
"version": "0.0.26",
"version": "0.0.27",
"type": "module",
"scripts": {
"build": "vite build",
@@ -1,5 +1,13 @@
# @llamaindex/waku-query-engine-test
## 0.0.161
### Patch Changes
- Updated dependencies [b0cd530]
- Updated dependencies [361a685]
- llamaindex@0.11.0
## 0.0.160
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/waku-query-engine-test",
"version": "0.0.160",
"version": "0.0.161",
"type": "module",
"private": true,
"scripts": {
+2
View File
@@ -1,6 +1,7 @@
import { ClipEmbedding } from "@llamaindex/clip";
import type { LoadTransformerEvent } from "@llamaindex/env/multi-model";
import { setTransformers } from "@llamaindex/env/multi-model";
import { OpenAIEmbedding } from "@llamaindex/openai";
import { ImageNode, Settings } from "llamaindex";
import assert from "node:assert";
import { type Mock, test } from "node:test";
@@ -19,6 +20,7 @@ test.before(() => {
test.beforeEach(() => {
callback.mock.resetCalls();
Settings.embedModel = new OpenAIEmbedding();
});
await test.skip("clip embedding", async (t) => {
+2 -6
View File
@@ -1,10 +1,6 @@
import type { TaskStep } from "@llamaindex/core/agent";
import {
LLMSingleSelector,
OpenAIAgent,
Settings,
type ChatMessage,
} from "llamaindex";
import { OpenAIAgent } from "@llamaindex/openai";
import { LLMSingleSelector, Settings, type ChatMessage } from "llamaindex";
import assert from "node:assert";
import { test } from "node:test";
import { divideNumbersTool, sumNumbersTool } from "./fixtures/tools.js";
+1 -2
View File
@@ -1,11 +1,10 @@
import { extractText } from "@llamaindex/core/utils";
import { OpenAI, OpenAIAgent } from "@llamaindex/openai";
import { consola } from "consola";
import {
Document,
FunctionTool,
ObjectIndex,
OpenAI,
OpenAIAgent,
QueryEngineTool,
SentenceSplitter,
Settings,
+2 -1
View File
@@ -1,5 +1,6 @@
import { extractText } from "@llamaindex/core/utils";
import { OpenAI, ReActAgent, Settings, type LLM } from "llamaindex";
import { OpenAI } from "@llamaindex/openai";
import { ReActAgent, Settings, type LLM } from "llamaindex";
import { ok } from "node:assert";
import { beforeEach, test } from "node:test";
import { getWeatherTool } from "./fixtures/tools.js";
+7 -2
View File
@@ -1,8 +1,9 @@
import { OpenAIEmbedding } from "@llamaindex/openai";
import { PGVectorStore } from "@llamaindex/postgres";
import { config } from "dotenv";
import { Document, VectorStoreQueryMode } from "llamaindex";
import { Document, Settings, VectorStoreQueryMode } from "llamaindex";
import assert from "node:assert";
import { test } from "node:test";
import { beforeEach, test } from "node:test";
import pg from "pg";
import { registerTypes } from "pgvector/pg";
@@ -14,6 +15,10 @@ const pgConfig = {
database: "llamaindex_node_test",
};
beforeEach(async () => {
Settings.embedModel = new OpenAIEmbedding();
});
await test("init with client", async (t) => {
const pgClient = new pg.Client(pgConfig);
await pgClient.connect();
+2 -1
View File
@@ -1,5 +1,6 @@
import { OpenAI } from "@llamaindex/openai";
import { agent } from "@llamaindex/workflow";
import { OpenAI, Settings, tool } from "llamaindex";
import { Settings, tool } from "llamaindex";
import { ok } from "node:assert";
import { test } from "node:test";
import { z } from "zod";
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/e2e",
"private": true,
"version": "0.1.0",
"version": "0.1.1",
"type": "module",
"scripts": {
"e2e": "node --import tsx --import ./mock-register.js --test ./node/**/*.e2e.ts",
+55
View File
@@ -1,5 +1,60 @@
# examples
## 0.3.16
### Patch Changes
- Updated dependencies [680b529]
- Updated dependencies [b0cd530]
- Updated dependencies [c73c659]
- Updated dependencies [361a685]
- Updated dependencies [3e66ddc]
- @llamaindex/workflow@1.1.3
- @llamaindex/core@0.6.6
- llamaindex@0.11.0
- @llamaindex/qdrant@0.1.15
- @llamaindex/azure@0.1.16
- @llamaindex/openai@0.4.0
- @llamaindex/cloud@4.0.8
- @llamaindex/node-parser@2.0.6
- @llamaindex/anthropic@0.3.7
- @llamaindex/assemblyai@0.1.5
- @llamaindex/clip@0.0.56
- @llamaindex/cohere@0.0.20
- @llamaindex/deepinfra@0.0.56
- @llamaindex/discord@0.1.5
- @llamaindex/google@0.3.2
- @llamaindex/huggingface@0.1.10
- @llamaindex/jinaai@0.0.16
- @llamaindex/mistral@0.1.6
- @llamaindex/mixedbread@0.0.20
- @llamaindex/notion@0.1.5
- @llamaindex/ollama@0.1.6
- @llamaindex/perplexity@0.0.13
- @llamaindex/portkey-ai@0.0.48
- @llamaindex/replicate@0.0.48
- @llamaindex/astra@0.0.20
- @llamaindex/chroma@0.0.20
- @llamaindex/elastic-search@0.1.6
- @llamaindex/firestore@1.0.13
- @llamaindex/milvus@0.1.15
- @llamaindex/mongodb@0.0.21
- @llamaindex/pinecone@0.1.6
- @llamaindex/postgres@0.0.49
- @llamaindex/supabase@0.1.5
- @llamaindex/upstash@0.0.20
- @llamaindex/weaviate@0.0.20
- @llamaindex/vercel@0.1.6
- @llamaindex/voyage-ai@1.0.12
- @llamaindex/readers@3.1.4
- @llamaindex/tools@0.0.11
- @llamaindex/deepseek@0.0.16
- @llamaindex/fireworks@0.0.16
- @llamaindex/groq@0.0.71
- @llamaindex/together@0.0.16
- @llamaindex/vllm@0.0.42
- @llamaindex/xai@0.0.3
## 0.3.15
### Patch Changes
+1 -1
View File
@@ -92,7 +92,7 @@ async function multiWeatherAgent() {
agentInputEvent.include(event) ||
stopAgentEvent.include(event)
) {
console.log(event);
console.log(event.data);
} else if (agentStreamEvent.include(event)) {
for (const chunk of event.data.delta) {
process.stdout.write(chunk);
+2 -1
View File
@@ -1,9 +1,10 @@
import { openai } from "@llamaindex/openai";
import {
agent,
agentStreamEvent,
agentToolCallResultEvent,
} from "@llamaindex/workflow";
import { Document, VectorStoreIndex, openai } from "llamaindex";
import { Document, VectorStoreIndex } from "llamaindex";
async function main() {
const index = await VectorStoreIndex.fromDocuments([
+332
View File
@@ -0,0 +1,332 @@
import { ChatMemoryBuffer, ChatMessage, LLM, MessageContent } from "llamaindex";
import {
agentStreamEvent,
createStatefulMiddleware,
createWorkflow,
startAgentEvent,
stopAgentEvent,
workflowEvent,
} from "@llamaindex/workflow";
import { z } from "zod";
export const DocumentRequirementSchema = z.object({
type: z.enum(["markdown", "html"]),
title: z.string(),
requirement: z.string(),
});
export type DocumentRequirement = z.infer<typeof DocumentRequirementSchema>;
export const UIEventSchema = z.object({
type: z.literal("ui_event"),
data: z.object({
state: z
.enum(["plan", "generate", "completed"])
.describe(
"The current state of the workflow: 'plan', 'generate', or 'completed'.",
),
requirement: z
.string()
.optional()
.describe(
"An optional requirement creating or updating a document, if applicable.",
),
}),
});
export type UIEvent = z.infer<typeof UIEventSchema>;
export const uiEvent = workflowEvent<UIEvent>();
const planEvent = workflowEvent<{
userInput: MessageContent;
context?: string | undefined;
}>();
const generateArtifactEvent = workflowEvent<{
requirement: DocumentRequirement;
}>();
const synthesizeAnswerEvent = workflowEvent<{
requirement: DocumentRequirement;
generatedArtifact: string;
}>();
const ArtifactSchema = z.object({
type: z.literal("artifact"),
data: z.object({
type: z.literal("document"),
data: z.object({
title: z.string(),
content: z.string(),
type: z.string(),
}),
created_at: z.number(),
}),
});
export type Artifact = z.infer<typeof ArtifactSchema>;
export const artifactEvent = workflowEvent<Artifact>();
export function createDocumentArtifactWorkflow(
llm: LLM,
chatHistory: ChatMessage[],
lastArtifact: Artifact | undefined,
) {
const { withState, getContext } = createStatefulMiddleware(() => {
return {
memory: new ChatMemoryBuffer({
llm,
chatHistory: chatHistory,
}),
lastArtifact: lastArtifact,
};
});
const workflow = withState(createWorkflow());
workflow.handle([startAgentEvent], async ({ data: { userInput } }) => {
// Prepare chat history
const { state } = getContext();
// Put user input to the memory
if (!userInput) {
throw new Error("Missing user input to start the workflow");
}
state.memory.put({
role: "user",
content: userInput,
});
return planEvent.with({
userInput,
context: state.lastArtifact
? JSON.stringify(state.lastArtifact)
: undefined,
});
});
workflow.handle([planEvent], async ({ data: planData }) => {
const { sendEvent } = getContext();
const { state } = getContext();
sendEvent(
uiEvent.with({
type: "ui_event",
data: {
state: "plan",
},
}),
);
const user_msg = planData.userInput;
const context = planData.context
? `## The context is: \n${planData.context}\n`
: "";
const prompt = `
You are a documentation analyst responsible for analyzing the user's request and providing requirements for document generation or update.
Follow these instructions:
1. Carefully analyze the conversation history and the user's request to determine what has been done and what the next step should be.
2. From the user's request, provide requirements for the next step of the document generation or update.
3. Do not be verbose; only return the requirements for the next step of the document generation or update.
4. Only the following document types are allowed: "markdown", "html".
5. The requirement should be in the following format:
\`\`\`json
{
"type": "markdown" | "html",
"title": string,
"requirement": string
}
\`\`\`
## Example:
User request: Create a project guideline document.
You should return:
\`\`\`json
{
"type": "markdown",
"title": "Project Guideline",
"requirement": "Generate a Markdown document that outlines the project goals, deliverables, and timeline. Include sections for introduction, objectives, deliverables, and timeline."
}
\`\`\`
User request: Add a troubleshooting section to the guideline.
You should return:
\`\`\`json
{
"type": "markdown",
"title": "Project Guideline",
"requirement": "Add a 'Troubleshooting' section at the end of the document with common issues and solutions."
}
\`\`\`
${context}
Now, please plan for the user's request:
${user_msg}
`;
const response = await llm.complete({
prompt,
});
// Parse the response to DocumentRequirement
const jsonBlock = response.text.match(/```json\s*([\s\S]*?)\s*```/);
if (!jsonBlock) {
throw new Error("No JSON block found in the response.");
}
const requirement = DocumentRequirementSchema.parse(
JSON.parse(jsonBlock[1]),
);
state.memory.put({
role: "assistant",
content: `Planning for the document generation: \n${response.text}`,
});
return generateArtifactEvent.with({
requirement,
});
});
workflow.handle(
[generateArtifactEvent],
async ({ data: { requirement } }) => {
const { sendEvent } = getContext();
const { state } = getContext();
sendEvent(
uiEvent.with({
type: "ui_event",
data: {
state: "generate",
requirement: requirement.requirement,
},
}),
);
const previousArtifact = state.lastArtifact
? JSON.stringify(state.lastArtifact)
: "";
const requirementStr = JSON.stringify(requirement);
const prompt = `
You are a skilled technical writer who can help users with documentation.
You are given a task to generate or update a document for a given requirement.
## Follow these instructions:
**1. Carefully read the user's requirements.**
If any details are ambiguous or missing, make reasonable assumptions and clearly reflect those in your output.
If the previous document is provided:
+ Carefully analyze the document with the request to make the right changes.
+ Avoid making unnecessary changes from the previous document if the request is not to rewrite it from scratch.
**2. For document requests:**
- If the user does not specify a type, default to Markdown.
- Ensure the document is clear, well-structured, and grammatically correct.
- Only generate content relevant to the user's request—do not add extra boilerplate.
**3. Do not be verbose in your response.**
- No other text or comments; only return the document content wrapped by the appropriate code block (\`\`\`markdown or \`\`\`html).
- If the user's request is to update the document, only return the updated document.
**4. Only the following types are allowed: "markdown", "html".**
**5. If there is no change to the document, return the reason without any code block.**
## Example:
\`\`\`markdown
# Project Guideline
## Introduction
...
\`\`\`
The previous content is:
${previousArtifact}
Now, please generate the document for the following requirement:
${requirementStr}
`;
const response = await llm.complete({
prompt,
});
// Extract the document from the response
const docMatch = response.text.match(/```(markdown|html)([\s\S]*)```/);
const generatedContent = response.text;
if (docMatch) {
const content = docMatch[2].trim();
const docType = docMatch[1] as "markdown" | "html";
// Put the generated document to the memory
state.memory.put({
role: "assistant",
content: `Generated document: \n${response.text}`,
});
// To show the Canvas panel for the artifact
sendEvent(
artifactEvent.with({
type: "artifact",
data: {
type: "document",
created_at: Date.now(),
data: {
title: requirement.title,
content: content,
type: docType,
},
},
}),
);
}
return synthesizeAnswerEvent.with({
requirement,
generatedArtifact: generatedContent,
});
},
);
workflow.handle([synthesizeAnswerEvent], async ({ data }) => {
const { sendEvent } = getContext();
const { state } = getContext();
const chatHistory = await state.memory.getMessages();
const messages = [
...chatHistory,
{
role: "system" as const,
content: `
Your responsibility is to explain the work to the user.
If there is no document to update, explain the reason.
If the document is updated, just summarize what changed. Don't need to include the whole document again in the response.
`,
},
];
const responseStream = await llm.chat({
messages,
stream: true,
});
sendEvent(
uiEvent.with({
type: "ui_event",
data: {
state: "completed",
requirement: data.requirement.requirement,
},
}),
);
let response = "";
for await (const chunk of responseStream) {
response += chunk.delta;
sendEvent(
agentStreamEvent.with({
delta: chunk.delta,
response: "",
currentAgentName: "assistant",
raw: chunk,
}),
);
}
return stopAgentEvent.with({
result: response,
});
});
return workflow;
}
+162
View File
@@ -0,0 +1,162 @@
import { openai } from "@llamaindex/openai";
import { Box, render, Text } from "ink";
import React from "react";
import {
agentStreamEvent,
startAgentEvent,
stopAgentEvent,
} from "@llamaindex/workflow";
import {
artifactEvent,
createDocumentArtifactWorkflow,
uiEvent,
UIEvent,
} from "./doc-workflow";
// Import Artifact type (assuming it's exported from doc-workflow.ts)
// If not exported, we'd define a simplified version here or use 'any' temporarily.
// Based on the read file, Artifact is a Zod schema inference.
// We can either import it or define a similar structure for props.
// For now, let's assume it's available from './doc-workflow'.
import type { Artifact } from "./doc-workflow"; // Assuming Artifact is exported
const llm = openai({ model: "gpt-4.1-mini" });
// Define the props for our UI component
interface WorkflowUIProps {
uiEvent: UIEvent;
}
// React component to render the UI using Ink
const WorkflowUI: React.FC<WorkflowUIProps> = ({ uiEvent }) => {
const contentWidth = 60;
const stateColorMap: { [key: string]: string } = {
plan: "yellow",
generate: "blue",
completed: "green",
};
const state = uiEvent.data.state;
const coloredStateText = (
<Text color={stateColorMap[state] || "white"}>{state.toUpperCase()}</Text>
);
const title = "💡 Workflow Event";
const requirementLabel = "Requirement: ";
return (
<Box
borderStyle="round"
borderColor="gray"
flexDirection="column"
paddingX={1}
width={contentWidth + 2 + 2}
>
<Box justifyContent="center" paddingTop={0} paddingBottom={0}>
<Text>{title}</Text>
</Box>
<Box borderStyle="single" borderColor="gray" height={1} marginY={1} />
<Box flexDirection="column">
<Box>
<Text>State: </Text>
{coloredStateText}
</Box>
{uiEvent.data.requirement !== undefined && (
<Box flexDirection="row" marginTop={1}>
<Text>{requirementLabel}</Text>
<Box flexGrow={1} flexShrink={1} marginLeft={1}>
<Text>{uiEvent.data.requirement}</Text>
</Box>
</Box>
)}
</Box>
</Box>
);
};
// --- BEGIN NEW ARTIFACT UI COMPONENT ---
interface ArtifactUIProps {
artifact: Artifact; // Use the imported Artifact type
}
const ArtifactUI: React.FC<ArtifactUIProps> = ({ artifact }) => {
const artifactData = artifact.data.data; // Access nested data
const contentWidth = 80; // Allow more width for artifact content
return (
<Box
borderStyle="round"
borderColor="cyan"
flexDirection="column"
padding={1}
width={contentWidth + 2 + 2} // Account for padding and border
>
<Box justifyContent="center" paddingBottom={1}>
<Text bold color="cyan">
📄 Artifact Generated: {artifactData.title}
</Text>
</Box>
<Box borderStyle="single" borderColor="gray" marginY={1} />
<Box flexDirection="column" gap={1}>
<Box>
<Text bold>Title: </Text>
<Text>{artifactData.title}</Text>
</Box>
<Box>
<Text bold>Type: </Text>
<Text>{artifactData.type}</Text>
</Box>
<Box flexDirection="column">
<Text bold>Content:</Text>
{/* Add a Box for content to allow it to take up space and wrap */}
<Box borderStyle="round" borderColor="gray" padding={1} marginTop={1}>
<Text>{artifactData.content}</Text>
</Box>
</Box>
<Box marginTop={1}>
<Text dimColor>
Created At: {new Date(artifact.data.created_at).toLocaleString()}
</Text>
</Box>
</Box>
</Box>
);
};
async function main() {
const workflow = createDocumentArtifactWorkflow(llm, [], undefined);
const { stream, sendEvent } = workflow.createContext();
const { rerender, unmount, clear } = render(
<Text>Waiting for workflow to start...</Text>,
);
sendEvent(
startAgentEvent.with({ userInput: "Create a project guideline document." }),
);
for await (const event of stream.until(stopAgentEvent)) {
if (agentStreamEvent.include(event)) {
process.stdout.write(event.data.delta);
} else if (uiEvent.include(event)) {
if (event.data.data.state !== "completed") {
rerender(<WorkflowUI uiEvent={event.data} />);
}
} else if (artifactEvent.include(event)) {
rerender(<ArtifactUI artifact={event.data} />);
}
}
unmount();
console.log("\nWorkflow finished.");
}
main().catch(console.error);
+8
View File
@@ -1,12 +1,20 @@
import fs from "node:fs/promises";
import { openai, OpenAIEmbedding } from "@llamaindex/openai";
import {
Document,
MetadataMode,
NodeWithScore,
Settings,
VectorStoreIndex,
} from "llamaindex";
Settings.llm = openai({
apiKey: process.env.OPENAI_API_KEY,
model: "gpt-4o",
});
Settings.embedModel = new OpenAIEmbedding();
async function main() {
// Load essay from abramov.txt in Node
const path = "node_modules/llamaindex/examples/abramov.txt";
+50 -46
View File
@@ -1,7 +1,8 @@
{
"name": "@llamaindex/examples",
"version": "0.3.15",
"version": "0.3.16",
"private": true,
"type": "module",
"scripts": {
"lint": "eslint .",
"start": "tsx ./starter.ts"
@@ -11,51 +12,51 @@
"@azure/cosmos": "^4.1.1",
"@azure/identity": "^4.4.1",
"@azure/search-documents": "^12.1.0",
"@llamaindex/anthropic": "^0.3.6",
"@llamaindex/assemblyai": "^0.1.4",
"@llamaindex/astra": "^0.0.19",
"@llamaindex/azure": "^0.1.15",
"@llamaindex/chroma": "^0.0.19",
"@llamaindex/clip": "^0.0.55",
"@llamaindex/cloud": "^4.0.7",
"@llamaindex/cohere": "^0.0.19",
"@llamaindex/core": "^0.6.5",
"@llamaindex/deepinfra": "^0.0.55",
"@llamaindex/deepseek": "^0.0.15",
"@llamaindex/discord": "^0.1.4",
"@llamaindex/elastic-search": "^0.1.5",
"@llamaindex/anthropic": "^0.3.7",
"@llamaindex/assemblyai": "^0.1.5",
"@llamaindex/astra": "^0.0.20",
"@llamaindex/azure": "^0.1.16",
"@llamaindex/chroma": "^0.0.20",
"@llamaindex/clip": "^0.0.56",
"@llamaindex/cloud": "^4.0.8",
"@llamaindex/cohere": "^0.0.20",
"@llamaindex/core": "^0.6.6",
"@llamaindex/deepinfra": "^0.0.56",
"@llamaindex/deepseek": "^0.0.16",
"@llamaindex/discord": "^0.1.5",
"@llamaindex/elastic-search": "^0.1.6",
"@llamaindex/env": "^0.1.30",
"@llamaindex/firestore": "^1.0.12",
"@llamaindex/fireworks": "^0.0.15",
"@llamaindex/google": "^0.3.1",
"@llamaindex/groq": "^0.0.70",
"@llamaindex/huggingface": "^0.1.9",
"@llamaindex/jinaai": "^0.0.15",
"@llamaindex/milvus": "^0.1.14",
"@llamaindex/mistral": "^0.1.5",
"@llamaindex/mixedbread": "^0.0.19",
"@llamaindex/mongodb": "^0.0.20",
"@llamaindex/node-parser": "^2.0.5",
"@llamaindex/notion": "^0.1.4",
"@llamaindex/ollama": "^0.1.5",
"@llamaindex/openai": "^0.3.7",
"@llamaindex/perplexity": "^0.0.12",
"@llamaindex/pinecone": "^0.1.5",
"@llamaindex/portkey-ai": "^0.0.47",
"@llamaindex/postgres": "^0.0.48",
"@llamaindex/qdrant": "^0.1.14",
"@llamaindex/readers": "^3.1.3",
"@llamaindex/replicate": "^0.0.47",
"@llamaindex/supabase": "^0.1.4",
"@llamaindex/together": "^0.0.15",
"@llamaindex/tools": "^0.0.10",
"@llamaindex/upstash": "^0.0.19",
"@llamaindex/vercel": "^0.1.5",
"@llamaindex/vllm": "^0.0.41",
"@llamaindex/voyage-ai": "^1.0.11",
"@llamaindex/weaviate": "^0.0.19",
"@llamaindex/workflow": "^1.1.2",
"@llamaindex/xai": "workspace:^0.0.2",
"@llamaindex/firestore": "^1.0.13",
"@llamaindex/fireworks": "^0.0.16",
"@llamaindex/google": "^0.3.2",
"@llamaindex/groq": "^0.0.71",
"@llamaindex/huggingface": "^0.1.10",
"@llamaindex/jinaai": "^0.0.16",
"@llamaindex/milvus": "^0.1.15",
"@llamaindex/mistral": "^0.1.6",
"@llamaindex/mixedbread": "^0.0.20",
"@llamaindex/mongodb": "^0.0.21",
"@llamaindex/node-parser": "^2.0.6",
"@llamaindex/notion": "^0.1.5",
"@llamaindex/ollama": "^0.1.6",
"@llamaindex/openai": "^0.4.0",
"@llamaindex/perplexity": "^0.0.13",
"@llamaindex/pinecone": "^0.1.6",
"@llamaindex/portkey-ai": "^0.0.48",
"@llamaindex/postgres": "^0.0.49",
"@llamaindex/qdrant": "^0.1.15",
"@llamaindex/readers": "^3.1.4",
"@llamaindex/replicate": "^0.0.48",
"@llamaindex/supabase": "^0.1.5",
"@llamaindex/together": "^0.0.16",
"@llamaindex/tools": "^0.0.11",
"@llamaindex/upstash": "^0.0.20",
"@llamaindex/vercel": "^0.1.6",
"@llamaindex/vllm": "^0.0.42",
"@llamaindex/voyage-ai": "^1.0.12",
"@llamaindex/weaviate": "^0.0.20",
"@llamaindex/workflow": "^1.1.3",
"@llamaindex/xai": "workspace:^0.0.3",
"@notionhq/client": "^2.2.15",
"@pinecone-database/pinecone": "^4.0.0",
"@vercel/postgres": "^0.10.0",
@@ -63,15 +64,18 @@
"ajv": "^8.17.1",
"commander": "^12.1.0",
"dotenv": "^16.4.5",
"ink": "^5.2.1",
"js-tiktoken": "^1.0.14",
"llamaindex": "^0.10.6",
"llamaindex": "^0.11.0",
"mongodb": "6.7.0",
"postgres": "^3.4.4",
"react": "^18.3.1",
"wikipedia": "^2.1.2",
"zod": "^3.23.8"
},
"devDependencies": {
"@types/node": "^22.9.0",
"@types/react": "^18.3.21",
"tsx": "^4.19.3",
"typescript": "^5.7.3"
},
+7 -10
View File
@@ -8,8 +8,9 @@ import {
AzureCosmosDBNoSqlVectorStore,
AzureCosmosNoSqlDocumentStore,
AzureCosmosNoSqlIndexStore,
AzureOpenAI,
AzureOpenAIEmbedding,
} from "@llamaindex/azure";
import { OpenAI, OpenAIEmbedding } from "@llamaindex/openai";
import {
Document,
Settings,
@@ -38,17 +39,13 @@ import {
"https://cognitiveservices.azure.com/.default",
);
const azure = {
Settings.llm = new AzureOpenAI({
azureADTokenProvider,
deployment: process.env.AZURE_DEPLOYMENT_NAME,
};
Settings.llm = new OpenAI({ azure });
Settings.embedModel = new OpenAIEmbedding({
model: process.env.EMBEDDING_MODEL,
azure: {
...azure,
deployment: process.env.EMBEDDING_MODEL,
},
});
Settings.embedModel = new AzureOpenAIEmbedding({
azureADTokenProvider,
deployment: process.env.EMBEDDING_MODEL,
});
const docStore = AzureCosmosNoSqlDocumentStore.fromAadToken();
console.log({ docStore });
+6 -9
View File
@@ -2,7 +2,7 @@ import {
DefaultAzureCredential,
getBearerTokenProvider,
} from "@azure/identity";
import { OpenAI, OpenAIEmbedding } from "@llamaindex/openai";
import { AzureOpenAI, AzureOpenAIEmbedding } from "@llamaindex/azure";
import "dotenv/config";
const AZURE_COGNITIVE_SERVICES_SCOPE =
@@ -15,11 +15,10 @@ const AZURE_COGNITIVE_SERVICES_SCOPE =
AZURE_COGNITIVE_SERVICES_SCOPE,
);
const azure = {
const llm = new AzureOpenAI({
azureADTokenProvider,
deployment: process.env.AZURE_DEPLOYMENT_NAME ?? "gpt-35-turbo",
};
const llm = new OpenAI({ azure });
});
// complete api
const response1 = await llm.complete({ prompt: "How are you?" });
console.log(response1.text);
@@ -31,11 +30,9 @@ const AZURE_COGNITIVE_SERVICES_SCOPE =
console.log(response2.message.content);
// embeddings
const embedModel = new OpenAIEmbedding({
azure: {
...azure,
deployment: process.env.EMBEDDING_MODEL,
},
const embedModel = new AzureOpenAIEmbedding({
azureADTokenProvider,
deployment: process.env.EMBEDDING_MODEL,
});
const texts = ["hello", "world"];
+7 -10
View File
@@ -9,11 +9,12 @@ import {
} from "@azure/search-documents";
import {
AzureAISearchVectorStore,
AzureOpenAI,
AzureOpenAIEmbedding,
type FilterableMetadataFieldKeysType,
IndexManagement,
MetadataIndexFieldType,
} from "@llamaindex/azure";
import { OpenAI, OpenAIEmbedding } from "@llamaindex/openai";
import { SimpleDirectoryReader } from "@llamaindex/readers/directory";
import dotenv from "dotenv";
import {
@@ -67,17 +68,13 @@ function processResults(response: NodeWithScore[], mode: VectorStoreQueryMode) {
"https://cognitiveservices.azure.com/.default",
);
// You need to deploy your own embedding model as well as your own chat completion model
const azure = {
Settings.llm = new AzureOpenAI({
azureADTokenProvider,
deployment: process.env.AZURE_DEPLOYMENT_NAME,
};
Settings.llm = new OpenAI({ azure });
Settings.embedModel = new OpenAIEmbedding({
model: process.env.EMBEDDING_MODEL,
azure: {
...azure,
deployment: process.env.EMBEDDING_MODEL,
},
});
Settings.embedModel = new AzureOpenAIEmbedding({
azureADTokenProvider,
deployment: process.env.EMBEDDING_MODEL,
});
// ---------------------------------------------------------
@@ -4,8 +4,7 @@ import {
DefaultAzureCredential,
getBearerTokenProvider,
} from "@azure/identity";
import { AzureDynamicSessionTool } from "@llamaindex/azure";
import { OpenAI } from "@llamaindex/openai";
import { AzureDynamicSessionTool, AzureOpenAI } from "@llamaindex/azure";
import { ReActAgent } from "llamaindex";
async function main() {
@@ -15,14 +14,10 @@ async function main() {
"https://cognitiveservices.azure.com/.default",
);
const azure = {
// configure LLM model
const llm = new AzureOpenAI({
azureADTokenProvider,
deployment: process.env.AZURE_OPENAI_DEPLOYMENT ?? "gpt-35-turbo",
};
// configure LLM model
const llm = new OpenAI({
azure,
});
const azureDynamicSession = new AzureDynamicSessionTool();
@@ -2,10 +2,11 @@ import { CosmosClient } from "@azure/cosmos";
import { DefaultAzureCredential } from "@azure/identity";
import {
AzureCosmosDBNoSQLConfig,
AzureOpenAI,
AzureOpenAIEmbedding,
SimpleCosmosDBReader,
SimpleCosmosDBReaderLoaderConfig,
} from "@llamaindex/azure";
import { OpenAI, OpenAIEmbedding } from "@llamaindex/openai";
import * as dotenv from "dotenv";
import {
Settings,
@@ -31,23 +32,19 @@ const vectorCollectionName =
// This example uses Azure OpenAI llm and embedding models
const llmInit = {
azure: {
apiVersion: process.env.AZURE_OPENAI_LLM_API_VERSION,
endpoint: process.env.AZURE_OPENAI_LLM_ENDPOINT,
apiKey: process.env.AZURE_OPENAI_LLM_API_KEY,
},
apiVersion: process.env.AZURE_OPENAI_LLM_API_VERSION,
endpoint: process.env.AZURE_OPENAI_LLM_ENDPOINT,
apiKey: process.env.AZURE_OPENAI_LLM_API_KEY,
};
const embedModelInit = {
azure: {
apiVersion: process.env.AZURE_OPENAI_EMBEDDING_API_VERSION,
endpoint: process.env.AZURE_OPENAI_EMBEDDING_ENDPOINT,
apiKey: process.env.AZURE_OPENAI_EMBEDDING_API_KEY,
},
apiVersion: process.env.AZURE_OPENAI_EMBEDDING_API_VERSION,
endpoint: process.env.AZURE_OPENAI_EMBEDDING_ENDPOINT,
apiKey: process.env.AZURE_OPENAI_EMBEDDING_API_KEY,
};
Settings.llm = new OpenAI(llmInit);
Settings.embedModel = new OpenAIEmbedding(embedModelInit);
Settings.llm = new AzureOpenAI(llmInit);
Settings.embedModel = new AzureOpenAIEmbedding(embedModelInit);
// Initialize the CosmosDB client
async function initializeCosmosClient() {
@@ -1,7 +1,10 @@
import { CosmosClient } from "@azure/cosmos";
import { DefaultAzureCredential } from "@azure/identity";
import { AzureCosmosDBNoSQLConfig } from "@llamaindex/azure";
import { OpenAI, OpenAIEmbedding } from "@llamaindex/openai";
import {
AzureCosmosDBNoSQLConfig,
AzureOpenAI,
AzureOpenAIEmbedding,
} from "@llamaindex/azure";
import * as dotenv from "dotenv";
import {
Settings,
@@ -25,23 +28,19 @@ const containerName =
process.env.AZURE_COSMOSDB_VECTOR_CONTAINER_NAME || "vectorContainer";
const llmInit = {
azure: {
apiVersion: process.env.AZURE_OPENAI_LLM_API_VERSION,
endpoint: process.env.AZURE_OPENAI_LLM_ENDPOINT,
apiKey: process.env.AZURE_OPENAI_LLM_API_KEY,
},
apiVersion: process.env.AZURE_OPENAI_LLM_API_VERSION,
endpoint: process.env.AZURE_OPENAI_LLM_ENDPOINT,
apiKey: process.env.AZURE_OPENAI_LLM_API_KEY,
};
const embedModelInit = {
azure: {
apiVersion: process.env.AZURE_OPENAI_EMBEDDING_API_VERSION,
endpoint: process.env.AZURE_OPENAI_EMBEDDING_ENDPOINT,
apiKey: process.env.AZURE_OPENAI_EMBEDDING_API_KEY,
},
apiVersion: process.env.AZURE_OPENAI_EMBEDDING_API_VERSION,
endpoint: process.env.AZURE_OPENAI_EMBEDDING_ENDPOINT,
apiKey: process.env.AZURE_OPENAI_EMBEDDING_API_KEY,
};
Settings.llm = new OpenAI(llmInit);
Settings.embedModel = new OpenAIEmbedding(embedModelInit);
Settings.llm = new AzureOpenAI(llmInit);
Settings.embedModel = new AzureOpenAIEmbedding(embedModelInit);
async function initializeStores() {
// Create a configuration object for the Azure CosmosDB NoSQL Vector Store
+2 -1
View File
@@ -2,7 +2,8 @@ import { CollectionReference } from "@google-cloud/firestore";
import "dotenv/config";
import { FirestoreVectorStore } from "@llamaindex/firestore";
import { OpenAIEmbedding, Settings } from "llamaindex";
import { OpenAIEmbedding } from "@llamaindex/openai";
import { Settings } from "llamaindex";
const indexName = "MovieReviews";
+1 -1
View File
@@ -2,8 +2,8 @@ import { CollectionReference } from "@google-cloud/firestore";
import { CSVReader } from "@llamaindex/readers/csv";
import "dotenv/config";
import { OpenAIEmbedding } from "@llamaindex/openai";
import {
OpenAIEmbedding,
Settings,
storageContextFromDefaults,
VectorStoreIndex,
+2 -1
View File
@@ -1,6 +1,7 @@
import "dotenv/config";
import { OpenAIEmbedding, Settings, VectorStoreIndex } from "llamaindex";
import { OpenAIEmbedding } from "@llamaindex/openai";
import { Settings, VectorStoreIndex } from "llamaindex";
import { CollectionReference } from "@google-cloud/firestore";
import { FirestoreVectorStore } from "@llamaindex/firestore";
+3 -8
View File
@@ -10,13 +10,8 @@
"outDir": "./lib",
"tsBuildInfoFile": "./lib/.tsbuildinfo",
"incremental": true,
"composite": true
"composite": true,
"jsx": "react-jsx"
},
"ts-node": {
"files": true,
"compilerOptions": {
"module": "commonjs"
}
},
"include": ["./**/*.ts"]
"include": ["./**/*.ts", "./**/*.tsx"]
}
+8
View File
@@ -1,5 +1,13 @@
# @llamaindex/autotool
## 8.0.0
### Patch Changes
- Updated dependencies [b0cd530]
- Updated dependencies [361a685]
- llamaindex@0.11.0
## 7.0.6
### Patch Changes
@@ -1,5 +1,14 @@
# @llamaindex/autotool-01-node-example
## 0.0.108
### Patch Changes
- Updated dependencies [b0cd530]
- Updated dependencies [361a685]
- llamaindex@0.11.0
- @llamaindex/autotool@8.0.0
## 0.0.107
### Patch Changes
@@ -13,5 +13,5 @@
"scripts": {
"start": "node --import tsx --import @llamaindex/autotool/node ./src/index.ts"
},
"version": "0.0.107"
"version": "0.0.108"
}
+1 -1
View File
@@ -6,7 +6,7 @@
"url": "git+https://github.com/run-llama/LlamaIndexTS.git",
"directory": "packages/autotool"
},
"version": "7.0.6",
"version": "8.0.0",
"description": "auto transpile your JS function to LLM Agent compatible",
"files": [
"dist",
+8
View File
@@ -1,5 +1,13 @@
# @llamaindex/cloud
## 4.0.8
### Patch Changes
- Updated dependencies [680b529]
- Updated dependencies [361a685]
- @llamaindex/core@0.6.6
## 4.0.7
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/cloud",
"version": "4.0.7",
"version": "4.0.8",
"type": "module",
"license": "MIT",
"scripts": {
+7
View File
@@ -1,5 +1,12 @@
# @llamaindex/core
## 0.6.6
### Patch Changes
- 680b529: Remove requireContext from tools - better use binding to pass context
- 361a685: Remove old workflows - use @llamaindex/workflow package
## 0.6.5
### Patch Changes
+1 -12
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/core",
"type": "module",
"version": "0.6.5",
"version": "0.6.6",
"description": "LlamaIndex Core Module",
"exports": {
"./agent": {
@@ -136,17 +136,6 @@
},
"default": "./indices/dist/index.js"
},
"./workflow": {
"require": {
"types": "./workflow/dist/index.d.cts",
"default": "./workflow/dist/index.cjs"
},
"import": {
"types": "./workflow/dist/index.d.ts",
"default": "./workflow/dist/index.js"
},
"default": "./workflow/dist/index.js"
},
"./memory": {
"require": {
"types": "./memory/dist/index.d.cts",
@@ -9,7 +9,7 @@ export function getEmbeddedModel(): BaseEmbedding {
embeddedModelAsyncLocalStorage.getStore() ?? globalEmbeddedModel;
if (!currentEmbeddedModel) {
throw new Error(
"Cannot find Embedding, please set `Settings.embedModel = ...` on the top of your code",
"Cannot find Embedding, please set `Settings.embedModel = ...` on the top of your code. Check https://ts.llamaindex.ai/docs/llamaindex/modules/models/embeddings for details.",
);
}
return currentEmbeddedModel;
+1 -1
View File
@@ -8,7 +8,7 @@ export function getLLM(): LLM {
const currentLLM = llmAsyncLocalStorage.getStore() ?? globalLLM;
if (!currentLLM) {
throw new Error(
"Cannot find LLM, please set `Settings.llm = ...` on the top of your code",
"Cannot find LLM, please set `Settings.llm = ...` on the top of your code. Check https://ts.llamaindex.ai/docs/llamaindex/modules/models/llms for details.",
);
}
return currentLLM;
-4
View File
@@ -256,10 +256,6 @@ export type ToolMetadata<
* @link https://json-schema.org/understanding-json-schema
*/
parameters?: Parameters;
/**
* Whether the tool requires workflow context to be passed in.
*/
requireContext?: boolean;
};
/**
+3 -19
View File
@@ -134,32 +134,16 @@ export class FunctionTool<
};
call = (input: T) => {
if (this.#metadata.requireContext) {
const inputWithContext = input as Record<string, unknown>;
if (!inputWithContext.context) {
throw new Error(
"Tool call requires context, but context parameter is missing",
);
}
}
let params = input;
if (this.#zodType) {
const result = this.#zodType.safeParse(input);
if (result.success) {
if (this.#metadata.requireContext) {
const { context } = input as Record<string, unknown>;
return this.#fn.call(
null,
{ context, ...result.data },
this.#additionalArg,
);
} else {
return this.#fn.call(null, result.data, this.#additionalArg);
}
params = result.data;
} else {
console.warn(result.error.errors);
}
}
return this.#fn.call(null, input, this.#additionalArg);
return this.#fn.call(null, params, this.#additionalArg);
};
}
-114
View File
@@ -1,114 +0,0 @@
import { type EventTypes, type WorkflowEvent } from "./events";
import { type StepFunction, type Workflow } from "./workflow";
export class Context {
#workflow: Workflow;
#queues: Map<StepFunction, WorkflowEvent[]> = new Map();
#eventBuffer: Map<EventTypes, WorkflowEvent[]> = new Map();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
#globals: Map<string, any> = new Map();
#streamingQueue: WorkflowEvent[] = [];
running: boolean = true;
#verbose: boolean = false;
constructor(params: { workflow: Workflow; verbose?: boolean }) {
this.#workflow = params.workflow;
this.#verbose = params.verbose ?? false;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
set(key: string, value: any): void {
this.#globals.set(key, value);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
get(key: string, defaultValue?: any): any {
if (this.#globals.has(key)) {
return this.#globals.get(key);
} else if (defaultValue !== undefined) {
return defaultValue;
}
throw new Error(`Key '${key}' not found in Context`);
}
collectEvents(
event: WorkflowEvent,
expected: EventTypes[],
): WorkflowEvent[] | null {
const eventType = event.constructor as EventTypes;
if (!this.#eventBuffer.has(eventType)) {
this.#eventBuffer.set(eventType, []);
}
this.#eventBuffer.get(eventType)!.push(event);
const retval: WorkflowEvent[] = [];
for (const expectedType of expected) {
const events = this.#eventBuffer.get(expectedType);
if (events && events.length > 0) {
retval.push(events.shift()!);
}
}
if (retval.length === expected.length) {
return retval;
}
// Put back the events if unable to collect all
for (const ev of retval) {
const eventType = ev.constructor as EventTypes;
if (!this.#eventBuffer.has(eventType)) {
this.#eventBuffer.set(eventType, []);
}
this.#eventBuffer.get(eventType)!.unshift(ev);
}
return null;
}
sendEvent(message: WorkflowEvent, step?: StepFunction): void {
const stepName = step?.name ? `step ${step.name}` : "all steps";
if (this.#verbose) {
console.log(`Sending event ${message} to ${stepName}`);
}
if (step === undefined) {
for (const queue of this.#queues.values()) {
queue.push(message);
}
} else {
if (!this.#workflow.hasStep(step)) {
throw new Error(`Step ${step} does not exist`);
}
if (!this.#queues.has(step)) {
this.#queues.set(step, []);
}
this.#queues.get(step)!.push(message);
}
}
getNextEvent(step: StepFunction): WorkflowEvent | undefined {
const queue = this.#queues.get(step);
if (queue && queue.length > 0) {
return queue.shift();
}
return undefined;
}
writeEventToStream(event: WorkflowEvent): void {
this.#streamingQueue.push(event);
}
async *streamEvents(): AsyncGenerator<WorkflowEvent, void, void> {
while (true) {
const event = this.#streamingQueue.shift();
if (event) {
yield event;
} else {
if (!this.running) {
break;
}
await new Promise((resolve) => setTimeout(resolve, 0));
}
}
}
}
-20
View File
@@ -1,20 +0,0 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export class WorkflowEvent<T extends Record<string, any> = any> {
data: T;
constructor(data: T) {
this.data = data;
}
toString() {
return `${this.constructor.name}(${JSON.stringify(this.data)})`;
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type EventTypes<T extends Record<string, any> = any> = new (
data: T,
) => WorkflowEvent<T>;
export class StartEvent<T = string> extends WorkflowEvent<{ input: T }> {}
export class StopEvent<T = string> extends WorkflowEvent<{ result: T }> {}
-3
View File
@@ -1,3 +0,0 @@
export * from "./context";
export * from "./events";
export * from "./workflow";
-238
View File
@@ -1,238 +0,0 @@
import { Context } from "./context";
import {
type EventTypes,
StartEvent,
StopEvent,
WorkflowEvent,
} from "./events";
export type StepFunction<T extends WorkflowEvent = WorkflowEvent> = (
context: Context,
ev: T,
) => Promise<WorkflowEvent | void>;
type EventTypeParam = EventTypes | EventTypes[];
let once = false;
export class Workflow {
#steps: Map<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
StepFunction<any>,
{ inputs: EventTypes[]; outputs: EventTypes[] | undefined }
> = new Map();
#contexts: Set<Context> = new Set();
#verbose: boolean = false;
#timeout: number | null = null;
#validate: boolean = false;
constructor(
params: {
verbose?: boolean;
timeout?: number;
validate?: boolean;
ignoreDeprecatedWarning?: boolean;
} = {},
) {
if (!once && !params.ignoreDeprecatedWarning) {
console.warn(
"@llamaindex/core/workflow is going to use the new workflow API in the next major version.",
"Please update your imports to @llamaindex/workflow",
);
console.warn(
"See https://ts.llamaindex.ai/docs/llamaindex/guide/workflow for more information",
);
once = true;
}
this.#verbose = params.verbose ?? false;
this.#timeout = params.timeout ?? null;
this.#validate = params.validate ?? false;
}
addStep<T extends WorkflowEvent>(
eventType: EventTypeParam,
method: StepFunction<T>,
params: { outputs?: EventTypeParam } = {},
) {
const inputs = Array.isArray(eventType) ? eventType : [eventType];
const outputs = params.outputs
? Array.isArray(params.outputs)
? params.outputs
: [params.outputs]
: undefined;
this.#steps.set(method, { inputs, outputs });
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
hasStep(step: StepFunction<any>): boolean {
return this.#steps.has(step);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
#acceptsEvent(step: StepFunction<any>, event: WorkflowEvent): boolean {
const eventType = event.constructor as EventTypes;
const stepInfo = this.#steps.get(step);
if (!stepInfo) {
throw new Error(`No method found for step: ${step.name}`);
}
return stepInfo.inputs.includes(eventType);
}
async *streamEvents(): AsyncGenerator<WorkflowEvent, void> {
if (this.#contexts.size > 1) {
throw new Error(
"This workflow has multiple concurrent runs in progress and cannot stream events. " +
"To be able to stream events, make sure you call `run()` on this workflow only once.",
);
}
const context = this.#contexts.values().next().value;
if (!context) {
throw new Error("No active context found for streaming events.");
}
yield* context.streamEvents();
}
validate(): void {
if (this.#verbose) {
console.log("Validating workflow...");
}
// Check if all steps have outputs defined
// precondition for the validation to work
const allStepsHaveOutputs = Array.from(this.#steps.values()).every(
(stepInfo) => stepInfo.outputs !== undefined,
);
if (!allStepsHaveOutputs) {
throw new Error(
"Not all steps have outputs defined. Can't validate. Add the 'outputs' parameter to each 'addStep' method call to do validation",
);
}
// input events that are consumed by any step of the workflow
const consumedEvents: Set<EventTypes> = new Set();
// output events that are produced by any step of the workflow
const producedEvents: Set<EventTypes> = new Set([StartEvent]);
for (const [, stepInfo] of this.#steps) {
stepInfo.inputs.forEach((eventType) => consumedEvents.add(eventType));
stepInfo.outputs?.forEach((eventType) => producedEvents.add(eventType));
}
// Check if all consumed events are produced
const unconsumedEvents = Array.from(consumedEvents).filter(
(event) => !producedEvents.has(event),
);
if (unconsumedEvents.length > 0) {
const names = unconsumedEvents.map((event) => event.name).join(", ");
throw new Error(
`The following events are consumed but never produced: ${names}`,
);
}
// Check if there are any unused produced events (except StopEvent)
const unusedEvents = Array.from(producedEvents).filter(
(event) => !consumedEvents.has(event) && event !== StopEvent,
);
if (unusedEvents.length > 0) {
const names = unusedEvents.map((event) => event.name).join(", ");
throw new Error(
`The following events are produced but never consumed: ${names}`,
);
}
if (this.#verbose) {
console.log("Workflow validation passed");
}
}
async run<T = string>(event: StartEvent<T> | string): Promise<StopEvent> {
// Validate the workflow before running if #validate is true
if (this.#validate) {
this.validate();
}
const context = new Context({ workflow: this, verbose: this.#verbose });
this.#contexts.add(context);
const stopWorkflow = () => {
if (context.running) {
context.running = false;
this.#contexts.delete(context);
}
};
const startEvent: WorkflowEvent =
typeof event === "string" ? new StartEvent({ input: event }) : event;
if (this.#verbose) {
console.log(`Starting workflow with event ${startEvent}`);
}
const workflowPromise = new Promise<StopEvent>((resolve, reject) => {
for (const [step] of this.#steps) {
// send initial event to step
context.sendEvent(startEvent, step);
if (this.#verbose) {
console.log(`Starting tasks for step ${step.name}`);
}
queueMicrotask(async () => {
try {
while (context.running) {
const currentEvent = context.getNextEvent(step);
if (!currentEvent) {
// if there's no event, wait and try again
await new Promise((resolve) => setTimeout(resolve, 0));
continue;
}
if (!this.#acceptsEvent(step, currentEvent)) {
// step does not accept current event, skip it
continue;
}
if (this.#verbose) {
console.log(`Step ${step.name} received event ${currentEvent}`);
}
const result = await step.call(this, context, currentEvent);
if (!context.running) {
// workflow was stopped during the execution (e.g. there was a timeout)
return;
}
if (result instanceof StopEvent) {
if (this.#verbose) {
console.log(`Stopping workflow with event ${result}`);
}
resolve(result);
return;
}
if (result instanceof WorkflowEvent) {
context.sendEvent(result);
}
}
} catch (error) {
if (this.#verbose) {
console.error(`Error in calling step ${step.name}:`, error);
}
reject(error as Error);
} finally {
stopWorkflow();
}
});
}
});
if (this.#timeout !== null) {
const timeout = this.#timeout;
const timeoutPromise = new Promise<never>((_, reject) =>
setTimeout(() => {
stopWorkflow();
reject(new Error(`Operation timed out after ${timeout} seconds`));
}, timeout * 1000),
);
return Promise.race([workflowPromise, timeoutPromise]);
}
return workflowPromise;
}
}
-236
View File
@@ -1,236 +0,0 @@
import { beforeEach, describe, expect, test, vi, type Mocked } from "vitest";
import type { Context } from "../src/workflow/context.js";
import {
StartEvent,
StopEvent,
WorkflowEvent,
} from "../src/workflow/events.js";
import { Workflow } from "../src/workflow/workflow.js";
// mock OpenAI class for testing
class OpenAI {
complete = vi.fn();
}
class JokeEvent extends WorkflowEvent<{ joke: string }> {}
class AnalysisEvent extends WorkflowEvent<{ analysis: string }> {}
describe("Workflow", () => {
let mockLLM: Mocked<OpenAI>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let generateJoke: Mocked<any>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let critiqueJoke: Mocked<any>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let analyzeJoke: Mocked<any>;
beforeEach(() => {
mockLLM = new OpenAI() as Mocked<OpenAI>;
mockLLM.complete
.mockResolvedValueOnce({
text: "Why do pirates make great singers? They can hit the high Cs!",
})
.mockResolvedValueOnce({
text: "This joke is clever but could use improvement...",
})
.mockResolvedValueOnce({
text: "The analysis is insightful and helpful.",
});
generateJoke = vi.fn(async (_context, ev: StartEvent) => {
const response = await mockLLM.complete({
prompt: `Write your best joke about ${ev.data.input}.`,
});
return new JokeEvent({ joke: response.text });
});
critiqueJoke = vi.fn(async (_context, ev: JokeEvent) => {
const response = await mockLLM.complete({
prompt: `Give a thorough critique of the following joke: ${ev.data.joke}`,
});
return new StopEvent({ result: response.text });
});
analyzeJoke = vi.fn(async (_context: Context, ev: JokeEvent) => {
const prompt = `Give a thorough analysis of the following joke: ${ev.data.joke}`;
const response = await mockLLM.complete({ prompt });
return new AnalysisEvent({ analysis: response.text });
});
});
test("addStep", () => {
const jokeFlow = new Workflow({ verbose: true });
jokeFlow.addStep(StartEvent, generateJoke);
jokeFlow.addStep(JokeEvent, critiqueJoke);
expect(jokeFlow.hasStep(generateJoke)).toBe(true);
expect(jokeFlow.hasStep(critiqueJoke)).toBe(true);
});
test("run workflow", async () => {
const jokeFlow = new Workflow({ verbose: true });
jokeFlow.addStep(StartEvent, generateJoke);
jokeFlow.addStep(JokeEvent, critiqueJoke);
const result = await jokeFlow.run("pirates");
expect(generateJoke).toHaveBeenCalledTimes(1);
expect(critiqueJoke).toHaveBeenCalledTimes(1);
expect(result.data.result).toBe(
"This joke is clever but could use improvement...",
);
});
test("stream events", async () => {
const jokeFlow = new Workflow({ verbose: true });
jokeFlow.addStep(StartEvent, generateJoke);
jokeFlow.addStep(JokeEvent, critiqueJoke);
const run = jokeFlow.run("pirates");
const event = await jokeFlow.streamEvents().next(); // get one event to avoid testing timeout
const result = await run;
expect(generateJoke).toHaveBeenCalledTimes(1);
expect(critiqueJoke).toHaveBeenCalledTimes(1);
expect(result.data.result).toBe(
"This joke is clever but could use improvement...",
);
expect(event).not.toBeNull();
});
test("workflow timeout", async () => {
const TIMEOUT = 1;
const jokeFlow = new Workflow({ verbose: true, timeout: TIMEOUT });
const longRunning = async (_context: Context, ev: StartEvent) => {
await new Promise((resolve) => setTimeout(resolve, 2000)); // Wait for 2 seconds
return new StopEvent({ result: "We waited 2 seconds" });
};
jokeFlow.addStep(StartEvent, longRunning);
const run = jokeFlow.run("Let's start");
await expect(run).rejects.toThrow(
`Operation timed out after ${TIMEOUT} seconds`,
);
});
test("workflow validation", async () => {
const jokeFlow = new Workflow({ verbose: true, validate: true });
jokeFlow.addStep(StartEvent, generateJoke, { outputs: StopEvent });
jokeFlow.addStep(JokeEvent, critiqueJoke, { outputs: StopEvent });
const run = jokeFlow.run("pirates");
await expect(run).rejects.toThrow(
"The following events are consumed but never produced: JokeEvent",
);
});
test("collectEvents", async () => {
let collectedEvents: WorkflowEvent[] | null = null;
const jokeFlow = new Workflow({ verbose: true });
jokeFlow.addStep(StartEvent, generateJoke);
jokeFlow.addStep(JokeEvent, analyzeJoke);
jokeFlow.addStep([AnalysisEvent], async (context, ev) => {
collectedEvents = context.collectEvents(ev, [AnalysisEvent]);
return new StopEvent({ result: "Report generated" });
});
const result = await jokeFlow.run("pirates");
expect(generateJoke).toHaveBeenCalledTimes(1);
expect(analyzeJoke).toHaveBeenCalledTimes(1);
expect(result.data.result).toBe("Report generated");
expect(collectedEvents).toHaveLength(1);
});
test("run workflow with object-based StartEvent and StopEvent", async () => {
const objectFlow = new Workflow({ verbose: true });
type Person = { name: string; age: number };
const processObject = vi.fn(async (_context, ev: StartEvent<Person>) => {
const { name, age } = ev.data.input;
return new StopEvent({
result: { greeting: `Hello ${name}, you are ${age} years old!` },
});
});
objectFlow.addStep(StartEvent<Person>, processObject);
const result = await objectFlow.run(
new StartEvent<Person>({
input: { name: "Alice", age: 30 },
}),
);
expect(processObject).toHaveBeenCalledTimes(1);
expect(result.data.result).toEqual({
greeting: "Hello Alice, you are 30 years old!",
});
});
test("workflow with two concurrent steps", async () => {
const concurrentFlow = new Workflow({ verbose: true });
const step1 = vi.fn(async (_context, _ev: StartEvent) => {
await new Promise((resolve) => setTimeout(resolve, 200));
return new StopEvent({ result: "Step 1 completed" });
});
const step2 = vi.fn(async (_context, _ev: StartEvent) => {
await new Promise((resolve) => setTimeout(resolve, 100));
return new StopEvent({ result: "Step 2 completed" });
});
concurrentFlow.addStep(StartEvent, step1);
concurrentFlow.addStep(StartEvent, step2);
const startTime = new Date();
const result = await concurrentFlow.run("start");
const endTime = new Date();
const duration = endTime.getTime() - startTime.getTime();
expect(step1).toHaveBeenCalledTimes(1);
expect(step2).toHaveBeenCalledTimes(1);
expect(duration).toBeLessThan(200);
expect(result.data.result).toBe("Step 2 completed");
});
test("workflow with two concurrent cyclic steps", async () => {
const concurrentCyclicFlow = new Workflow({ verbose: true });
class Step1Event extends WorkflowEvent {}
class Step2Event extends WorkflowEvent {}
let step2Count = 0;
const step1 = vi.fn(async (_context, ev: StartEvent | Step1Event) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
return new Step1Event({ result: "Step 1 completed" });
});
const step2 = vi.fn(async (_context, ev: StartEvent | Step2Event) => {
await new Promise((resolve) => setTimeout(resolve, 100));
step2Count++;
if (step2Count >= 5) {
return new StopEvent({ result: "Step 2 completed 5 times" });
}
return new Step2Event({ result: "Step 2 completed" });
});
concurrentCyclicFlow.addStep([StartEvent, Step1Event], step1);
concurrentCyclicFlow.addStep([StartEvent, Step2Event], step2);
const startTime = new Date();
const result = await concurrentCyclicFlow.run("start");
const endTime = new Date();
const duration = endTime.getTime() - startTime.getTime();
expect(step1).toHaveBeenCalledTimes(1);
expect(step2).toHaveBeenCalledTimes(5);
expect(duration).toBeGreaterThan(500); // At least 5 * 100ms for step2
expect(duration).toBeLessThan(1000); // Less than 1 second
expect(result.data.result).toBe("Step 2 completed 5 times");
});
});
-8
View File
@@ -1,8 +0,0 @@
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": "./dist/index.js",
"private": true
}
+8
View File
@@ -1,5 +1,13 @@
# @llamaindex/experimental
## 0.0.177
### Patch Changes
- Updated dependencies [b0cd530]
- Updated dependencies [361a685]
- llamaindex@0.11.0
## 0.0.176
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/experimental",
"description": "Experimental package for LlamaIndexTS",
"version": "0.0.176",
"version": "0.0.177",
"type": "module",
"types": "dist/type/index.d.ts",
"main": "dist/cjs/index.js",
+25
View File
@@ -1,5 +1,30 @@
# llamaindex
## 0.11.0
### Minor Changes
- b0cd530: # Breaking Change
## What Changed
Remove default setting of llm and embedModel in Settings
## Migration Guide
Set the llm provider and embed Model in the top of your code using Settings.llm = and Settings.embedModel
- 361a685: Remove old workflows - use @llamaindex/workflow package
### Patch Changes
- Updated dependencies [680b529]
- Updated dependencies [361a685]
- @llamaindex/workflow@1.1.3
- @llamaindex/core@0.6.6
- @llamaindex/cloud@4.0.8
- @llamaindex/node-parser@2.0.6
## 0.10.6
### Patch Changes
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "llamaindex",
"version": "0.10.6",
"version": "0.11.0",
"license": "MIT",
"type": "module",
"keywords": [
@@ -24,7 +24,6 @@
"@llamaindex/core": "workspace:*",
"@llamaindex/env": "workspace:*",
"@llamaindex/node-parser": "workspace:*",
"@llamaindex/openai": "workspace:*",
"@llamaindex/workflow": "1.0.3",
"@types/lodash": "^4.17.7",
"@types/node": "^22.9.0",
+2 -2
View File
@@ -8,8 +8,8 @@ import {
import type { QueryType } from "@llamaindex/core/query-engine";
import type { BaseOutputParser } from "@llamaindex/core/schema";
import { extractText, toToolDescriptions } from "@llamaindex/core/utils";
import { OpenAI } from "@llamaindex/openai";
import { SubQuestionOutputParser } from "./OutputParser.js";
import { Settings } from "./Settings.js";
import type {
BaseQuestionGenerator,
SubQuestion,
@@ -30,7 +30,7 @@ export class LLMQuestionGenerator
constructor(init?: Partial<LLMQuestionGenerator>) {
super();
this.llm = init?.llm ?? new OpenAI();
this.llm = init?.llm ?? Settings.llm;
this.prompt = init?.prompt ?? defaultSubQuestionPrompt;
this.outputParser = init?.outputParser ?? new SubQuestionOutputParser();
}
@@ -1,73 +0,0 @@
import type {
NonStreamingChatEngineParams,
StreamingChatEngineParams,
} from "@llamaindex/core/chat-engine";
import type { MessageContent } from "@llamaindex/core/llms";
import type { BaseRetriever } from "@llamaindex/core/retriever";
import { EngineResponse, MetadataMode } from "@llamaindex/core/schema";
import { OpenAIAgent, type OpenAIAgentParams } from "@llamaindex/openai";
export interface ContextAwareConfig {
contextRetriever: BaseRetriever;
}
export interface ContextAwareState {
contextRetriever: BaseRetriever;
retrievedContext: string | null;
}
// TODO: support any LLMAgent
export type SupportedAgent = typeof OpenAIAgent;
export type AgentParams = OpenAIAgentParams;
/**
* ContextAwareAgentRunner enhances the base AgentRunner with the ability to retrieve and inject relevant context
* for each query. This allows the agent to access and utilize appropriate information from a given index or retriever,
* providing more informed and context-specific responses to user queries.
*/
export function withContextAwareness(Base: SupportedAgent) {
return class ContextAwareAgent extends Base {
public readonly contextRetriever: BaseRetriever;
public retrievedContext: string | null = null;
constructor(params: AgentParams & ContextAwareConfig) {
super(params);
this.contextRetriever = params.contextRetriever;
}
async retrieveContext(query: MessageContent): Promise<string> {
const nodes = await this.contextRetriever.retrieve({ query });
return nodes
.map((node) => node.node.getContent(MetadataMode.NONE))
.join("\n");
}
async injectContext(context: string): Promise<void> {
const systemMessage = this.chatHistory.find(
(msg) => msg.role === "system",
);
if (systemMessage) {
systemMessage.content = `${context}\n\n${systemMessage.content}`;
} else {
this.chatHistory.unshift({ role: "system", content: context });
}
}
async chat(params: NonStreamingChatEngineParams): Promise<EngineResponse>;
async chat(
params: StreamingChatEngineParams,
): Promise<ReadableStream<EngineResponse>>;
async chat(
params: NonStreamingChatEngineParams | StreamingChatEngineParams,
): Promise<EngineResponse | ReadableStream<EngineResponse>> {
const context = await this.retrieveContext(params.message);
await this.injectContext(context);
if ("stream" in params && params.stream === true) {
return super.chat(params);
} else {
return super.chat(params as NonStreamingChatEngineParams);
}
}
};
}
-1
View File
@@ -1,6 +1,5 @@
export * from "@llamaindex/core/agent";
export { OpenAIContextAwareAgent } from "./openai.js";
export {
ReACTAgentWorker,
ReActAgent,
-7
View File
@@ -1,7 +0,0 @@
import { OpenAIAgent } from "@llamaindex/openai";
import { withContextAwareness } from "./contextAwareMixin.js";
export const OpenAIContextAwareAgent = withContextAwareness(OpenAIAgent);
export type { ContextAwareConfig } from "./contextAwareMixin.js";
export * from "@llamaindex/openai";
@@ -14,7 +14,7 @@ import {
} from "@llamaindex/core/prompts";
import type { BaseNode } from "@llamaindex/core/schema";
import { MetadataMode, TextNode } from "@llamaindex/core/schema";
import { OpenAI } from "@llamaindex/openai";
import { Settings } from "../Settings.js";
import { BaseExtractor } from "./types.js";
const STRIP_REGEX = /(\r\n|\n|\r)/gm;
@@ -64,7 +64,7 @@ export class KeywordExtractor extends BaseExtractor {
super();
this.llm = options?.llm ?? new OpenAI();
this.llm = options?.llm ?? Settings.llm;
this.keywords = options?.keywords ?? 5;
this.promptTemplate = options?.promptTemplate
? new PromptTemplate({
@@ -170,7 +170,7 @@ export class TitleExtractor extends BaseExtractor {
constructor(options?: TitleExtractorsArgs) {
super();
this.llm = options?.llm ?? new OpenAI();
this.llm = options?.llm ?? Settings.llm;
this.nodes = options?.nodes ?? 5;
this.nodeTemplate = options?.nodeTemplate
@@ -330,7 +330,7 @@ export class QuestionsAnsweredExtractor extends BaseExtractor {
super();
this.llm = options?.llm ?? new OpenAI();
this.llm = options?.llm ?? Settings.llm;
this.questions = options?.questions ?? 5;
this.promptTemplate = options?.promptTemplate
? new PromptTemplate({
@@ -436,7 +436,7 @@ export class SummaryExtractor extends BaseExtractor {
super();
this.llm = options?.llm ?? new OpenAI();
this.llm = options?.llm ?? Settings.llm;
this.summaries = summaries;
this.promptTemplate = options?.promptTemplate
? new PromptTemplate({
-13
View File
@@ -1,17 +1,6 @@
//#region initial setup for OpenAI
import { OpenAI, OpenAIEmbedding } from "@llamaindex/openai";
import { Settings } from "./Settings.js";
try {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
Settings.llm;
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
Settings.embedModel;
} catch {
Settings.llm = new OpenAI();
Settings.embedModel = new OpenAIEmbedding();
}
//#endregion
export {
@@ -67,7 +56,6 @@ export { BaseDocumentStore } from "@llamaindex/core/storage/doc-store"; // expli
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 "./agent/index.js";
export * from "./cloud/index.js";
export * from "./engines/index.js";
@@ -85,5 +73,4 @@ 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
@@ -1,19 +0,0 @@
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);
}
}
+17
View File
@@ -1,5 +1,22 @@
# @llamaindex/core-test
## 0.1.1
### Patch Changes
- b0cd530: # Breaking Change
## What Changed
Remove default setting of llm and embedModel in Settings
## Migration Guide
Set the llm provider and embed Model in the top of your code using Settings.llm = and Settings.embedModel
- Updated dependencies [3e66ddc]
- @llamaindex/openai@0.4.0
## 0.1.0
### Minor Changes
+2 -1
View File
@@ -1,4 +1,5 @@
import { OpenAIEmbedding, SimilarityType, similarity } from "llamaindex";
import { OpenAIEmbedding } from "@llamaindex/openai";
import { SimilarityType, similarity } from "llamaindex";
import { beforeAll, describe, expect, test } from "vitest";
import { mockEmbeddingModel } from "./utility/mockOpenAI.js";
@@ -1,8 +1,7 @@
import { Document } from "@llamaindex/core/schema";
import { OpenAI, OpenAIEmbedding } from "@llamaindex/openai";
import {
KeywordExtractor,
OpenAI,
OpenAIEmbedding,
QuestionsAnsweredExtractor,
SentenceSplitter,
Settings,
+2 -1
View File
@@ -1,7 +1,8 @@
import { describe, expect, test } from "vitest";
// from unittest.mock import patch
import { LLMSingleSelector, OpenAI } from "llamaindex";
import { OpenAI } from "@llamaindex/openai";
import { LLMSingleSelector } from "llamaindex";
import { mocStructuredkLlmGeneration } from "./utility/mockOpenAI.js";
describe("LLMSelector", () => {
@@ -1,4 +1,9 @@
import { storageContextFromDefaults, type StorageContext } from "llamaindex";
import { OpenAIEmbedding } from "@llamaindex/openai";
import {
Settings,
storageContextFromDefaults,
type StorageContext,
} from "llamaindex";
import { existsSync, rmSync } from "node:fs";
import { mkdtemp } from "node:fs/promises";
import { tmpdir } from "node:os";
@@ -19,6 +24,7 @@ describe("StorageContext", () => {
let storageContext: StorageContext;
beforeAll(async () => {
Settings.embedModel = new OpenAIEmbedding();
storageContext = await storageContextFromDefaults({
persistDir: testDir,
});
@@ -1,6 +1,6 @@
import { OpenAIEmbedding } from "@llamaindex/openai";
import {
Document,
OpenAIEmbedding,
Settings,
SummaryIndex,
VectorStoreIndex,
@@ -1,8 +1,8 @@
import { OpenAIEmbedding } from "@llamaindex/openai";
import type { StorageContext } from "llamaindex";
import {
DocStoreStrategy,
Document,
OpenAIEmbedding,
Settings,
VectorStoreIndex,
} from "llamaindex";
-7
View File
@@ -1,7 +0,0 @@
import { expect, test, vi } from "vitest";
test("init without error", async () => {
vi.stubEnv("OPENAI_API_KEY", undefined);
const { Settings } = await import("llamaindex");
expect(Settings.llm).toBeDefined();
});
@@ -1,7 +1,7 @@
import { OpenAIEmbedding } from "@llamaindex/openai";
import {
FunctionTool,
ObjectIndex,
OpenAIEmbedding,
Settings,
SimpleToolNodeMapping,
VectorStoreIndex,
+4 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/llamaindex-test",
"private": true,
"version": "0.1.0",
"version": "0.1.1",
"type": "module",
"scripts": {
"test": "vitest run"
@@ -9,5 +9,8 @@
"devDependencies": {
"llamaindex": "workspace:*",
"vitest": "^2.1.5"
},
"dependencies": {
"@llamaindex/openai": "workspace:*"
}
}
@@ -1,6 +1,7 @@
import type { CallbackManager } from "@llamaindex/core/global";
import type { LLMChatParamsBase, OpenAIEmbedding } from "llamaindex";
import { OpenAI, Settings } from "llamaindex";
import { OpenAI, OpenAIEmbedding } from "@llamaindex/openai";
import type { LLMChatParamsBase } from "llamaindex";
import { Settings } from "llamaindex";
import { vi } from "vitest";
export const DEFAULT_LLM_TEXT_OUTPUT = "MOCK_TOKEN_1-MOCK_TOKEN_2";
@@ -1,8 +1,5 @@
import {
BaseEmbedding,
OpenAIEmbedding,
storageContextFromDefaults,
} from "llamaindex";
import { OpenAIEmbedding } from "@llamaindex/openai";
import { BaseEmbedding, storageContextFromDefaults } from "llamaindex";
import { mockEmbeddingModel } from "./mockOpenAI.js";
+8
View File
@@ -1,5 +1,13 @@
# @llamaindex/node-parser
## 2.0.6
### Patch Changes
- Updated dependencies [680b529]
- Updated dependencies [361a685]
- @llamaindex/core@0.6.6
## 2.0.5
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/node-parser",
"version": "2.0.5",
"version": "2.0.6",
"description": "Node parser for LlamaIndex",
"type": "module",
"exports": {
@@ -1,5 +1,13 @@
# @llamaindex/anthropic
## 0.3.7
### Patch Changes
- Updated dependencies [680b529]
- Updated dependencies [361a685]
- @llamaindex/core@0.6.6
## 0.3.6
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/anthropic",
"description": "Anthropic Adapter for LlamaIndex",
"version": "0.3.6",
"version": "0.3.7",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
@@ -1,5 +1,13 @@
# @llamaindex/assemblyai
## 0.1.5
### Patch Changes
- Updated dependencies [680b529]
- Updated dependencies [361a685]
- @llamaindex/core@0.6.6
## 0.1.4
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/assemblyai",
"description": "AssemblyAI Reader for LlamaIndex",
"version": "0.1.4",
"version": "0.1.5",
"type": "module",
"types": "dist/index.d.ts",
"main": "dist/index.cjs",
+8
View File
@@ -1,5 +1,13 @@
# @llamaindex/community
## 0.0.100
### Patch Changes
- Updated dependencies [680b529]
- Updated dependencies [361a685]
- @llamaindex/core@0.6.6
## 0.0.99
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/aws",
"description": "AWS package for LlamaIndexTS",
"version": "0.0.99",
"version": "0.0.100",
"type": "module",
"types": "dist/type/index.d.ts",
"main": "dist/cjs/index.js",

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