mirror of
https://github.com/run-llama/LlamaIndexTS.git
synced 2026-07-01 22:14:03 -04:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8daaef44ee | |||
| ac07e3cbe6 | |||
| 1a6137b323 | |||
| 85c2e198a4 | |||
| 01263c4cfd | |||
| fbd5e0174d | |||
| 70ccb4ae65 | |||
| 7eb331774d | |||
| 24a3f058a3 | |||
| 84c28f95f9 | |||
| 7af57982fe | |||
| 6b70c5408f | |||
| 74fc725f37 | |||
| a0a74aed60 | |||
| 11feef8c82 | |||
| 9c5ff164ac | |||
| 7edeb1c2d7 | |||
| 8b95abdc85 | |||
| ffe0cd1ef1 | |||
| 5d2111a19f | |||
| 68ac7fd57f | |||
| 7320d96a36 | |||
| ee17fb475b | |||
| 28b877e31f | |||
| 4389b80a52 | |||
| d3bc663951 | |||
| 4810364788 |
@@ -12,6 +12,10 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
POSTGRES_USER: runneradmin
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
|
||||
jobs:
|
||||
e2e:
|
||||
strategy:
|
||||
@@ -22,9 +26,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: ankane/setup-postgres@v1
|
||||
with:
|
||||
database: llamaindex_node_test
|
||||
dev-files: true
|
||||
- run: |
|
||||
cd /tmp
|
||||
git clone --branch v0.7.0 https://github.com/pgvector/pgvector.git
|
||||
cd pgvector
|
||||
make
|
||||
sudo make install
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
@@ -42,7 +54,6 @@ jobs:
|
||||
node-version: [18.x, 20.x, 22.x]
|
||||
name: Test on Node.js ${{ matrix.node-version }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
@@ -92,7 +103,8 @@ jobs:
|
||||
- nextjs-agent
|
||||
- nextjs-edge-runtime
|
||||
- nextjs-node-runtime
|
||||
# - waku-query-engine
|
||||
- waku-query-engine
|
||||
- llama-parse-browser
|
||||
runs-on: ubuntu-latest
|
||||
name: Build LlamaIndex Example (${{ matrix.packages }})
|
||||
steps:
|
||||
@@ -131,6 +143,12 @@ jobs:
|
||||
- name: Pack @llamaindex/cloud
|
||||
run: pnpm pack --pack-destination ${{ runner.temp }}
|
||||
working-directory: packages/cloud
|
||||
- name: Pack @llamaindex/openai
|
||||
run: pnpm pack --pack-destination ${{ runner.temp }}
|
||||
working-directory: packages/llm/openai
|
||||
- name: Pack @llamaindex/groq
|
||||
run: pnpm pack --pack-destination ${{ runner.temp }}
|
||||
working-directory: packages/llm/groq
|
||||
- name: Pack @llamaindex/core
|
||||
run: pnpm pack --pack-destination ${{ runner.temp }}
|
||||
working-directory: packages/core
|
||||
|
||||
@@ -36,9 +36,44 @@ For now, browser support is limited due to the lack of support for [AsyncLocalSt
|
||||
npm install llamaindex
|
||||
pnpm install llamaindex
|
||||
yarn add llamaindex
|
||||
jsr install @llamaindex/core
|
||||
```
|
||||
|
||||
### Setup TypeScript
|
||||
|
||||
```json5
|
||||
{
|
||||
compilerOptions: {
|
||||
// ⬇️ add this line to your tsconfig.json
|
||||
moduleResolution: "bundler", // or "node16"
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Why?</summary>
|
||||
We are shipping both ESM and CJS module, and compatible with Vercel Edge, Cloudflare Workers, and other serverless platforms.
|
||||
|
||||
So we are using [conditional exports](https://nodejs.org/api/packages.html#conditional-exports) to support all environments.
|
||||
|
||||
This is a kind of modern way of shipping packages, but might cause TypeScript type check to fail because of legacy module resolution.
|
||||
|
||||
Imaging you put output file into `/dist/openai.js` but you are importing `llamaindex/openai` in your code, and set `package.json` like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"exports": {
|
||||
"./openai": "./dist/openai.js"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In old module resolution, TypeScript will not be able to find the module because it is not follow the file structure, even you run `node index.js` successfully. (on Node.js >=16)
|
||||
|
||||
See more about [moduleResolution](https://www.typescriptlang.org/docs/handbook/modules/theory.html#module-resolution) or
|
||||
[TypeScript 5.0 blog](https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#--moduleresolution-bundler7).
|
||||
|
||||
</details>
|
||||
|
||||
### Node.js
|
||||
|
||||
```ts
|
||||
@@ -154,6 +189,21 @@ export async function chatWithAgent(
|
||||
}
|
||||
```
|
||||
|
||||
### Vite
|
||||
|
||||
We have some wasm dependencies for better performance. You can use `vite-plugin-wasm` to load them.
|
||||
|
||||
```ts
|
||||
import wasm from "vite-plugin-wasm";
|
||||
|
||||
export default {
|
||||
plugins: [wasm()],
|
||||
ssr: {
|
||||
external: ["tiktoken"],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## Playground
|
||||
|
||||
Check out our NextJS playground at https://llama-playground.vercel.app/. The source is available at https://github.com/run-llama/ts-playground
|
||||
|
||||
@@ -1,5 +1,46 @@
|
||||
# docs
|
||||
|
||||
## 0.0.70
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [fbd5e01]
|
||||
- Updated dependencies [6b70c54]
|
||||
- Updated dependencies [1a6137b]
|
||||
- Updated dependencies [85c2e19]
|
||||
- llamaindex@0.6.1
|
||||
|
||||
## 0.0.69
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [11feef8]
|
||||
- llamaindex@0.6.0
|
||||
- @llamaindex/examples@0.0.8
|
||||
|
||||
## 0.0.68
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [7edeb1c]
|
||||
- llamaindex@0.5.27
|
||||
|
||||
## 0.0.67
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ffe0cd1]
|
||||
- Updated dependencies [ffe0cd1]
|
||||
- llamaindex@0.5.26
|
||||
|
||||
## 0.0.66
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [4810364]
|
||||
- Updated dependencies [d3bc663]
|
||||
- llamaindex@0.5.25
|
||||
|
||||
## 0.0.65
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
label: "Agents"
|
||||
position: 3
|
||||
position: 10
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
sidebar_position: 13
|
||||
---
|
||||
|
||||
# ChatEngine
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
sidebar_position: 12
|
||||
---
|
||||
|
||||
# Index
|
||||
@@ -8,6 +8,7 @@ An index is the basic container and organization for your data. LlamaIndex.TS su
|
||||
|
||||
- `VectorStoreIndex` - will send the top-k `Node`s to the LLM when generating a response. The default top-k is 2.
|
||||
- `SummaryIndex` - will send every `Node` in the index to the LLM in order to generate a response
|
||||
- `KeywordTableIndex` extracts and provides keywords from `Node`s to the LLM
|
||||
|
||||
```typescript
|
||||
import { Document, VectorStoreIndex } from "llamaindex";
|
||||
|
||||
@@ -6,6 +6,19 @@ import CodeSource2 from "!raw-loader!../../../../../examples/readers/src/custom-
|
||||
|
||||
Before you can start indexing your documents, you need to load them into memory.
|
||||
|
||||
All "basic" data loaders can be seen below, mapped to their respective filetypes in `SimpleDirectoryReader`. More loaders are shown in the sidebar on the left.
|
||||
Additionally the following loaders exist without separate documentation:
|
||||
|
||||
- `AssemblyAIReader` transcribes audio using [AssemblyAI](https://www.assemblyai.com/).
|
||||
- [AudioTranscriptReader](../../api/classes/AudioTranscriptReader.md): loads entire transcript as a single document.
|
||||
- [AudioTranscriptParagraphsReader](../../api/classes/AudioTranscriptParagraphsReader.md): creates a document per paragraph.
|
||||
- [AudioTranscriptSentencesReader](../../api/classes/AudioTranscriptSentencesReader.md): creates a document per sentence.
|
||||
- [AudioSubtitlesReader](../../api/classes/AudioTranscriptParagraphsReader.md): creates a document containing the subtitles of a transcript.
|
||||
- [NotionReader](../../api/classes/NotionReader.md) loads [Notion](https://www.notion.so/) pages.
|
||||
- [SimpleMongoReader](../../api/classes/SimpleMongoReader) loads data from a [MongoDB](https://www.mongodb.com/).
|
||||
|
||||
Check the [LlamaIndexTS Github](https://github.com/run-llama/LlamaIndexTS) for the most up to date overview of integrations.
|
||||
|
||||
## SimpleDirectoryReader
|
||||
|
||||
[](https://stackblitz.com/github/run-llama/LlamaIndexTS/tree/main/examples/readers?file=src/simple-directory-reader.ts&title=Simple%20Directory%20Reader)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
label: "Data Stores"
|
||||
position: 2
|
||||
@@ -0,0 +1 @@
|
||||
label: "Chat Stores"
|
||||
@@ -0,0 +1,13 @@
|
||||
# Chat Stores
|
||||
|
||||
Chat stores manage chat history by storing sequences of messages in a structured way, ensuring the order of messages is maintained for accurate conversation flow.
|
||||
|
||||
## Available Chat Stores
|
||||
|
||||
- [SimpleChatStore](../../../api/classes/SimpleChatStore.md): A simple in-memory chat store with support for [persisting](../index.md#local-storage) data to disk.
|
||||
|
||||
Check the [LlamaIndexTS Github](https://github.com/run-llama/LlamaIndexTS) for the most up to date overview of integrations.
|
||||
|
||||
## API Reference
|
||||
|
||||
- [BaseChatStore](../../../api/interfaces/BaseChatStore.md)
|
||||
@@ -0,0 +1,2 @@
|
||||
label: "Document Stores"
|
||||
position: 2
|
||||
@@ -0,0 +1,14 @@
|
||||
# Document Stores
|
||||
|
||||
Document stores contain ingested document chunks, i.e. [Node](../../documents_and_nodes/index.md)s.
|
||||
|
||||
## Available Document Stores
|
||||
|
||||
- [SimpleDocumentStore](../../../api/classes/SimpleDocumentStore.md): A simple in-memory document store with support for [persisting](../index.md#local-storage) data to disk.
|
||||
- [PostgresDocumentStore](../../../api/classes/PostgresDocumentStore.md): A PostgreSQL document store, see [PostgreSQL Storage](../index.md#postgresql-storage).
|
||||
|
||||
Check the [LlamaIndexTS Github](https://github.com/run-llama/LlamaIndexTS) for the most up to date overview of integrations.
|
||||
|
||||
## API Reference
|
||||
|
||||
- [BaseDocumentStore](../../../api/classes/BaseDocumentStore.md)
|
||||
@@ -0,0 +1,56 @@
|
||||
# Storage
|
||||
|
||||
Storage in LlamaIndex.TS works automatically once you've configured a
|
||||
`StorageContext` object.
|
||||
|
||||
## Local Storage
|
||||
|
||||
You can configure the `persistDir` and attach it to an index.
|
||||
|
||||
```typescript
|
||||
import {
|
||||
Document,
|
||||
VectorStoreIndex,
|
||||
storageContextFromDefaults,
|
||||
} from "llamaindex";
|
||||
|
||||
const storageContext = await storageContextFromDefaults({
|
||||
persistDir: "./storage",
|
||||
});
|
||||
|
||||
const document = new Document({ text: "Test Text" });
|
||||
const index = await VectorStoreIndex.fromDocuments([document], {
|
||||
storageContext,
|
||||
});
|
||||
```
|
||||
|
||||
## PostgreSQL Storage
|
||||
|
||||
You can configure the `schemaName`, `tableName`, `namespace`, and
|
||||
`connectionString`. If a `connectionString` is not
|
||||
provided, it will use the environment variables `PGHOST`, `PGUSER`,
|
||||
`PGPASSWORD`, `PGDATABASE` and `PGPORT`.
|
||||
|
||||
```typescript
|
||||
import {
|
||||
Document,
|
||||
VectorStoreIndex,
|
||||
PostgresDocumentStore,
|
||||
PostgresIndexStore,
|
||||
storageContextFromDefaults,
|
||||
} from "llamaindex";
|
||||
|
||||
const storageContext = await storageContextFromDefaults({
|
||||
docStore: new PostgresDocumentStore(),
|
||||
indexStore: new PostgresIndexStore(),
|
||||
});
|
||||
|
||||
const document = new Document({ text: "Test Text" });
|
||||
const index = await VectorStoreIndex.fromDocuments([document], {
|
||||
storageContext,
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- [StorageContext](../../api/interfaces/StorageContext.md)
|
||||
@@ -0,0 +1,2 @@
|
||||
label: "Index Stores"
|
||||
position: 3
|
||||
@@ -0,0 +1,14 @@
|
||||
# Index Stores
|
||||
|
||||
Index stores are underlying storage components that contain metadata(i.e. information created when indexing) about the [index](../../data_index.md) itself.
|
||||
|
||||
## Available Index Stores
|
||||
|
||||
- [SimpleIndexStore](../../../api/classes/SimpleIndexStore.md): A simple in-memory index store with support for [persisting](../index.md#local-storage) data to disk.
|
||||
- [PostgresIndexStore](../../../api/classes/PostgresIndexStore.md): A PostgreSQL index store, , see [PostgreSQL Storage](../index.md#postgresql-storage).
|
||||
|
||||
Check the [LlamaIndexTS Github](https://github.com/run-llama/LlamaIndexTS) for the most up to date overview of integrations.
|
||||
|
||||
## API Reference
|
||||
|
||||
- [BaseIndexStore](../../../api/classes/BaseIndexStore.md)
|
||||
@@ -0,0 +1,2 @@
|
||||
label: "Key-Value Stores"
|
||||
position: 4
|
||||
@@ -0,0 +1,14 @@
|
||||
# Key-Value Stores
|
||||
|
||||
Key-Value Stores represent underlying storage components used in [Document Stores](../doc_stores/index.md) and [Index Stores](../index_stores/index.md)
|
||||
|
||||
## Available Key-Value Stores
|
||||
|
||||
- [SimpleKVStore](../../../api/classes/SimpleKVStore.md): A simple Key-Value store with support of [persisting](../index.md#local-storage) data to disk.
|
||||
- [PostgresKVStore](../../../api/classes/PostgresKVStore.md): A PostgreSQL Key-Value store, see [PostgreSQL Storage](../index.md#postgresql-storage).
|
||||
|
||||
Check the [LlamaIndexTS Github](https://github.com/run-llama/LlamaIndexTS) for the most up to date overview of integrations.
|
||||
|
||||
## API Reference
|
||||
|
||||
- [BaseKVStore](../../../api/classes/BaseKVStore.md)
|
||||
@@ -0,0 +1,22 @@
|
||||
# Vector Stores
|
||||
|
||||
Vector stores save embedding vectors of your ingested document chunks.
|
||||
|
||||
## Available Vector Stores
|
||||
|
||||
Available Vector Stores are shown on the sidebar to the left. Additionally the following integrations exist without separate documentation:
|
||||
|
||||
- [SimpleVectorStore](../../../api/classes/SimpleVectorStore.md): A simple in-memory vector store with optional [persistance](../index.md#local-storage) to disk.
|
||||
- [AstraDBVectorStore](../../../api/classes/AstraDBVectorStore.md): A cloud-native, scalable Database-as-a-Service built on Apache Cassandra, see [datastax.com](https://www.datastax.com/products/datastax-astra)
|
||||
- [ChromaVectorStore](../../../api/classes/ChromaVectorStore.md): An open-source vector database, focused on ease of use and performance, see [trychroma.com](https://www.trychroma.com/)
|
||||
- [MilvusVectorStore](../../../api/classes/MilvusVectorStore.md): An open-source, high-performance, highly scalable vector database, see [milvus.io](https://milvus.io/)
|
||||
- [MongoDBAtlasVectorSearch](../../../api/classes/MongoDBAtlasVectorSearch.md): A cloud-based vector search solution for MongoDB, see [mongodb.com](https://www.mongodb.com/products/platform/atlas-vector-search)
|
||||
- [PGVectorStore](../../../api/classes/PGVectorStore.md): An open-source vector store built on PostgreSQL, see [pgvector Github](https://github.com/pgvector/pgvector)
|
||||
- [PineconeVectorStore](../../../api/classes/PineconeVectorStore.md): A managed, cloud-native vector database, see [pinecone.io](https://www.pinecone.io/)
|
||||
- [WeaviateVectorStore](../../../api/classes/WeaviateVectorStore.md): An open-source, ai-native vector database, see [weaviate.io](https://weaviate.io/)
|
||||
|
||||
Check the [LlamaIndexTS Github](https://github.com/run-llama/LlamaIndexTS) for the most up to date overview of integrations.
|
||||
|
||||
## API Reference
|
||||
|
||||
- [VectorStoreBase](../../../api/classes/VectorStoreBase.md)
|
||||
+3
-1
@@ -1,5 +1,7 @@
|
||||
# Qdrant Vector Store
|
||||
|
||||
[qdrant.tech](https://qdrant.tech/)
|
||||
|
||||
To run this example, you need to have a Qdrant instance running. You can run it with Docker:
|
||||
|
||||
```bash
|
||||
@@ -87,4 +89,4 @@ main().catch(console.error);
|
||||
|
||||
## API Reference
|
||||
|
||||
- [QdrantVectorStore](../../api/classes/QdrantVectorStore.md)
|
||||
- [QdrantVectorStore](../../../api/classes/QdrantVectorStore.md)
|
||||
@@ -1,7 +1,3 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Documents and Nodes
|
||||
|
||||
`Document`s and `Node`s are the basic building blocks of any index. While the API for these objects is similar, `Document` objects represent entire files, while `Node`s are smaller pieces of that original document, that are suitable for an LLM and Q&A.
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
label: "Embeddings"
|
||||
position: 3
|
||||
position: 6
|
||||
|
||||
@@ -7,7 +7,7 @@ To find out more about the latest features, updates, and available models, visit
|
||||
## Table of Contents
|
||||
|
||||
1. [Setup](#setup)
|
||||
2. [Usage with LlamaIndex](#integration-with-llamaindex)
|
||||
2. [Usage with LlamaIndex](#usage-with-llamaindex)
|
||||
3. [Embeddings with Custom Parameters](#embeddings-with-custom-parameters)
|
||||
|
||||
## Setup
|
||||
|
||||
@@ -16,6 +16,16 @@ Settings.embedModel = new OpenAIEmbedding({
|
||||
|
||||
For local embeddings, you can use the [HuggingFace](./available_embeddings/huggingface.md) embedding model.
|
||||
|
||||
## Available Embeddings
|
||||
|
||||
Most available embeddings are listed in the sidebar on the left.
|
||||
Additionally the following integrations exist without separate documentation:
|
||||
|
||||
- [ClipEmbedding](../../api/classes/ClipEmbedding.md) using `@xenova/transformers`
|
||||
- [FireworksEmbedding](../../api/classes/FireworksEmbedding.md) see [fireworks.ai](https://fireworks.ai/)
|
||||
|
||||
Check the [LlamaIndexTS Github](https://github.com/run-llama/LlamaIndexTS) for the most up to date overview of integrations.
|
||||
|
||||
## API Reference
|
||||
|
||||
- [OpenAIEmbedding](../../api/classes/OpenAIEmbedding.md)
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
label: "Evaluating"
|
||||
position: 3
|
||||
position: 9
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
label: "Ingestion Pipeline"
|
||||
position: 2
|
||||
position: 4
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
label: "LLMs"
|
||||
position: 3
|
||||
position: 5
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Fireworks LLM
|
||||
|
||||
Fireworks.ai focus on production use cases for open source LLMs, offering speed and quality.
|
||||
[Fireworks.ai](https://fireworks.ai/) focus on production use cases for open source LLMs, offering speed and quality.
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Large Language Models (LLMs)
|
||||
|
||||
The LLM is responsible for reading text and generating natural language responses to queries. By default, LlamaIndex.TS uses `gpt-3.5-turbo`.
|
||||
@@ -30,6 +26,15 @@ export AZURE_OPENAI_DEPLOYMENT="gpt-4" # or some other deployment name
|
||||
|
||||
For local LLMs, currently we recommend the use of [Ollama](./available_llms/ollama.md) LLM.
|
||||
|
||||
## Available LLMs
|
||||
|
||||
Most available LLMs are listed in the sidebar on the left. Additionally the following integrations exist without separate documentation:
|
||||
|
||||
- [HuggingFaceLLM](../../api/classes/HuggingFaceLLM.md) and [HuggingFaceInferenceAPI](../../api/classes/HuggingFaceInferenceAPI.md).
|
||||
- [ReplicateLLM](../../api/classes/ReplicateLLM.md) see [replicate.com](https://replicate.com/)
|
||||
|
||||
Check the [LlamaIndexTS Github](https://github.com/run-llama/LlamaIndexTS) for the most up to date overview of integrations.
|
||||
|
||||
## API Reference
|
||||
|
||||
- [OpenAI](../../api/classes/OpenAI.md)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
sidebar_position: 11
|
||||
---
|
||||
|
||||
# NodeParser
|
||||
|
||||
@@ -107,3 +107,4 @@ const filteredNodes = processor.postprocessNodes(nodes);
|
||||
## API Reference
|
||||
|
||||
- [SimilarityPostprocessor](../../api/classes/SimilarityPostprocessor.md)
|
||||
- [MetadataReplacementPostProcessor](../../api/classes/MetadataReplacementPostProcessor.md)
|
||||
|
||||
@@ -7,7 +7,7 @@ To find out more about the latest features and updates, visit the [mixedbread.ai
|
||||
## Table of Contents
|
||||
|
||||
1. [Setup](#setup)
|
||||
2. [Usage with LlamaIndex](#integration-with-llamaindex)
|
||||
2. [Usage with LlamaIndex](#usage-with-llamaindex)
|
||||
3. [Simple Reranking Guide](#simple-reranking-guide)
|
||||
4. [Reranking with Objects](#reranking-with-objects)
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
label: "Prompts"
|
||||
position: 0
|
||||
position: 7
|
||||
|
||||
@@ -73,6 +73,5 @@ const response = await queryEngine.query({
|
||||
|
||||
## API Reference
|
||||
|
||||
- [TextQaPrompt](../../api/type-aliases/TextQaPrompt.md)
|
||||
- [ResponseSynthesizer](../../api/classes/ResponseSynthesizer.md)
|
||||
- [CompactAndRefine](../../api/classes/CompactAndRefine.md)
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
label: "Query Engines"
|
||||
position: 2
|
||||
position: 8
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 6
|
||||
sidebar_position: 15
|
||||
---
|
||||
|
||||
# ResponseSynthesizer
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
sidebar_position: 14
|
||||
---
|
||||
|
||||
# Retriever
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
---
|
||||
sidebar_position: 7
|
||||
---
|
||||
|
||||
# Storage
|
||||
|
||||
Storage in LlamaIndex.TS works automatically once you've configured a `StorageContext` object. Just configure the `persistDir` and attach it to an index.
|
||||
|
||||
Right now, only saving and loading from disk is supported, with future integrations planned!
|
||||
|
||||
```typescript
|
||||
import { Document, VectorStoreIndex, storageContextFromDefaults } from "./src";
|
||||
|
||||
const storageContext = await storageContextFromDefaults({
|
||||
persistDir: "./storage",
|
||||
});
|
||||
|
||||
const document = new Document({ text: "Test Text" });
|
||||
const index = await VectorStoreIndex.fromDocuments([document], {
|
||||
storageContext,
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- [StorageContext](../api/interfaces/StorageContext.md)
|
||||
@@ -0,0 +1,168 @@
|
||||
import CodeBlock from "@theme/CodeBlock";
|
||||
import CodeSource from "!raw-loader!../../../../examples/workflow/joke.ts";
|
||||
|
||||
# Workflows
|
||||
|
||||
A `Workflow` in LlamaIndexTS is an event-driven abstraction used to chain together several events. Workflows are made up of `steps`, with each step responsible for handling certain event types and emitting new events.
|
||||
|
||||
Workflows in LlamaIndexTS work by defining step functions that handle specific event types and emit new events.
|
||||
|
||||
When a step function is added to a workflow, you need to specify the input and optionally the output event types (used for validation). The specification of the input events ensures each step only runs when an accepted event is ready.
|
||||
|
||||
You can create a `Workflow` to do anything! Build an agent, a RAG flow, an extraction flow, or anything else you want.
|
||||
|
||||
## Getting Started
|
||||
|
||||
As an illustrative example, let's consider a naive workflow where a joke is generated and then critiqued.
|
||||
|
||||
<CodeBlock language="ts">{CodeSource}</CodeBlock>
|
||||
|
||||
There's a few moving pieces here, so let's go through this piece by piece.
|
||||
|
||||
### Defining Workflow Events
|
||||
|
||||
```typescript
|
||||
export class JokeEvent extends WorkflowEvent<{ joke: string }> {}
|
||||
```
|
||||
|
||||
Events are user-defined classes that extend `WorkflowEvent` and contain arbitrary data provided as template argument. In this case, our workflow relies on a single user-defined event, the `JokeEvent` with a `joke` attribute of type `string`.
|
||||
|
||||
### Setting up the Workflow Class
|
||||
|
||||
```typescript
|
||||
const llm = new OpenAI();
|
||||
...
|
||||
const jokeFlow = new Workflow({ verbose: true });
|
||||
```
|
||||
|
||||
Our workflow is implemented by initiating the `Workflow` class. For simplicity, we created a `OpenAI` llm instance.
|
||||
|
||||
### Workflow Entry Points
|
||||
|
||||
```typescript
|
||||
const generateJoke = async (_context: Context, ev: StartEvent) => {
|
||||
const prompt = `Write your best joke about ${ev.data.input}.`;
|
||||
const response = await llm.complete({ prompt });
|
||||
return new JokeEvent({ joke: response.text });
|
||||
};
|
||||
```
|
||||
|
||||
Here, we come to the entry-point of our workflow. While events are user-defined, there are two special-case events, the `StartEvent` and the `StopEvent`. Here, the `StartEvent` signifies where to send the initial workflow input.
|
||||
|
||||
The `StartEvent` is a bit of a special object since it can hold arbitrary attributes. Here, we accessed the topic with `ev.data.input`.
|
||||
|
||||
At this point, you may have noticed that we haven't explicitly told the workflow what events are handled by which steps.
|
||||
|
||||
To do so, we use the `addStep` method which adds a step to the workflow. The first argument is the event type that the step will handle, and the second argument is the previously defined step function:
|
||||
|
||||
```typescript
|
||||
jokeFlow.addStep(StartEvent, generateJoke);
|
||||
```
|
||||
|
||||
### Workflow Exit Points
|
||||
|
||||
```typescript
|
||||
const critiqueJoke = async (_context: Context, ev: JokeEvent) => {
|
||||
const prompt = `Give a thorough critique of the following joke: ${ev.data.joke}`;
|
||||
const response = await llm.complete({ prompt });
|
||||
return new StopEvent({ result: response.text });
|
||||
};
|
||||
```
|
||||
|
||||
Here, we have our second, and last step, in the workflow. We know its the last step because the special `StopEvent` is returned. When the workflow encounters a returned `StopEvent`, it immediately stops the workflow and returns whatever the result was.
|
||||
|
||||
In this case, the result is a string, but it could be a map, array, or any other object.
|
||||
|
||||
Don't forget to add the step to the workflow:
|
||||
|
||||
```typescript
|
||||
jokeFlow.addStep(JokeEvent, critiqueJoke);
|
||||
```
|
||||
|
||||
### Running the Workflow
|
||||
|
||||
```typescript
|
||||
const result = await jokeFlow.run("pirates");
|
||||
console.log(result.data.result);
|
||||
```
|
||||
|
||||
Lastly, we run the workflow. The `.run()` method is async, so we use await here to wait for the result.
|
||||
|
||||
### Validating Workflows
|
||||
|
||||
To tell the workflow what events are produced by each step, you can optionally provide a third argument to `addStep` to specify the output event type:
|
||||
|
||||
```typescript
|
||||
jokeFlow.addStep(StartEvent, generateJoke, { outputs: JokeEvent });
|
||||
jokeFlow.addStep(JokeEvent, critiqueJoke, { outputs: StopEvent });
|
||||
```
|
||||
|
||||
To validate a workflow, you need to call the `validate` method:
|
||||
|
||||
```typescript
|
||||
jokeFlow.validate();
|
||||
```
|
||||
|
||||
To automatically validate a workflow when you run it, you can set the `validate` flag to `true` at initialization:
|
||||
|
||||
```typescript
|
||||
const jokeFlow = new Workflow({ verbose: true, validate: true });
|
||||
```
|
||||
|
||||
## Working with Global Context/State
|
||||
|
||||
Optionally, you can choose to use global context between steps. For example, maybe multiple steps access the original `query` input from the user. You can store this in global context so that every step has access.
|
||||
|
||||
```typescript
|
||||
import { Context } from "@llamaindex/core/workflow";
|
||||
|
||||
const query = async (context: Context, ev: MyEvent) => {
|
||||
// get the query from the context
|
||||
const query = context.get("query");
|
||||
// do something with context and event
|
||||
const val = ...
|
||||
const result = ...
|
||||
// store in context
|
||||
context.set("key", val);
|
||||
|
||||
return new StopEvent({ result });
|
||||
};
|
||||
```
|
||||
|
||||
## Waiting for Multiple Events
|
||||
|
||||
The context does more than just hold data, it also provides utilities to buffer and wait for multiple events.
|
||||
|
||||
For example, you might have a step that waits for a query and retrieved nodes before synthesizing a response:
|
||||
|
||||
```typescript
|
||||
const synthesize = async (context: Context, ev: QueryEvent | RetrieveEvent) => {
|
||||
const events = context.collectEvents(ev, [QueryEvent | RetrieveEvent]);
|
||||
if (!events) {
|
||||
return;
|
||||
}
|
||||
const prompt = events
|
||||
.map((event) => {
|
||||
if (event instanceof QueryEvent) {
|
||||
return `Answer this query using the context provided: ${event.data.query}`;
|
||||
} else if (event instanceof RetrieveEvent) {
|
||||
return `Context: ${event.data.context}`;
|
||||
}
|
||||
return "";
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
const response = await llm.complete({ prompt });
|
||||
return new StopEvent({ result: response.text });
|
||||
};
|
||||
```
|
||||
|
||||
Using `ctx.collectEvents()` we can buffer and wait for ALL expected events to arrive. This function will only return events (in the requested order) once all events have arrived.
|
||||
|
||||
## Manually Triggering Events
|
||||
|
||||
Normally, events are triggered by returning another event during a step. However, events can also be manually dispatched using the `ctx.sendEvent(event)` method within a workflow.
|
||||
|
||||
## Examples
|
||||
|
||||
You can find many useful examples of using workflows in the [examples folder](https://github.com/run-llama/LlamaIndexTS/blob/main/examples/workflow).
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docs",
|
||||
"version": "0.0.65",
|
||||
"version": "0.0.70",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
@@ -37,7 +37,7 @@
|
||||
"docusaurus-plugin-typedoc": "1.0.5",
|
||||
"typedoc": "0.26.6",
|
||||
"typedoc-plugin-markdown": "4.2.6",
|
||||
"typescript": "^5.5.4"
|
||||
"typescript": "^5.6.2"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# examples
|
||||
|
||||
## 0.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 11feef8: Add workflows
|
||||
- Updated dependencies [11feef8]
|
||||
- @llamaindex/core@0.2.0
|
||||
- llamaindex@0.6.0
|
||||
|
||||
## 0.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
+12
-1
@@ -1,12 +1,23 @@
|
||||
import fs from "node:fs/promises";
|
||||
|
||||
import { Document, Groq, Settings, VectorStoreIndex } from "llamaindex";
|
||||
import {
|
||||
Document,
|
||||
Groq,
|
||||
HuggingFaceEmbedding,
|
||||
Settings,
|
||||
VectorStoreIndex,
|
||||
} from "llamaindex";
|
||||
|
||||
// Update llm to use Groq
|
||||
Settings.llm = new Groq({
|
||||
apiKey: process.env.GROQ_API_KEY,
|
||||
});
|
||||
|
||||
// Use HuggingFace for embeddings
|
||||
Settings.embedModel = new HuggingFaceEmbedding({
|
||||
modelType: "Xenova/all-mpnet-base-v2",
|
||||
});
|
||||
|
||||
async function main() {
|
||||
// Load essay from abramov.txt in Node
|
||||
const path = "node_modules/llamaindex/examples/abramov.txt";
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { OpenAI } from "llamaindex";
|
||||
|
||||
(async () => {
|
||||
const llm = new OpenAI({ model: "o1-preview", temperature: 1 });
|
||||
|
||||
const prompt = `What are three compounds we should consider investigating to advance research
|
||||
into new antibiotics? Why should we consider them?
|
||||
`;
|
||||
|
||||
// complete api
|
||||
const response = await llm.complete({ prompt });
|
||||
console.log(response.text);
|
||||
})();
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@llamaindex/examples",
|
||||
"private": true,
|
||||
"version": "0.0.7",
|
||||
"version": "0.0.8",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-js": "^5.2.0",
|
||||
"@azure/identity": "^4.4.1",
|
||||
"@datastax/astra-db-ts": "^1.4.1",
|
||||
"@llamaindex/core": "^0.1.0",
|
||||
"@llamaindex/core": "^0.2.0",
|
||||
"@notionhq/client": "^2.2.15",
|
||||
"@pinecone-database/pinecone": "^3.0.2",
|
||||
"@zilliz/milvus2-sdk-node": "^2.4.6",
|
||||
@@ -14,14 +14,14 @@
|
||||
"commander": "^12.1.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"js-tiktoken": "^1.0.14",
|
||||
"llamaindex": "^0.5.0",
|
||||
"llamaindex": "^0.6.0",
|
||||
"mongodb": "^6.7.0",
|
||||
"pathe": "^1.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.5.1",
|
||||
"tsx": "^4.19.0",
|
||||
"typescript": "^5.5.4"
|
||||
"typescript": "^5.6.2"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint ."
|
||||
|
||||
@@ -23,6 +23,6 @@
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.5.1",
|
||||
"tsx": "^4.19.0",
|
||||
"typescript": "^5.5.4"
|
||||
"typescript": "^5.6.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Workflow Examples
|
||||
|
||||
These examples demonstrate LlamaIndexTS's workflow system. Check out [its documentation](https://ts.llamaindex.ai/modules/workflows) for more information.
|
||||
|
||||
## Running the Examples
|
||||
|
||||
To run the examples, make sure to run them from the parent folder called `examples`). For example, to run the joke workflow, run `npx tsx workflow/joke.ts`.
|
||||
@@ -0,0 +1,122 @@
|
||||
import {
|
||||
Context,
|
||||
StartEvent,
|
||||
StopEvent,
|
||||
Workflow,
|
||||
WorkflowEvent,
|
||||
} from "@llamaindex/core/workflow";
|
||||
import { OpenAI } from "llamaindex";
|
||||
|
||||
const MAX_REVIEWS = 3;
|
||||
|
||||
// Using the o1-preview model (see https://platform.openai.com/docs/guides/reasoning?reasoning-prompt-examples=coding-planning)
|
||||
const llm = new OpenAI({ model: "o1-preview", temperature: 1 });
|
||||
|
||||
// example specification from https://platform.openai.com/docs/guides/reasoning?reasoning-prompt-examples=coding-planning
|
||||
const specification = `Python app that takes user questions and looks them up in a
|
||||
database where they are mapped to answers. If there is a close match, it retrieves
|
||||
the matched answer. If there isn't, it asks the user to provide an answer and
|
||||
stores the question/answer pair in the database.`;
|
||||
|
||||
// Create custom event types
|
||||
export class MessageEvent extends WorkflowEvent<{ msg: string }> {}
|
||||
export class CodeEvent extends WorkflowEvent<{ code: string }> {}
|
||||
export class ReviewEvent extends WorkflowEvent<{
|
||||
review: string;
|
||||
code: string;
|
||||
}> {}
|
||||
|
||||
// Helper function to truncate long strings
|
||||
const truncate = (str: string) => {
|
||||
const MAX_LENGTH = 60;
|
||||
if (str.length <= MAX_LENGTH) return str;
|
||||
return str.slice(0, MAX_LENGTH) + "...";
|
||||
};
|
||||
|
||||
// the architect is responsible for writing the structure and the initial code based on the specification
|
||||
const architect = async (context: Context, ev: StartEvent) => {
|
||||
// get the specification from the start event and save it to context
|
||||
context.set("specification", ev.data.input);
|
||||
const spec = context.get("specification");
|
||||
// write a message to send an update to the user
|
||||
context.writeEventToStream(
|
||||
new MessageEvent({
|
||||
msg: `Writing app using this specification: ${truncate(spec)}`,
|
||||
}),
|
||||
);
|
||||
const prompt = `Build an app for this specification: <spec>${spec}</spec>. Make a plan for the directory structure you'll need, then return each file in full. Don't supply any reasoning, just code.`;
|
||||
const code = await llm.complete({ prompt });
|
||||
return new CodeEvent({ code: code.text });
|
||||
};
|
||||
|
||||
// the coder is responsible for updating the code based on the review
|
||||
const coder = async (context: Context, ev: ReviewEvent) => {
|
||||
// get the specification from the context
|
||||
const spec = context.get("specification");
|
||||
// get the latest review and code
|
||||
const { review, code } = ev.data;
|
||||
// write a message to send an update to the user
|
||||
context.writeEventToStream(
|
||||
new MessageEvent({
|
||||
msg: `Update code based on review: ${truncate(review)}`,
|
||||
}),
|
||||
);
|
||||
const prompt = `We need to improve code that should implement this specification: <spec>${spec}</spec>. Here is the current code: <code>${code}</code>. And here is a review of the code: <review>${review}</review>. Improve the code based on the review, keep the specification in mind, and return the full updated code. Don't supply any reasoning, just code.`;
|
||||
const updatedCode = await llm.complete({ prompt });
|
||||
return new CodeEvent({ code: updatedCode.text });
|
||||
};
|
||||
|
||||
// the reviewer is responsible for reviewing the code and providing feedback
|
||||
const reviewer = async (context: Context, ev: CodeEvent) => {
|
||||
// get the specification from the context
|
||||
const spec = context.get("specification");
|
||||
// get latest code from the event
|
||||
const { code } = ev.data;
|
||||
// update and check the number of reviews
|
||||
const numberReviews = context.get("numberReviews", 0) + 1;
|
||||
context.set("numberReviews", numberReviews);
|
||||
if (numberReviews > MAX_REVIEWS) {
|
||||
// the we've done this too many times - return the code
|
||||
context.writeEventToStream(
|
||||
new MessageEvent({
|
||||
msg: `Already reviewed ${numberReviews - 1} times, stopping!`,
|
||||
}),
|
||||
);
|
||||
return new StopEvent({ result: code });
|
||||
}
|
||||
// write a message to send an update to the user
|
||||
context.writeEventToStream(
|
||||
new MessageEvent({ msg: `Review #${numberReviews}: ${truncate(code)}` }),
|
||||
);
|
||||
const prompt = `Review this code: <code>${code}</code>. Check if the code quality and whether it correctly implements this specification: <spec>${spec}</spec>. If you're satisfied, just return 'Looks great', nothing else. If not, return a review with a list of changes you'd like to see.`;
|
||||
const review = (await llm.complete({ prompt })).text;
|
||||
if (review.includes("Looks great")) {
|
||||
// the reviewer is satisfied with the code, let's return the review
|
||||
context.writeEventToStream(
|
||||
new MessageEvent({
|
||||
msg: `Reviewer says: ${review}`,
|
||||
}),
|
||||
);
|
||||
return new StopEvent({ result: code });
|
||||
}
|
||||
|
||||
return new ReviewEvent({ review, code });
|
||||
};
|
||||
|
||||
const codeAgent = new Workflow({ validate: true });
|
||||
codeAgent.addStep(StartEvent, architect, { outputs: CodeEvent });
|
||||
codeAgent.addStep(ReviewEvent, coder, { outputs: CodeEvent });
|
||||
codeAgent.addStep(CodeEvent, reviewer, { outputs: ReviewEvent });
|
||||
|
||||
// Usage
|
||||
async function main() {
|
||||
const run = codeAgent.run(specification);
|
||||
for await (const event of codeAgent.streamEvents()) {
|
||||
const msg = (event as MessageEvent).data.msg;
|
||||
console.log(`${msg}\n`);
|
||||
}
|
||||
const result = await run;
|
||||
console.log("Final code:\n", result.data.result);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,70 @@
|
||||
import {
|
||||
Context,
|
||||
StartEvent,
|
||||
StopEvent,
|
||||
Workflow,
|
||||
WorkflowEvent,
|
||||
} from "@llamaindex/core/workflow";
|
||||
import { OpenAI } from "llamaindex";
|
||||
|
||||
// Create LLM instance
|
||||
const llm = new OpenAI();
|
||||
|
||||
// Create custom event types
|
||||
export class JokeEvent extends WorkflowEvent<{ joke: string }> {}
|
||||
export class CritiqueEvent extends WorkflowEvent<{ critique: string }> {}
|
||||
export class AnalysisEvent extends WorkflowEvent<{ analysis: string }> {}
|
||||
|
||||
const generateJoke = async (_context: Context, ev: StartEvent) => {
|
||||
const prompt = `Write your best joke about ${ev.data.input}.`;
|
||||
const response = await llm.complete({ prompt });
|
||||
return new JokeEvent({ joke: response.text });
|
||||
};
|
||||
|
||||
const critiqueJoke = async (_context: Context, ev: JokeEvent) => {
|
||||
const prompt = `Give a thorough critique of the following joke: ${ev.data.joke}`;
|
||||
const response = await llm.complete({ prompt });
|
||||
return new CritiqueEvent({ critique: response.text });
|
||||
};
|
||||
|
||||
const analyzeJoke = async (_context: Context, ev: JokeEvent) => {
|
||||
const prompt = `Give a thorough analysis of the following joke: ${ev.data.joke}`;
|
||||
const response = await llm.complete({ prompt });
|
||||
return new AnalysisEvent({ analysis: response.text });
|
||||
};
|
||||
|
||||
const reportJoke = async (
|
||||
context: Context,
|
||||
ev: AnalysisEvent | CritiqueEvent,
|
||||
) => {
|
||||
const events = context.collectEvents(ev, [AnalysisEvent, CritiqueEvent]);
|
||||
if (!events) {
|
||||
return;
|
||||
}
|
||||
const subPrompts = events.map((event) => {
|
||||
if (event instanceof AnalysisEvent) {
|
||||
return `Analysis: ${event.data.analysis}`;
|
||||
} else if (event instanceof CritiqueEvent) {
|
||||
return `Critique: ${event.data.critique}`;
|
||||
}
|
||||
return "";
|
||||
});
|
||||
|
||||
const prompt = `Based on the following information about a joke:\n${subPrompts.join("\n")}\nProvide a comprehensive report on the joke's quality and impact.`;
|
||||
const response = await llm.complete({ prompt });
|
||||
return new StopEvent({ result: response.text });
|
||||
};
|
||||
|
||||
const jokeFlow = new Workflow();
|
||||
jokeFlow.addStep(StartEvent, generateJoke);
|
||||
jokeFlow.addStep(JokeEvent, critiqueJoke);
|
||||
jokeFlow.addStep(JokeEvent, analyzeJoke);
|
||||
jokeFlow.addStep([AnalysisEvent, CritiqueEvent], reportJoke);
|
||||
|
||||
// Usage
|
||||
async function main() {
|
||||
const result = await jokeFlow.run("pirates");
|
||||
console.log(result.data.result);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,38 @@
|
||||
import {
|
||||
Context,
|
||||
StartEvent,
|
||||
StopEvent,
|
||||
Workflow,
|
||||
WorkflowEvent,
|
||||
} from "@llamaindex/core/workflow";
|
||||
import { OpenAI } from "llamaindex";
|
||||
|
||||
// Create LLM instance
|
||||
const llm = new OpenAI();
|
||||
|
||||
// Create a custom event type
|
||||
export class JokeEvent extends WorkflowEvent<{ joke: string }> {}
|
||||
|
||||
const generateJoke = async (_context: Context, ev: StartEvent) => {
|
||||
const prompt = `Write your best joke about ${ev.data.input}.`;
|
||||
const response = await llm.complete({ prompt });
|
||||
return new JokeEvent({ joke: response.text });
|
||||
};
|
||||
|
||||
const critiqueJoke = async (_context: Context, ev: JokeEvent) => {
|
||||
const prompt = `Give a thorough critique of the following joke: ${ev.data.joke}`;
|
||||
const response = await llm.complete({ prompt });
|
||||
return new StopEvent({ result: response.text });
|
||||
};
|
||||
|
||||
const jokeFlow = new Workflow({ verbose: true });
|
||||
jokeFlow.addStep(StartEvent, generateJoke);
|
||||
jokeFlow.addStep(JokeEvent, critiqueJoke);
|
||||
|
||||
// Usage
|
||||
async function main() {
|
||||
const result = await jokeFlow.run("pirates");
|
||||
console.log(result.data.result);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,49 @@
|
||||
import {
|
||||
Context,
|
||||
StartEvent,
|
||||
StopEvent,
|
||||
Workflow,
|
||||
WorkflowEvent,
|
||||
} from "@llamaindex/core/workflow";
|
||||
import { OpenAI } from "llamaindex";
|
||||
|
||||
// Create LLM instance
|
||||
const llm = new OpenAI();
|
||||
|
||||
// Create custom event types
|
||||
export class JokeEvent extends WorkflowEvent<{ joke: string }> {}
|
||||
export class MessageEvent extends WorkflowEvent<{ msg: string }> {}
|
||||
|
||||
const generateJoke = async (context: Context, ev: StartEvent) => {
|
||||
context.writeEventToStream(
|
||||
new MessageEvent({ msg: `Generating a joke about: ${ev.data.input}` }),
|
||||
);
|
||||
const prompt = `Write your best joke about ${ev.data.input}.`;
|
||||
const response = await llm.complete({ prompt });
|
||||
return new JokeEvent({ joke: response.text });
|
||||
};
|
||||
|
||||
const critiqueJoke = async (context: Context, ev: JokeEvent) => {
|
||||
context.writeEventToStream(
|
||||
new MessageEvent({ msg: `Write a critique of this joke: ${ev.data.joke}` }),
|
||||
);
|
||||
const prompt = `Give a thorough critique of the following joke: ${ev.data.joke}`;
|
||||
const response = await llm.complete({ prompt });
|
||||
return new StopEvent({ result: response.text });
|
||||
};
|
||||
|
||||
const jokeFlow = new Workflow();
|
||||
jokeFlow.addStep(StartEvent, generateJoke);
|
||||
jokeFlow.addStep(JokeEvent, critiqueJoke);
|
||||
|
||||
// Usage
|
||||
async function main() {
|
||||
const run = jokeFlow.run("pirates");
|
||||
for await (const event of jokeFlow.streamEvents()) {
|
||||
console.log((event as MessageEvent).data.msg);
|
||||
}
|
||||
const result = await run;
|
||||
console.log(result.data.result);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,37 @@
|
||||
import {
|
||||
Context,
|
||||
StartEvent,
|
||||
StopEvent,
|
||||
Workflow,
|
||||
} from "@llamaindex/core/workflow";
|
||||
|
||||
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" });
|
||||
};
|
||||
|
||||
async function timeout() {
|
||||
const workflow = new Workflow({ verbose: true, timeout: 1 });
|
||||
workflow.addStep(StartEvent, longRunning);
|
||||
// This will timeout
|
||||
try {
|
||||
await workflow.run("Let's start");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function notimeout() {
|
||||
// Increase timeout to 3 seconds - no timeout
|
||||
const workflow = new Workflow({ verbose: true, timeout: 3 });
|
||||
workflow.addStep(StartEvent, longRunning);
|
||||
const result = await workflow.run("Let's start");
|
||||
console.log(result.data.result);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await timeout();
|
||||
await notimeout();
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,53 @@
|
||||
import {
|
||||
Context,
|
||||
StartEvent,
|
||||
StopEvent,
|
||||
Workflow,
|
||||
WorkflowEvent,
|
||||
} from "@llamaindex/core/workflow";
|
||||
import { OpenAI } from "llamaindex";
|
||||
|
||||
// Create LLM instance
|
||||
const llm = new OpenAI();
|
||||
|
||||
// Create a custom event type
|
||||
export class JokeEvent extends WorkflowEvent<{ joke: string }> {}
|
||||
|
||||
const generateJoke = async (_context: Context, ev: StartEvent) => {
|
||||
const prompt = `Write your best joke about ${ev.data.input}.`;
|
||||
const response = await llm.complete({ prompt });
|
||||
return new JokeEvent({ joke: response.text });
|
||||
};
|
||||
|
||||
const critiqueJoke = async (_context: Context, ev: JokeEvent) => {
|
||||
const prompt = `Give a thorough critique of the following joke: ${ev.data.joke}`;
|
||||
const response = await llm.complete({ prompt });
|
||||
return new StopEvent({ result: response.text });
|
||||
};
|
||||
|
||||
async function validateFails() {
|
||||
try {
|
||||
const jokeFlow = new Workflow({ verbose: true, validate: true });
|
||||
jokeFlow.addStep(StartEvent, generateJoke, { outputs: StopEvent });
|
||||
jokeFlow.addStep(JokeEvent, critiqueJoke, { outputs: StopEvent });
|
||||
await jokeFlow.run("pirates");
|
||||
} catch (e) {
|
||||
console.error("Validation failed:", e);
|
||||
}
|
||||
}
|
||||
|
||||
async function validate() {
|
||||
const jokeFlow = new Workflow({ verbose: true, validate: true });
|
||||
jokeFlow.addStep(StartEvent, generateJoke, { outputs: JokeEvent });
|
||||
jokeFlow.addStep(JokeEvent, critiqueJoke, { outputs: StopEvent });
|
||||
const result = await jokeFlow.run("pirates");
|
||||
console.log(result.data.result);
|
||||
}
|
||||
|
||||
// Usage
|
||||
async function main() {
|
||||
await validateFails();
|
||||
await validate();
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
+4
-4
@@ -2,9 +2,9 @@
|
||||
"name": "@llamaindex/monorepo",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "turbo run build --filter=\"!docs\" --filter=\"!*-test\" --filter=\"!*-example\"",
|
||||
"build:release": "turbo run build lint test --filter=\"!docs\" --filter=\"!*-test\" --filter=\"!*-example\"",
|
||||
"dev": "turbo run dev",
|
||||
"build": "turbo run build",
|
||||
"build:release": "turbo run build --filter=\"./packages/*\"",
|
||||
"dev": "turbo run dev --filter=\"./packages/*\"",
|
||||
"format": "prettier --ignore-unknown --cache --check .",
|
||||
"format:write": "prettier --ignore-unknown --write .",
|
||||
"lint": "turbo run lint",
|
||||
@@ -31,7 +31,7 @@
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-organize-imports": "^4.0.0",
|
||||
"turbo": "^2.1.0",
|
||||
"typescript": "^5.5.4"
|
||||
"typescript": "^5.6.2"
|
||||
},
|
||||
"packageManager": "pnpm@9.5.0",
|
||||
"pnpm": {
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# @llamaindex/autotool
|
||||
|
||||
## 3.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1a6137b: feat: experimental support for browser
|
||||
|
||||
If you see bundler issue in next.js edge runtime, please bump to `next@14` latest version.
|
||||
|
||||
- Updated dependencies [fbd5e01]
|
||||
- Updated dependencies [6b70c54]
|
||||
- Updated dependencies [1a6137b]
|
||||
- Updated dependencies [85c2e19]
|
||||
- llamaindex@0.6.1
|
||||
|
||||
## 3.0.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [11feef8]
|
||||
- llamaindex@0.6.0
|
||||
|
||||
## 2.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,5 +1,50 @@
|
||||
# @llamaindex/autotool-01-node-example
|
||||
|
||||
## 0.0.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [fbd5e01]
|
||||
- Updated dependencies [6b70c54]
|
||||
- Updated dependencies [1a6137b]
|
||||
- Updated dependencies [85c2e19]
|
||||
- llamaindex@0.6.1
|
||||
- @llamaindex/autotool@3.0.1
|
||||
|
||||
## 0.0.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [11feef8]
|
||||
- llamaindex@0.6.0
|
||||
- @llamaindex/autotool@3.0.0
|
||||
|
||||
## 0.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [7edeb1c]
|
||||
- llamaindex@0.5.27
|
||||
- @llamaindex/autotool@2.0.1
|
||||
|
||||
## 0.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ffe0cd1]
|
||||
- Updated dependencies [ffe0cd1]
|
||||
- llamaindex@0.5.26
|
||||
- @llamaindex/autotool@2.0.1
|
||||
|
||||
## 0.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [4810364]
|
||||
- Updated dependencies [d3bc663]
|
||||
- llamaindex@0.5.25
|
||||
- @llamaindex/autotool@2.0.1
|
||||
|
||||
## 0.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -13,5 +13,5 @@
|
||||
"scripts": {
|
||||
"start": "node --import tsx --import @llamaindex/autotool/node ./src/index.ts"
|
||||
},
|
||||
"version": "0.0.5"
|
||||
"version": "0.0.10"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,50 @@
|
||||
# @llamaindex/autotool-02-next-example
|
||||
|
||||
## 0.1.54
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [fbd5e01]
|
||||
- Updated dependencies [6b70c54]
|
||||
- Updated dependencies [1a6137b]
|
||||
- Updated dependencies [85c2e19]
|
||||
- llamaindex@0.6.1
|
||||
- @llamaindex/autotool@3.0.1
|
||||
|
||||
## 0.1.53
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [11feef8]
|
||||
- llamaindex@0.6.0
|
||||
- @llamaindex/autotool@3.0.0
|
||||
|
||||
## 0.1.52
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [7edeb1c]
|
||||
- llamaindex@0.5.27
|
||||
- @llamaindex/autotool@2.0.1
|
||||
|
||||
## 0.1.51
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ffe0cd1]
|
||||
- Updated dependencies [ffe0cd1]
|
||||
- llamaindex@0.5.26
|
||||
- @llamaindex/autotool@2.0.1
|
||||
|
||||
## 0.1.50
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [4810364]
|
||||
- Updated dependencies [d3bc663]
|
||||
- llamaindex@0.5.25
|
||||
- @llamaindex/autotool@2.0.1
|
||||
|
||||
## 0.1.49
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -5,9 +5,9 @@ import { runWithStreamableUI } from "@/context";
|
||||
import "@/tool";
|
||||
import { convertTools } from "@llamaindex/autotool";
|
||||
import { createStreamableUI } from "ai/rsc";
|
||||
import type { JSX } from "react";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
export async function chatWithAI(message: string): Promise<JSX.Element> {
|
||||
export async function chatWithAI(message: string): Promise<ReactNode> {
|
||||
const agent = new OpenAIAgent({
|
||||
tools: convertTools("llamaindex"),
|
||||
});
|
||||
@@ -25,7 +25,7 @@ export async function chatWithAI(message: string): Promise<JSX.Element> {
|
||||
uiStream.append("\n");
|
||||
},
|
||||
write: async (message) => {
|
||||
uiStream.append(message.response.delta);
|
||||
uiStream.append(message.response);
|
||||
},
|
||||
close: () => {
|
||||
uiStream.done();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/autotool-02-next-example",
|
||||
"private": true,
|
||||
"version": "0.1.49",
|
||||
"version": "0.1.54",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
@@ -32,6 +32,6 @@
|
||||
"cross-env": "^7.0.3",
|
||||
"postcss": "^8.4.41",
|
||||
"tailwindcss": "^3.4.10",
|
||||
"typescript": "^5.5.4"
|
||||
"typescript": "^5.6.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/autotool",
|
||||
"type": "module",
|
||||
"version": "2.0.1",
|
||||
"version": "3.0.1",
|
||||
"description": "auto transpile your JS function to LLM Agent compatible",
|
||||
"files": [
|
||||
"dist",
|
||||
@@ -51,7 +51,7 @@
|
||||
"unplugin": "^1.12.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"llamaindex": "^0.5.24",
|
||||
"llamaindex": "workspace:*",
|
||||
"openai": "^4",
|
||||
"typescript": "^4"
|
||||
},
|
||||
@@ -72,10 +72,10 @@
|
||||
"@types/node": "^22.5.1",
|
||||
"bunchee": "5.3.2",
|
||||
"llamaindex": "workspace:*",
|
||||
"next": "14.2.7",
|
||||
"next": "14.2.11",
|
||||
"rollup": "^4.21.2",
|
||||
"tsx": "^4.19.0",
|
||||
"typescript": "^5.5.4",
|
||||
"typescript": "^5.6.2",
|
||||
"vitest": "^2.0.5",
|
||||
"webpack": "^5.94.0"
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import td from "typedoc";
|
||||
import type { SourceMapCompact } from "unplugin";
|
||||
import type { InfoString } from "./internal";
|
||||
|
||||
export const isToolFile = (url: string) => /tool\.[jt]sx?$/.test(url);
|
||||
export const isToolFile = (url: string) => /\.tool\.[jt]sx?$/.test(url);
|
||||
export const isJSorTS = (url: string) => /\.m?[jt]sx?$/.test(url);
|
||||
|
||||
async function parseRoot(entryPoint: string) {
|
||||
@@ -28,7 +28,7 @@ async function parseRoot(entryPoint: string) {
|
||||
if (project) {
|
||||
return app.serializer.projectToObject(project, process.cwd());
|
||||
}
|
||||
throw new Error("Failed to parse root");
|
||||
throw new Error(`Failed to parse root ${entryPoint}`);
|
||||
}
|
||||
|
||||
export async function transformAutoTool(
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
# @llamaindex/cloud
|
||||
|
||||
## 0.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 85c2e19: feat: `@llamaindex/cloud` package update
|
||||
|
||||
- Bump to latest openapi schema
|
||||
- Move LlamaParse class from llamaindex, this will allow you use llamaparse in more non-node.js environment
|
||||
|
||||
- Updated dependencies [ac07e3c]
|
||||
- Updated dependencies [70ccb4a]
|
||||
- Updated dependencies [1a6137b]
|
||||
- Updated dependencies [ac07e3c]
|
||||
- @llamaindex/core@0.2.1
|
||||
- @llamaindex/env@0.1.11
|
||||
|
||||
## 0.2.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 4810364: fix: bump version
|
||||
|
||||
## 0.2.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
+2522
-337
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/cloud",
|
||||
"version": "0.2.3",
|
||||
"version": "0.2.5",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
@@ -26,6 +26,20 @@
|
||||
"types": "./dist/api.d.ts",
|
||||
"default": "./dist/api.js"
|
||||
}
|
||||
},
|
||||
"./reader": {
|
||||
"require": {
|
||||
"types": "./dist/reader.d.cts",
|
||||
"default": "./dist/reader.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/reader.d.ts",
|
||||
"default": "./dist/reader.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./dist/reader.d.ts",
|
||||
"default": "./dist/reader.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
@@ -36,6 +50,15 @@
|
||||
"devDependencies": {
|
||||
"@hey-api/client-fetch": "^0.2.4",
|
||||
"@hey-api/openapi-ts": "^0.53.0",
|
||||
"@llamaindex/core": "workspace:^0.2.1",
|
||||
"@llamaindex/env": "workspace:^0.1.11",
|
||||
"bunchee": "5.3.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@llamaindex/core": "workspace:^0.2.1",
|
||||
"@llamaindex/env": "workspace:^0.1.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"magic-bytes.js": "^1.10.0"
|
||||
}
|
||||
}
|
||||
|
||||
+180
-202
@@ -1,92 +1,17 @@
|
||||
import { createClient, createConfig, type Client } from "@hey-api/client-fetch";
|
||||
import { Document, FileReader } from "@llamaindex/core/schema";
|
||||
import { fs, getEnv } from "@llamaindex/env";
|
||||
import { filetypeinfo } from "magic-bytes.js";
|
||||
import {
|
||||
ParsingService,
|
||||
type Body_upload_file_api_v1_parsing_upload_post,
|
||||
type ParserLanguages,
|
||||
} from "./api";
|
||||
import { sleep } from "./utils";
|
||||
|
||||
export type Language = ParserLanguages;
|
||||
|
||||
export type ResultType = "text" | "markdown" | "json";
|
||||
export type Language =
|
||||
| "abq"
|
||||
| "ady"
|
||||
| "af"
|
||||
| "ang"
|
||||
| "ar"
|
||||
| "as"
|
||||
| "ava"
|
||||
| "az"
|
||||
| "be"
|
||||
| "bg"
|
||||
| "bh"
|
||||
| "bho"
|
||||
| "bn"
|
||||
| "bs"
|
||||
| "ch_sim"
|
||||
| "ch_tra"
|
||||
| "che"
|
||||
| "cs"
|
||||
| "cy"
|
||||
| "da"
|
||||
| "dar"
|
||||
| "de"
|
||||
| "en"
|
||||
| "es"
|
||||
| "et"
|
||||
| "fa"
|
||||
| "fr"
|
||||
| "ga"
|
||||
| "gom"
|
||||
| "hi"
|
||||
| "hr"
|
||||
| "hu"
|
||||
| "id"
|
||||
| "inh"
|
||||
| "is"
|
||||
| "it"
|
||||
| "ja"
|
||||
| "kbd"
|
||||
| "kn"
|
||||
| "ko"
|
||||
| "ku"
|
||||
| "la"
|
||||
| "lbe"
|
||||
| "lez"
|
||||
| "lt"
|
||||
| "lv"
|
||||
| "mah"
|
||||
| "mai"
|
||||
| "mi"
|
||||
| "mn"
|
||||
| "mr"
|
||||
| "ms"
|
||||
| "mt"
|
||||
| "ne"
|
||||
| "new"
|
||||
| "nl"
|
||||
| "no"
|
||||
| "oc"
|
||||
| "pi"
|
||||
| "pl"
|
||||
| "pt"
|
||||
| "ro"
|
||||
| "ru"
|
||||
| "rs_cyrillic"
|
||||
| "rs_latin"
|
||||
| "sck"
|
||||
| "sk"
|
||||
| "sl"
|
||||
| "sq"
|
||||
| "sv"
|
||||
| "sw"
|
||||
| "ta"
|
||||
| "tab"
|
||||
| "te"
|
||||
| "th"
|
||||
| "tjk"
|
||||
| "tl"
|
||||
| "tr"
|
||||
| "ug"
|
||||
| "uk"
|
||||
| "ur"
|
||||
| "uz"
|
||||
| "vi";
|
||||
|
||||
const SUPPORT_FILE_EXT: string[] = [
|
||||
".pdf",
|
||||
@@ -181,6 +106,15 @@ const SUPPORT_FILE_EXT: string[] = [
|
||||
".tsv",
|
||||
];
|
||||
|
||||
//todo: should move into @llamaindex/env
|
||||
type WriteStream = {
|
||||
write: (text: string) => void;
|
||||
};
|
||||
|
||||
// Do not modify this variable or cause type errors
|
||||
// eslint-disable-next-line no-var
|
||||
var process: any;
|
||||
|
||||
/**
|
||||
* Represents a reader for parsing files using the LlamaParse API.
|
||||
* See https://github.com/run-llama/llama_parse
|
||||
@@ -188,8 +122,8 @@ const SUPPORT_FILE_EXT: string[] = [
|
||||
export class LlamaParseReader extends FileReader {
|
||||
// The API key for the LlamaParse API. Can be set as an environment variable: LLAMA_CLOUD_API_KEY
|
||||
apiKey: string;
|
||||
// The base URL of the Llama Parsing API.
|
||||
baseUrl: string = "https://api.cloud.llamaindex.ai/api/parsing";
|
||||
// The base URL of the Llama Cloud Platform.
|
||||
baseUrl: string = "https://api.cloud.llamaindex.ai";
|
||||
// The result type for the parser.
|
||||
resultType: ResultType = "text";
|
||||
// The interval in seconds to check if the parsing is done.
|
||||
@@ -199,7 +133,7 @@ export class LlamaParseReader extends FileReader {
|
||||
// Whether to print the progress of the parsing.
|
||||
verbose = true;
|
||||
// The language of the text to parse.
|
||||
language: Language = "en";
|
||||
language: ParserLanguages[] = ["en"];
|
||||
// The parsing instruction for the parser. Backend default is an empty string.
|
||||
parsingInstruction?: string | undefined;
|
||||
// Wether to ignore diagonal text (when the text rotation in degrees is not 0, 90, 180 or 270, so not a horizontal or vertical text). Backend default is false.
|
||||
@@ -237,21 +171,38 @@ export class LlamaParseReader extends FileReader {
|
||||
// The API key for the multimodal API. Can also be set as an env variable: LLAMA_CLOUD_VENDOR_MULTIMODAL_API_KEY
|
||||
vendorMultimodalApiKey?: string | undefined;
|
||||
// numWorkers is implemented in SimpleDirectoryReader
|
||||
stdout?: WriteStream | undefined;
|
||||
|
||||
readonly #client: Client;
|
||||
|
||||
constructor(
|
||||
params: Partial<LlamaParseReader> & {
|
||||
params: Partial<Omit<LlamaParseReader, "language" | "apiKey">> & {
|
||||
language?: ParserLanguages | ParserLanguages[] | undefined;
|
||||
apiKey?: string | undefined;
|
||||
} = {},
|
||||
) {
|
||||
super();
|
||||
Object.assign(this, params);
|
||||
params.apiKey = params.apiKey ?? getEnv("LLAMA_CLOUD_API_KEY");
|
||||
if (!params.apiKey) {
|
||||
this.language = Array.isArray(this.language)
|
||||
? this.language
|
||||
: [this.language];
|
||||
this.stdout =
|
||||
(params.stdout ?? typeof process !== "undefined")
|
||||
? process!.stdout
|
||||
: undefined;
|
||||
const apiKey = params.apiKey ?? getEnv("LLAMA_CLOUD_API_KEY");
|
||||
if (!apiKey) {
|
||||
throw new Error(
|
||||
"API Key is required for LlamaParseReader. Please pass the apiKey parameter or set the LLAMA_CLOUD_API_KEY environment variable.",
|
||||
);
|
||||
}
|
||||
this.apiKey = params.apiKey;
|
||||
this.apiKey = apiKey;
|
||||
if (this.baseUrl.endsWith("/")) {
|
||||
this.baseUrl = this.baseUrl.slice(0, -"/".length);
|
||||
}
|
||||
if (this.baseUrl.endsWith("/api/parsing")) {
|
||||
this.baseUrl = this.baseUrl.slice(0, -"/api/parsing".length);
|
||||
}
|
||||
|
||||
if (params.gpt4oMode) {
|
||||
params.gpt4oApiKey =
|
||||
@@ -266,12 +217,21 @@ export class LlamaParseReader extends FileReader {
|
||||
|
||||
this.vendorMultimodalApiKey = params.vendorMultimodalApiKey;
|
||||
}
|
||||
|
||||
this.#client = createClient(
|
||||
createConfig({
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.apiKey}`,
|
||||
},
|
||||
baseUrl: this.baseUrl,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// Create a job for the LlamaParse API
|
||||
private async createJob(
|
||||
data: Uint8Array,
|
||||
fileName?: string,
|
||||
fileName: string = "unknown",
|
||||
): Promise<string> {
|
||||
// Load data, set the mime type
|
||||
const { mime, extension } = await LlamaParseReader.getMimeType(data);
|
||||
@@ -281,111 +241,126 @@ export class LlamaParseReader extends FileReader {
|
||||
console.log(`Starting load for ${name} file`);
|
||||
}
|
||||
|
||||
const body = new FormData();
|
||||
body.set("file", new Blob([data], { type: mime }), fileName);
|
||||
|
||||
const LlamaParseBodyParams = {
|
||||
const body = {
|
||||
file: new File([data], fileName, { type: mime }),
|
||||
language: this.language,
|
||||
parsing_instruction: this.parsingInstruction,
|
||||
skip_diagonal_text: this.skipDiagonalText?.toString(),
|
||||
invalidate_cache: this.invalidateCache?.toString(),
|
||||
do_not_cache: this.doNotCache?.toString(),
|
||||
fast_mode: this.fastMode?.toString(),
|
||||
do_not_unroll_columns: this.doNotUnrollColumns?.toString(),
|
||||
skip_diagonal_text: this.skipDiagonalText,
|
||||
invalidate_cache: this.invalidateCache,
|
||||
do_not_cache: this.doNotCache,
|
||||
fast_mode: this.fastMode,
|
||||
do_not_unroll_columns: this.doNotUnrollColumns,
|
||||
page_separator: this.pageSeparator,
|
||||
page_prefix: this.pagePrefix,
|
||||
page_suffix: this.pageSuffix,
|
||||
gpt4o_mode: this.gpt4oMode?.toString(),
|
||||
gpt4o_mode: this.gpt4oMode,
|
||||
gpt4o_api_key: this.gpt4oApiKey,
|
||||
bounding_box: this.boundingBox,
|
||||
target_pages: this.targetPages,
|
||||
use_vendor_multimodal_model: this.useVendorMultimodalModel?.toString(),
|
||||
use_vendor_multimodal_model: this.useVendorMultimodalModel,
|
||||
vendor_multimodal_model_name: this.vendorMultimodalModelName,
|
||||
vendor_multimodal_api_key: this.vendorMultimodalApiKey,
|
||||
};
|
||||
// fixme: does these fields need to be set?
|
||||
webhook_url: undefined,
|
||||
take_screenshot: undefined,
|
||||
disable_ocr: undefined,
|
||||
disable_reconstruction: undefined,
|
||||
input_s3_path: undefined,
|
||||
output_s3_path_prefix: undefined,
|
||||
} satisfies {
|
||||
[Key in keyof Body_upload_file_api_v1_parsing_upload_post]-?:
|
||||
| Body_upload_file_api_v1_parsing_upload_post[Key]
|
||||
| undefined;
|
||||
} as unknown as Body_upload_file_api_v1_parsing_upload_post;
|
||||
|
||||
// Filter out params with invalid values that would cause issues on the backend.
|
||||
const filteredParams = this.filterSpecificParams(LlamaParseBodyParams, [
|
||||
"page_separator",
|
||||
"page_prefix",
|
||||
"page_suffix",
|
||||
"bounding_box",
|
||||
"target_pages",
|
||||
]);
|
||||
|
||||
// Appends body with any defined LlamaParseBodyParams
|
||||
Object.entries(filteredParams).forEach(([key, value]) => {
|
||||
if (value !== undefined) {
|
||||
body.append(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
const headers = {
|
||||
Authorization: `Bearer ${this.apiKey}`,
|
||||
};
|
||||
|
||||
// Send the request, start job
|
||||
const url = `${this.baseUrl}/upload`;
|
||||
const response = await fetch(url, {
|
||||
const response = await ParsingService.uploadFileApiV1ParsingUploadPost({
|
||||
client: this.#client,
|
||||
throwOnError: true,
|
||||
signal: AbortSignal.timeout(this.maxTimeout * 1000),
|
||||
method: "POST",
|
||||
body,
|
||||
headers,
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to parse the file: ${await response.text()}`);
|
||||
}
|
||||
const jsonResponse = await response.json();
|
||||
return jsonResponse.id;
|
||||
|
||||
return response.data.id;
|
||||
}
|
||||
|
||||
// Get the result of the job
|
||||
private async getJobResult(jobId: string, resultType: string): Promise<any> {
|
||||
const resultUrl = `${this.baseUrl}/job/${jobId}/result/${resultType}`;
|
||||
const statusUrl = `${this.baseUrl}/job/${jobId}`;
|
||||
const headers = { Authorization: `Bearer ${this.apiKey}` };
|
||||
|
||||
private async getJobResult(
|
||||
jobId: string,
|
||||
resultType: "text" | "json" | "markdown",
|
||||
): Promise<any> {
|
||||
const signal = AbortSignal.timeout(this.maxTimeout * 1000);
|
||||
let tries = 0;
|
||||
while (true) {
|
||||
await new Promise((resolve) =>
|
||||
setTimeout(resolve, this.checkInterval * 1000),
|
||||
);
|
||||
await sleep(this.checkInterval * 1000);
|
||||
|
||||
// Check the job status. If unsuccessful response, checks if maximum timeout has been reached. If reached, throws an error
|
||||
const statusResponse = await fetch(statusUrl, {
|
||||
headers,
|
||||
signal,
|
||||
});
|
||||
if (!statusResponse.ok) {
|
||||
signal.throwIfAborted();
|
||||
if (this.verbose && tries % 10 === 0) {
|
||||
process.stdout.write(".");
|
||||
}
|
||||
tries++;
|
||||
continue;
|
||||
}
|
||||
const result =
|
||||
await ParsingService.getParsingJobDetailsApiV1ParsingJobJobIdDetailsGet(
|
||||
{
|
||||
client: this.#client,
|
||||
throwOnError: true,
|
||||
path: {
|
||||
job_id: jobId,
|
||||
},
|
||||
signal,
|
||||
},
|
||||
);
|
||||
const { data } = result;
|
||||
|
||||
// If response is succesful, check status of job. Allowed values "PENDING", "SUCCESS", "ERROR", "CANCELED"
|
||||
const statusJson = await statusResponse.json();
|
||||
const status = statusJson.status;
|
||||
const status = (data as Record<string, unknown>)["status"];
|
||||
// If job has completed, return the result
|
||||
if (status === "SUCCESS") {
|
||||
const resultResponse = await fetch(resultUrl, {
|
||||
headers,
|
||||
signal,
|
||||
});
|
||||
if (!resultResponse.ok) {
|
||||
throw new Error(
|
||||
`Failed to fetch result: ${await resultResponse.text()}`,
|
||||
);
|
||||
let result;
|
||||
switch (resultType) {
|
||||
case "json": {
|
||||
result =
|
||||
await ParsingService.getJobJsonResultApiV1ParsingJobJobIdResultJsonGet(
|
||||
{
|
||||
client: this.#client,
|
||||
throwOnError: true,
|
||||
path: {
|
||||
job_id: jobId,
|
||||
},
|
||||
signal,
|
||||
},
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "markdown": {
|
||||
result =
|
||||
await ParsingService.getJobResultApiV1ParsingJobJobIdResultMarkdownGet(
|
||||
{
|
||||
client: this.#client,
|
||||
throwOnError: true,
|
||||
path: {
|
||||
job_id: jobId,
|
||||
},
|
||||
signal,
|
||||
},
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "text": {
|
||||
result =
|
||||
await ParsingService.getJobTextResultApiV1ParsingJobJobIdResultTextGet(
|
||||
{
|
||||
client: this.#client,
|
||||
throwOnError: true,
|
||||
path: {
|
||||
job_id: jobId,
|
||||
},
|
||||
signal,
|
||||
},
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return resultResponse.json();
|
||||
return result.data;
|
||||
// If job is still pending, check if maximum timeout has been reached. If reached, throws an error
|
||||
} else if (status === "PENDING") {
|
||||
signal.throwIfAborted();
|
||||
if (this.verbose && tries % 10 === 0) {
|
||||
process.stdout.write(".");
|
||||
this.stdout?.write(".");
|
||||
}
|
||||
tries++;
|
||||
} else {
|
||||
@@ -408,36 +383,34 @@ export class LlamaParseReader extends FileReader {
|
||||
fileContent: Uint8Array,
|
||||
fileName?: string,
|
||||
): Promise<Document[]> {
|
||||
let jobId;
|
||||
try {
|
||||
// Creates a job for the file
|
||||
jobId = await this.createJob(fileContent, fileName);
|
||||
if (this.verbose) {
|
||||
console.log(`Started parsing the file under job id ${jobId}`);
|
||||
}
|
||||
return this.createJob(fileContent, fileName)
|
||||
.then(async (jobId) => {
|
||||
if (this.verbose) {
|
||||
console.log(`Started parsing the file under job id ${jobId}`);
|
||||
}
|
||||
|
||||
// Return results as Document objects
|
||||
const jobResults = await this.getJobResult(jobId, this.resultType);
|
||||
const resultText = jobResults[this.resultType];
|
||||
// Return results as Document objects
|
||||
const jobResults = await this.getJobResult(jobId, this.resultType);
|
||||
const resultText = jobResults[this.resultType];
|
||||
|
||||
// Split the text by separator if splitByPage is true
|
||||
if (this.splitByPage) {
|
||||
return this.splitTextBySeparator(resultText);
|
||||
}
|
||||
// Split the text by separator if splitByPage is true
|
||||
if (this.splitByPage) {
|
||||
return this.splitTextBySeparator(resultText);
|
||||
}
|
||||
|
||||
return [
|
||||
new Document({
|
||||
text: resultText,
|
||||
}),
|
||||
];
|
||||
} catch (e) {
|
||||
console.error(`Error while parsing file under job id ${jobId}`, e);
|
||||
if (this.ignoreErrors) {
|
||||
return [];
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return [
|
||||
new Document({
|
||||
text: resultText,
|
||||
}),
|
||||
];
|
||||
})
|
||||
.catch((error) => {
|
||||
if (this.ignoreErrors) {
|
||||
return [];
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Loads data from a file and returns an array of JSON objects.
|
||||
@@ -551,15 +524,20 @@ export class LlamaParseReader extends FileReader {
|
||||
imagePath: string,
|
||||
jobId: string,
|
||||
): Promise<void> {
|
||||
const headers = { Authorization: `Bearer ${this.apiKey}` };
|
||||
// Construct the image URL
|
||||
const imageUrl = `${this.baseUrl}/job/${jobId}/result/image/${imageName}`;
|
||||
const response = await fetch(imageUrl, { headers });
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to download image: ${await response.text()}`);
|
||||
const response =
|
||||
await ParsingService.getJobImageResultApiV1ParsingJobJobIdResultImageNameGet(
|
||||
{
|
||||
client: this.#client,
|
||||
path: {
|
||||
job_id: jobId,
|
||||
name: imageName,
|
||||
},
|
||||
},
|
||||
);
|
||||
if (response.error) {
|
||||
throw new Error(`Failed to download image: ${response.error.detail}`);
|
||||
}
|
||||
// Convert the response to an ArrayBuffer and then to a Buffer
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
const arrayBuffer = (await response.data) as ArrayBuffer;
|
||||
const buffer = new Uint8Array(arrayBuffer);
|
||||
// Write the image buffer to the specified imagePath
|
||||
await fs.writeFile(imagePath, buffer);
|
||||
@@ -0,0 +1,3 @@
|
||||
export async function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
@@ -8,8 +8,17 @@
|
||||
"moduleResolution": "Bundler",
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"lib": ["DOM", "ESNext"]
|
||||
"lib": ["DOM", "ESNext"],
|
||||
"types": []
|
||||
},
|
||||
"include": ["./src"],
|
||||
"exclude": ["node_modules"]
|
||||
"exclude": ["node_modules"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../core/tsconfig.json"
|
||||
},
|
||||
{
|
||||
"path": "../env/tsconfig.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# @llamaindex/community
|
||||
|
||||
## 0.0.35
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ac07e3c]
|
||||
- Updated dependencies [70ccb4a]
|
||||
- Updated dependencies [1a6137b]
|
||||
- Updated dependencies [ac07e3c]
|
||||
- @llamaindex/core@0.2.1
|
||||
- @llamaindex/env@0.1.11
|
||||
|
||||
## 0.0.34
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [11feef8]
|
||||
- @llamaindex/core@0.2.0
|
||||
|
||||
## 0.0.33
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/community",
|
||||
"description": "Community package for LlamaIndexTS",
|
||||
"version": "0.0.33",
|
||||
"version": "0.0.35",
|
||||
"type": "module",
|
||||
"types": "dist/type/index.d.ts",
|
||||
"main": "dist/cjs/index.js",
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# @llamaindex/core
|
||||
|
||||
## 0.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ac07e3c: fix: replace instanceof check with `.type` check
|
||||
- 70ccb4a: Allow arbitrary types in workflow's StartEvent and StopEvent
|
||||
- ac07e3c: fix: add `console.warn` when import dual module
|
||||
- Updated dependencies [ac07e3c]
|
||||
- Updated dependencies [1a6137b]
|
||||
- Updated dependencies [ac07e3c]
|
||||
- @llamaindex/env@0.1.11
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 11feef8: Add workflows
|
||||
|
||||
## 0.1.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/core",
|
||||
"type": "module",
|
||||
"version": "0.1.12",
|
||||
"version": "0.2.1",
|
||||
"description": "LlamaIndex Core Module",
|
||||
"exports": {
|
||||
"./node-parser": {
|
||||
@@ -143,6 +143,20 @@
|
||||
"types": "./dist/indices/index.d.ts",
|
||||
"default": "./dist/indices/index.js"
|
||||
}
|
||||
},
|
||||
"./workflow": {
|
||||
"require": {
|
||||
"types": "./dist/workflow/index.d.cts",
|
||||
"default": "./dist/workflow/index.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/workflow/index.d.ts",
|
||||
"default": "./dist/workflow/index.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./dist/workflow/index.d.ts",
|
||||
"default": "./dist/workflow/index.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
@@ -158,8 +172,10 @@
|
||||
"url": "https://github.com/himself65/LlamaIndexTS.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@edge-runtime/vm": "^4.0.3",
|
||||
"ajv": "^8.17.1",
|
||||
"bunchee": "5.3.2",
|
||||
"happy-dom": "^15.7.4",
|
||||
"natural": "^8.0.1",
|
||||
"python-format-js": "^1.4.3"
|
||||
},
|
||||
|
||||
@@ -437,9 +437,16 @@ export function splitNodesByType(nodes: BaseNode[]): NodesByType {
|
||||
|
||||
for (const node of nodes) {
|
||||
let type: ModalityType;
|
||||
if (node instanceof ImageNode) {
|
||||
if (
|
||||
node.type === ObjectType.IMAGE ||
|
||||
node.type === ObjectType.IMAGE_DOCUMENT
|
||||
) {
|
||||
type = ModalityType.IMAGE;
|
||||
} else if (node instanceof TextNode) {
|
||||
} else if (
|
||||
node.type === ObjectType.TEXT ||
|
||||
node.type === ObjectType.DOCUMENT ||
|
||||
node.type === ObjectType.INDEX
|
||||
) {
|
||||
type = ModalityType.TEXT;
|
||||
} else {
|
||||
throw new Error(`Unknown node type: ${node.type}`);
|
||||
@@ -465,28 +472,36 @@ export function buildNodeFromSplits(
|
||||
};
|
||||
|
||||
textSplits.forEach((textChunk, i) => {
|
||||
if (doc instanceof ImageDocument) {
|
||||
if (
|
||||
doc.type === ObjectType.IMAGE ||
|
||||
doc.type === ObjectType.IMAGE_DOCUMENT
|
||||
) {
|
||||
const imageDoc = doc as ImageNode;
|
||||
const imageNode = new ImageNode({
|
||||
id_: idGenerator(i, doc),
|
||||
id_: idGenerator(i, imageDoc),
|
||||
text: textChunk,
|
||||
image: doc.image,
|
||||
embedding: doc.embedding,
|
||||
excludedEmbedMetadataKeys: [...doc.excludedEmbedMetadataKeys],
|
||||
excludedLlmMetadataKeys: [...doc.excludedLlmMetadataKeys],
|
||||
metadataSeparator: doc.metadataSeparator,
|
||||
textTemplate: doc.textTemplate,
|
||||
image: imageDoc.image,
|
||||
embedding: imageDoc.embedding,
|
||||
excludedEmbedMetadataKeys: [...imageDoc.excludedEmbedMetadataKeys],
|
||||
excludedLlmMetadataKeys: [...imageDoc.excludedLlmMetadataKeys],
|
||||
metadataSeparator: imageDoc.metadataSeparator,
|
||||
textTemplate: imageDoc.textTemplate,
|
||||
relationships: { ...relationships },
|
||||
});
|
||||
nodes.push(imageNode);
|
||||
} else if (doc instanceof Document || doc instanceof TextNode) {
|
||||
} else if (
|
||||
doc.type === ObjectType.DOCUMENT ||
|
||||
doc.type === ObjectType.TEXT
|
||||
) {
|
||||
const textDoc = doc as TextNode;
|
||||
const node = new TextNode({
|
||||
id_: idGenerator(i, doc),
|
||||
id_: idGenerator(i, textDoc),
|
||||
text: textChunk,
|
||||
embedding: doc.embedding,
|
||||
excludedEmbedMetadataKeys: [...doc.excludedEmbedMetadataKeys],
|
||||
excludedLlmMetadataKeys: [...doc.excludedLlmMetadataKeys],
|
||||
metadataSeparator: doc.metadataSeparator,
|
||||
textTemplate: doc.textTemplate,
|
||||
embedding: textDoc.embedding,
|
||||
excludedEmbedMetadataKeys: [...textDoc.excludedEmbedMetadataKeys],
|
||||
excludedLlmMetadataKeys: [...textDoc.excludedLlmMetadataKeys],
|
||||
metadataSeparator: textDoc.metadataSeparator,
|
||||
textTemplate: textDoc.textTemplate,
|
||||
relationships: { ...relationships },
|
||||
});
|
||||
nodes.push(node);
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
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();
|
||||
#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;
|
||||
}
|
||||
|
||||
set(key: string, value: any): void {
|
||||
this.#globals.set(key, value);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
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)})`;
|
||||
}
|
||||
}
|
||||
|
||||
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 }> {}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from "./context";
|
||||
export * from "./events";
|
||||
export * from "./workflow";
|
||||
@@ -0,0 +1,221 @@
|
||||
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[];
|
||||
|
||||
export class Workflow {
|
||||
#steps: Map<
|
||||
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;
|
||||
} = {},
|
||||
) {
|
||||
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 });
|
||||
}
|
||||
|
||||
hasStep(step: StepFunction<any>): boolean {
|
||||
return this.#steps.has(step);
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { defineWorkspace } from "vitest/config";
|
||||
|
||||
export default defineWorkspace([
|
||||
{
|
||||
test: {
|
||||
environment: "edge-runtime",
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
environment: "happy-dom",
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
environment: "node",
|
||||
},
|
||||
},
|
||||
]);
|
||||
@@ -0,0 +1,169 @@
|
||||
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>;
|
||||
let generateJoke: Mocked<any>;
|
||||
let critiqueJoke: Mocked<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!",
|
||||
});
|
||||
});
|
||||
});
|
||||
Vendored
+11
@@ -1,5 +1,16 @@
|
||||
# @llamaindex/env
|
||||
|
||||
## 0.1.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ac07e3c: fix: replace instanceof check with `.type` check
|
||||
- 1a6137b: feat: experimental support for browser
|
||||
|
||||
If you see bundler issue in next.js edge runtime, please bump to `next@14` latest version.
|
||||
|
||||
- ac07e3c: fix: add `console.warn` when import dual module
|
||||
|
||||
## 0.1.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
Vendored
+5
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/env",
|
||||
"description": "environment wrapper, supports all JS environment including node, deno, bun, edge runtime, and cloudflare worker",
|
||||
"version": "0.1.10",
|
||||
"version": "0.1.11",
|
||||
"type": "module",
|
||||
"types": "dist/type/index.d.ts",
|
||||
"main": "dist/cjs/index.js",
|
||||
@@ -36,6 +36,10 @@
|
||||
"types": "./dist/type/index.edge-light.d.ts",
|
||||
"default": "./dist/index.edge-light.js"
|
||||
},
|
||||
"browser": {
|
||||
"types": "./dist/type/index.browser.d.ts",
|
||||
"default": "./dist/index.browser.js"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/type/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
|
||||
Vendored
+31
@@ -0,0 +1,31 @@
|
||||
const glo: any =
|
||||
typeof globalThis !== "undefined"
|
||||
? globalThis
|
||||
: // @ts-expect-error
|
||||
typeof window !== "undefined"
|
||||
? // @ts-expect-error
|
||||
window
|
||||
: typeof global !== "undefined"
|
||||
? global
|
||||
: {};
|
||||
|
||||
const importIdentifier = "__ $@llamaindex/env$ __";
|
||||
|
||||
if (glo[importIdentifier] === true) {
|
||||
/**
|
||||
* Dear reader of this message. Please take this seriously.
|
||||
*
|
||||
* If you see this message, make sure that you only import one version of llamaindex. In many cases,
|
||||
* your package manager installs two versions of llamaindex that are used by different packages within your project.
|
||||
* Another reason for this message is that some parts of your project use the CJS version of llamaindex
|
||||
* and others use the ESM version of llamaindex.
|
||||
*
|
||||
* This often leads to issues that are hard to debug. We often need to perform constructor checks,
|
||||
* e.g. `node instanceof TextNode`. If you imported different versions of llamaindex, it is impossible for us to
|
||||
* do the constructor checks anymore - which might break the functionality of your application.
|
||||
*/
|
||||
console.error(
|
||||
"llamaindex was already imported. This breaks constructor checks and will lead to issues!",
|
||||
);
|
||||
}
|
||||
glo[importIdentifier] = true;
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Web environment polyfill.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
import "./global-check.js";
|
||||
export * from "./web-polyfill.js";
|
||||
|
||||
export { Tokenizers, tokenizers, type Tokenizer } from "./tokenizers/js.js";
|
||||
|
||||
// @ts-expect-error
|
||||
if (typeof window === "undefined") {
|
||||
console.warn(
|
||||
"You are not in a browser environment. This module is not supposed to be used in a non-browser environment.",
|
||||
);
|
||||
}
|
||||
Vendored
+2
-1
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
export * from "./polyfill.js";
|
||||
import "./global-check.js";
|
||||
export * from "./node-polyfill.js";
|
||||
|
||||
export { Tokenizers, tokenizers, type Tokenizer } from "./tokenizers/js.js";
|
||||
|
||||
Vendored
+8
-2
@@ -18,7 +18,8 @@ import path from "node:path";
|
||||
import { Readable } from "node:stream";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { createWriteStream, fs } from "./fs/node.js";
|
||||
import type { SHA256 } from "./polyfill.js";
|
||||
import "./global-check.js";
|
||||
import type { SHA256 } from "./node-polyfill.js";
|
||||
|
||||
export function createSHA256(): SHA256 {
|
||||
const hash = createHash("sha256");
|
||||
@@ -33,7 +34,12 @@ export function createSHA256(): SHA256 {
|
||||
}
|
||||
|
||||
export { Tokenizers, tokenizers, type Tokenizer } from "./tokenizers/node.js";
|
||||
export { AsyncLocalStorage, CustomEvent, getEnv, setEnvs } from "./utils.js";
|
||||
export {
|
||||
AsyncLocalStorage,
|
||||
CustomEvent,
|
||||
getEnv,
|
||||
setEnvs,
|
||||
} from "./utils/index.js";
|
||||
export {
|
||||
createWriteStream,
|
||||
EOL,
|
||||
|
||||
Vendored
+2
-2
@@ -5,9 +5,9 @@
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
import { INTERNAL_ENV } from "./utils.js";
|
||||
import { INTERNAL_ENV } from "./utils/index.js";
|
||||
|
||||
export * from "./polyfill.js";
|
||||
export * from "./node-polyfill.js";
|
||||
|
||||
export function getEnv(name: string): string | undefined {
|
||||
return INTERNAL_ENV[name];
|
||||
|
||||
@@ -46,4 +46,9 @@ export function randomUUID(): string {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
|
||||
export { AsyncLocalStorage, CustomEvent, getEnv, setEnvs } from "./utils.js";
|
||||
export {
|
||||
AsyncLocalStorage,
|
||||
CustomEvent,
|
||||
getEnv,
|
||||
setEnvs,
|
||||
} from "./utils/index.js";
|
||||
Vendored
+45
@@ -0,0 +1,45 @@
|
||||
// DO NOT EXPOSE THIS VARIABLE TO PUBLIC, IT IS USED INTERNALLY FOR BROWSER ENVIRONMENT
|
||||
export const INTERNAL_ENV: Record<string, string> = {};
|
||||
|
||||
export function setEnvs(envs: object): void {
|
||||
Object.assign(INTERNAL_ENV, envs);
|
||||
}
|
||||
|
||||
export function getEnv(name: string): string | undefined {
|
||||
if (INTERNAL_ENV[name]) {
|
||||
return INTERNAL_ENV[name];
|
||||
}
|
||||
}
|
||||
|
||||
// Web doesn't have AsyncLocalStorage and there's no alternative way to implement it
|
||||
// Wait for https://github.com/tc39/proposal-async-context
|
||||
export class AsyncLocalStorage<T> {
|
||||
#store: T = null!;
|
||||
static bind<Func extends (...args: any[]) => any>(fn: Func): Func {
|
||||
return fn;
|
||||
}
|
||||
|
||||
static snapshot(): <R, TArgs extends any[]>(
|
||||
fn: (...args: TArgs) => R,
|
||||
...args: TArgs
|
||||
) => R {
|
||||
return (cb: any, ...args: any[]) => cb(...args);
|
||||
}
|
||||
|
||||
getStore() {
|
||||
return this.#store;
|
||||
}
|
||||
|
||||
run<R>(store: T, cb: () => R): R {
|
||||
this.#store = store;
|
||||
if (cb.constructor.name === "AsyncFunction") {
|
||||
console.warn("AsyncLocalStorage is not supported in the web environment");
|
||||
console.warn("Please note that some features may not work as expected");
|
||||
}
|
||||
return cb();
|
||||
}
|
||||
}
|
||||
|
||||
const defaultCustomEvent = (globalThis as any).CustomEvent;
|
||||
|
||||
export { defaultCustomEvent as CustomEvent };
|
||||
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Polyfill implementation for `@llamaindex/env`.
|
||||
*
|
||||
* The code should be compatible with any JS runtime.
|
||||
*
|
||||
* Sometimes you should overwrite the polyfill with a native implementation.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
import { Sha256 } from "@aws-crypto/sha256-js";
|
||||
import pathe from "pathe";
|
||||
import { fs } from "./fs/memory.js";
|
||||
|
||||
export { fs, pathe as path };
|
||||
|
||||
export interface SHA256 {
|
||||
update(data: string | Uint8Array): void;
|
||||
// to base64
|
||||
digest(): string;
|
||||
}
|
||||
|
||||
export const EOL = "\n";
|
||||
|
||||
export function ok(value: unknown, message?: string): asserts value {
|
||||
if (!value) {
|
||||
const error = Error(message);
|
||||
error.name = "AssertionError";
|
||||
error.message = message ?? "The expression evaluated to a falsy value.";
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export function createSHA256(): SHA256 {
|
||||
const sha256 = new Sha256();
|
||||
return {
|
||||
update(data: string | Uint8Array): void {
|
||||
sha256.update(data);
|
||||
},
|
||||
digest() {
|
||||
return globalThis.btoa(sha256.digestSync().toString());
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function randomUUID(): string {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
|
||||
export {
|
||||
AsyncLocalStorage,
|
||||
CustomEvent,
|
||||
getEnv,
|
||||
setEnvs,
|
||||
} from "./utils/index.web.js";
|
||||
@@ -1,5 +1,45 @@
|
||||
# @llamaindex/experimental
|
||||
|
||||
## 0.0.79
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [fbd5e01]
|
||||
- Updated dependencies [6b70c54]
|
||||
- Updated dependencies [1a6137b]
|
||||
- Updated dependencies [85c2e19]
|
||||
- llamaindex@0.6.1
|
||||
|
||||
## 0.0.78
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [11feef8]
|
||||
- llamaindex@0.6.0
|
||||
|
||||
## 0.0.77
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [7edeb1c]
|
||||
- llamaindex@0.5.27
|
||||
|
||||
## 0.0.76
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ffe0cd1]
|
||||
- Updated dependencies [ffe0cd1]
|
||||
- llamaindex@0.5.26
|
||||
|
||||
## 0.0.75
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [4810364]
|
||||
- Updated dependencies [d3bc663]
|
||||
- llamaindex@0.5.25
|
||||
|
||||
## 0.0.74
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/experimental",
|
||||
"description": "Experimental package for LlamaIndexTS",
|
||||
"version": "0.0.74",
|
||||
"version": "0.0.79",
|
||||
"type": "module",
|
||||
"types": "dist/type/index.d.ts",
|
||||
"main": "dist/cjs/index.js",
|
||||
|
||||
@@ -1,5 +1,74 @@
|
||||
# llamaindex
|
||||
|
||||
## 0.6.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fbd5e01: refactor: move groq as llm package
|
||||
- 6b70c54: feat: update JinaAIEmbedding, support embedding v3
|
||||
- 1a6137b: feat: experimental support for browser
|
||||
|
||||
If you see bundler issue in next.js edge runtime, please bump to `next@14` latest version.
|
||||
|
||||
- 85c2e19: feat: `@llamaindex/cloud` package update
|
||||
|
||||
- Bump to latest openapi schema
|
||||
- Move LlamaParse class from llamaindex, this will allow you use llamaparse in more non-node.js environment
|
||||
|
||||
- Updated dependencies [ac07e3c]
|
||||
- Updated dependencies [fbd5e01]
|
||||
- Updated dependencies [70ccb4a]
|
||||
- Updated dependencies [1a6137b]
|
||||
- Updated dependencies [85c2e19]
|
||||
- Updated dependencies [ac07e3c]
|
||||
- @llamaindex/core@0.2.1
|
||||
- @llamaindex/env@0.1.11
|
||||
- @llamaindex/groq@0.0.2
|
||||
- @llamaindex/cloud@0.2.5
|
||||
- @llamaindex/openai@0.1.3
|
||||
|
||||
## 0.6.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 11feef8: Add workflows
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [11feef8]
|
||||
- @llamaindex/core@0.2.0
|
||||
- @llamaindex/openai@0.1.2
|
||||
|
||||
## 0.5.27
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 7edeb1c: feat: decouple openai from `llamaindex` module
|
||||
|
||||
This should be a non-breaking change, but just you can now only install `@llamaindex/openai` to reduce the bundle size in the future
|
||||
|
||||
- Updated dependencies [7edeb1c]
|
||||
- @llamaindex/openai@0.1.1
|
||||
|
||||
## 0.5.26
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ffe0cd1: faet: add openai o1 support
|
||||
- ffe0cd1: feat: add PostgreSQL storage
|
||||
|
||||
## 0.5.25
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 4810364: fix: handle `RouterQueryEngine` with string query
|
||||
- d3bc663: refactor: export vector store only in nodejs environment on top level
|
||||
|
||||
If you see some missing modules error, please change vector store related imports to `llamaindex/vector-store`
|
||||
|
||||
- Updated dependencies [4810364]
|
||||
- @llamaindex/cloud@0.2.4
|
||||
|
||||
## 0.5.24
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,5 +1,45 @@
|
||||
# @llamaindex/cloudflare-worker-agent-test
|
||||
|
||||
## 0.0.63
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [fbd5e01]
|
||||
- Updated dependencies [6b70c54]
|
||||
- Updated dependencies [1a6137b]
|
||||
- Updated dependencies [85c2e19]
|
||||
- llamaindex@0.6.1
|
||||
|
||||
## 0.0.62
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [11feef8]
|
||||
- llamaindex@0.6.0
|
||||
|
||||
## 0.0.61
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [7edeb1c]
|
||||
- llamaindex@0.5.27
|
||||
|
||||
## 0.0.60
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ffe0cd1]
|
||||
- Updated dependencies [ffe0cd1]
|
||||
- llamaindex@0.5.26
|
||||
|
||||
## 0.0.59
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [4810364]
|
||||
- Updated dependencies [d3bc663]
|
||||
- llamaindex@0.5.25
|
||||
|
||||
## 0.0.58
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/cloudflare-worker-agent-test",
|
||||
"version": "0.0.58",
|
||||
"version": "0.0.63",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -16,7 +16,7 @@
|
||||
"@cloudflare/workers-types": "^4.20240821.1",
|
||||
"@vitest/runner": "1.5.3",
|
||||
"@vitest/snapshot": "1.5.3",
|
||||
"typescript": "^5.5.4",
|
||||
"typescript": "^5.6.2",
|
||||
"vitest": "1.5.3",
|
||||
"wrangler": "^3.73.0"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
@@ -0,0 +1,8 @@
|
||||
# @llamaindex/llama-parse-browser-test
|
||||
|
||||
## 0.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [85c2e19]
|
||||
- @llamaindex/cloud@0.2.5
|
||||
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + TS</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "@llamaindex/llama-parse-browser-test",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.5.3",
|
||||
"vite": "^5.4.1",
|
||||
"vite-plugin-wasm": "^3.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@llamaindex/cloud": "workspace:*"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { LlamaParseReader } from "@llamaindex/cloud/reader";
|
||||
import "./style.css";
|
||||
|
||||
new LlamaParseReader();
|
||||
|
||||
document.querySelector<HTMLDivElement>("#app")!.innerHTML = `
|
||||
<div>
|
||||
Hello, world!
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1,96 @@
|
||||
:root {
|
||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
#app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
transition: filter 300ms;
|
||||
}
|
||||
.logo:hover {
|
||||
filter: drop-shadow(0 0 2em #646cffaa);
|
||||
}
|
||||
.logo.vanilla:hover {
|
||||
filter: drop-shadow(0 0 2em #3178c6aa);
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user