Compare commits

...

14 Commits

Author SHA1 Message Date
github-actions[bot] 06af08cac4 Release 0.4.8 (#998)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-01 15:07:50 -07:00
Alex Yang 83ebdfb1c5 fix: next.js binding (#997) 2024-07-01 14:52:57 -07:00
github-actions[bot] 835b1ac000 Release 0.4.7 (#986)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-06-28 22:58:14 -07:00
Alex Yang f10b41dbc1 chore: fix release files (#991) 2024-06-28 13:36:55 -07:00
Wassim Chegham 41fe871e2f feat: add support for azure dynamic session tool (#942)
Co-authored-by: Marcus Schiesser <marcus.schiesser@googlemail.com>
2024-06-27 13:18:05 -07:00
Alex Yang 321c39ddc7 fix: generate api as class (#988) 2024-06-27 09:58:00 -07:00
Alex Yang f7f1af0139 fix: llamacloud sdk edge case (#985) 2024-06-26 23:10:04 -07:00
github-actions[bot] a8c9c279d6 Release 0.4.6 (#981)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-06-26 17:22:28 -07:00
Alex Yang eece129831 feat: migrate @llamaindex/cloud package (#984) 2024-06-26 16:51:47 -07:00
Alex Yang 80e4f51a83 fix: remove check-minor-version.mjs
We no longer need that
2024-06-26 15:31:08 -07:00
Alex Yang 22ff0837c3 feat: init @llamaindex/core (#938) 2024-06-26 15:28:57 -07:00
Alex Yang 74d7e05bcb ci: continue when commit lockfile error (#982) 2024-06-26 11:06:06 -07:00
Parham Saidi 1feb23bb83 feat: added Gemini tool calling support (#973) 2024-06-26 10:49:11 -07:00
Marcus Schiesser 08c55ec258 fix: Add metadata to PDFs and use Uint8Array for readers content (#980) 2024-06-26 10:16:23 -07:00
194 changed files with 13702 additions and 2469 deletions
-36
View File
@@ -1,36 +0,0 @@
name: Publish
on:
push:
branches:
- main
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
cache: "pnpm"
- name: Install dependencies
run: pnpm install
- name: Publish @llamaindex/env
run: npx jsr publish
working-directory: packages/env
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish @llamaindex/llamaindex
run: npx jsr publish --allow-slow-types
working-directory: packages/llamaindex
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+2
View File
@@ -58,9 +58,11 @@ jobs:
# Refs: https://github.com/changesets/changesets/issues/421
- name: Update lock file
continue-on-error: true
run: pnpm install --lockfile-only
- name: Commit lock file
continue-on-error: true
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "chore: update lock file"
+6
View File
@@ -128,6 +128,12 @@ jobs:
run: pnpm run build
- name: Copy examples
run: rsync -rv --exclude=node_modules ./examples ${{ runner.temp }}
- name: Pack @llamaindex/cloud
run: pnpm pack --pack-destination ${{ runner.temp }}
working-directory: packages/cloud
- name: Pack @llamaindex/core
run: pnpm pack --pack-destination ${{ runner.temp }}
working-directory: packages/core
- name: Pack @llamaindex/env
run: pnpm pack --pack-destination ${{ runner.temp }}
working-directory: packages/env
+3
View File
@@ -48,3 +48,6 @@ playwright/.cache/
# intellij
**/.idea
# generated API
packages/cloud/src/client
+24
View File
@@ -1,5 +1,29 @@
# docs
## 0.0.34
### Patch Changes
- Updated dependencies [83ebdfb]
- llamaindex@0.4.8
## 0.0.33
### Patch Changes
- Updated dependencies [41fe871]
- Updated dependencies [321c39d]
- Updated dependencies [f7f1af0]
- llamaindex@0.4.7
## 0.0.32
### Patch Changes
- Updated dependencies [1feb23b]
- Updated dependencies [08c55ec]
- llamaindex@0.4.6
## 0.0.31
### Patch Changes
+6
View File
@@ -0,0 +1,6 @@
# Gemini Agent
import CodeBlock from "@theme/CodeBlock";
import CodeSourceGemini from "!raw-loader!../../../../examples/gemini/agent.ts";
<CodeBlock language="ts">{CodeSourceGemini}</CodeBlock>
+3 -1
View File
@@ -12,12 +12,14 @@ An “agent” is an automated reasoning and decision engine. It takes in a user
LlamaIndex.TS comes with a few built-in agents, but you can also create your own. The built-in agents include:
- OpenAI Agent
- Anthropic Agent
- Anthropic Agent both via Anthropic and Bedrock (in `@llamaIndex/community`)
- Gemini Agent
- ReACT Agent
## Examples
- [OpenAI Agent](../../examples/agent.mdx)
- [Gemini Agent](../../examples/agent_gemini.mdx)
## Api References
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "docs",
"version": "0.0.31",
"version": "0.0.34",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
+1 -1
View File
@@ -9,7 +9,7 @@ make sure you have basic knowledge of the [LlamaIndexTS](https://ts.llamaindex.a
# export your API key
export OPENAI_API_KEY="sk-..."
npx ts-node ./chatEngine.ts
npx tsx ./chatEngine.ts
```
## Build your own RAG app
+54
View File
@@ -0,0 +1,54 @@
import "dotenv/config";
import {
DefaultAzureCredential,
getBearerTokenProvider,
} from "@azure/identity";
import { AzureDynamicSessionTool, OpenAI, ReActAgent } from "llamaindex";
async function main() {
const credential = new DefaultAzureCredential();
const azureADTokenProvider = getBearerTokenProvider(
credential,
"https://cognitiveservices.azure.com/.default",
);
const azure = {
azureADTokenProvider,
deployment: process.env.AZURE_OPENAI_DEPLOYMENT ?? "gpt-35-turbo",
};
// configure LLM model
const llm = new OpenAI({
azure,
});
const azureDynamicSession = new AzureDynamicSessionTool();
// Create an ReActAgent with the azure dynamic session tool
const agent = new ReActAgent({
llm,
tools: [azureDynamicSession],
// verbose: true,
systemPrompt: `You are a Python interpreter.
- You are given tasks to complete and you run python code to solve them.
- The python code runs by the python runtime. Every time you call $(interpreter) tool, the python code is executed in a separate cell. It's okay to make multiple calls to $(interpreter).
- You can run any python code you want in a secure environment.
- For images, return the full URL, not the base64 data.
- Return any image content as an HTML tag with the src attribute set to the URL of the image.`,
});
// Chat with the agent
const response = await agent.chat({
message:
"plot a chart of 5 random numbers and save it to /mnt/data/chart.png",
stream: false,
});
// Print the response
console.log({ response });
}
void main().then(() => {
console.log("Done");
});
+3 -3
View File
@@ -24,7 +24,7 @@ Here are two sample scripts which work well with the sample data in the Astra Po
Loads and queries a simple vectorstore with some documents about Astra DB
run `ts-node astradb/example`
run `tsx astradb/example`
## Movie Reviews Example
@@ -32,10 +32,10 @@ run `ts-node astradb/example`
This sample loads the same dataset of movie reviews as the Astra Portal sample dataset. (Feel free to load the data in your the Astra Data Explorer to compare)
run `npx ts-node astradb/load`
run `npx tsx astradb/load`
### Use RAG to Query the data
Check out your data in the Astra Data Explorer and change the sample query as you see fit.
run `npx ts-node astradb/query`
run `npx tsx astradb/query`
+1 -1
View File
@@ -6,7 +6,7 @@ Export your OpenAI API Key using `export OPEN_API_KEY=insert your api key here`
If you haven't installed chromadb, run `pip install chromadb`. Start the server using `chroma run`.
Now, open a new terminal window and inside `examples`, run `pnpm dlx ts-node chromadb/test.ts`.
Now, open a new terminal window and inside `examples`, run `pnpm dlx tsx chromadb/test.ts`.
Here's the output for the input query `Tell me about Godfrey Cheshire's rating of La Sapienza.`:
+3 -3
View File
@@ -21,7 +21,7 @@ export LLAMA_CLOUD_BASE_URL="https://api.staging.llamaindex.ai"
This example is using the managed index named `test` from the project `default` to create a chat engine.
```shell
pnpx ts-node cloud/chat.ts
pnpx tsx cloud/chat.ts
```
## Query Engine
@@ -29,7 +29,7 @@ pnpx ts-node cloud/chat.ts
This example shows how to use the managed index with a query engine.
```shell
pnpx ts-node cloud/query.ts
pnpx tsx cloud/query.ts
```
## Pipeline
@@ -37,5 +37,5 @@ pnpx ts-node cloud/query.ts
This example shows how to create a managed index with a pipeline.
```shell
pnpx ts-node cloud/pipeline.ts
pnpx tsx cloud/pipeline.ts
```
+2 -2
View File
@@ -6,7 +6,7 @@ import { ContextChatEngine, LlamaCloudIndex } from "llamaindex";
async function main() {
const index = new LlamaCloudIndex({
name: "test",
projectName: "default",
projectName: "Default",
baseUrl: process.env.LLAMA_CLOUD_BASE_URL,
apiKey: process.env.LLAMA_CLOUD_API_KEY,
});
@@ -19,10 +19,10 @@ async function main() {
while (true) {
const query = await rl.question("User: ");
const stream = await chatEngine.chat({ message: query, stream: true });
console.log();
for await (const chunk of stream) {
process.stdout.write(chunk.response);
}
process.stdout.write("\n");
}
}
+65
View File
@@ -0,0 +1,65 @@
import { FunctionTool, Gemini, GEMINI_MODEL, LLMAgent } from "llamaindex";
const sumNumbers = FunctionTool.from(
({ a, b }: { a: number; b: number }) => `${a + b}`,
{
name: "sumNumbers",
description: "Use this function to sum two numbers",
parameters: {
type: "object",
properties: {
a: {
type: "number",
description: "The first number",
},
b: {
type: "number",
description: "The second number",
},
},
required: ["a", "b"],
},
},
);
const divideNumbers = FunctionTool.from(
({ a, b }: { a: number; b: number }) => `${a / b}`,
{
name: "divideNumbers",
description: "Use this function to divide two numbers",
parameters: {
type: "object",
properties: {
a: {
type: "number",
description: "The dividend a to divide",
},
b: {
type: "number",
description: "The divisor b to divide by",
},
},
required: ["a", "b"],
},
},
);
async function main() {
const gemini = new Gemini({
model: GEMINI_MODEL.GEMINI_PRO,
});
const agent = new LLMAgent({
llm: gemini,
tools: [sumNumbers, divideNumbers],
});
const response = await agent.chat({
message: "How much is 5 + 5? then divide by 2",
});
console.log(response.message);
}
void main().then(() => {
console.log("Done");
});
+2 -2
View File
@@ -25,10 +25,10 @@ Here are two sample scripts which work with loading and querying data from a Mil
This sample loads the same dataset of movie reviews as sample dataset. You can install https://github.com/zilliztech/attu to inspect the loaded data.
run `npx ts-node milvus/load`
run `npx tsx milvus/load`
## Use RAG to Query the data
Check out your data in Attu and change the sample query as you see fit.
run `npx ts-node milvus/query`
run `npx tsx milvus/query`
+3 -3
View File
@@ -34,7 +34,7 @@ MONGODB_COLLECTION=tiny_tweets_collection
You are now ready to import our ready-made data set into Mongo. This is the file `tinytweets.json`, a selection of approximately 1000 tweets from @seldo on Twitter in mid-2019. With your environment set up you can do this by running
```
npx ts-node mongodb/1_import.ts
npx tsx mongodb/1_import.ts
```
If you don't want to use tweets, you can replace `json_file` with any other array of JSON objects, but you will need to modify some code later to make sure the correct field gets indexed. There is no LlamaIndex-specific code here; you can load your data into Mongo any way you want to.
@@ -59,7 +59,7 @@ MONGODB_VECTOR_INDEX=tiny_tweets_vector_index
If the data you're indexing is the tweets we gave you, you're ready to go:
```bash
npx ts-node mongodb/2_load_and_index.ts
npx tsx mongodb/2_load_and_index.ts
```
> Note: this script is running a couple of minutes and currently doesn't show any progress.
@@ -112,7 +112,7 @@ Now you're ready to query your data!
You can do this by running
```bash
npx ts-node mongodb/3_query.ts
npx tsx mongodb/3_query.ts
```
This sets up a connection to Atlas just like `2_load_and_index.ts` did, then it creates a [query engine](https://docs.llamaindex.ai/en/stable/understanding/querying/querying.html#getting-started) and runs a query against it.
+1 -1
View File
@@ -4,6 +4,7 @@
"version": "0.0.6",
"dependencies": {
"@aws-crypto/sha256-js": "^5.2.0",
"@azure/identity": "^4.2.1",
"@datastax/astra-db-ts": "^1.2.1",
"@notionhq/client": "^2.2.15",
"@pinecone-database/pinecone": "^2.2.2",
@@ -18,7 +19,6 @@
},
"devDependencies": {
"@types/node": "^20.14.1",
"ts-node": "^10.9.2",
"tsx": "^4.15.6",
"typescript": "^5.5.2"
},
+2 -2
View File
@@ -37,7 +37,7 @@ Read and follow the instructions in the README.md file located one directory up
To import documents and save the embedding vectors to your database:
> `npx ts-node pg-vector-store/load-docs.ts data`
> `npx tsx pg-vector-store/load-docs.ts data`
where data is the directory containing your input files. Using the `data` directory in the example above will read all of the files in that directory using the LlamaIndexTS default readers for each file type.
@@ -45,6 +45,6 @@ where data is the directory containing your input files. Using the `data` direct
To query using the resulting vector store:
> `npx ts-node pg-vector-store/query.ts`
> `npx tsx pg-vector-store/query.ts`
The script will prompt for a question, then process and present the answer using the PGVectorStore data and your OpenAI API key. It will continue to prompt until you enter `q`, `quit` or `exit` as the next query.
+2 -2
View File
@@ -19,7 +19,7 @@ Read and follow the instructions in the README.md file located one directory up
To import documents and save the embedding vectors to your database:
> `npx ts-node pinecone-vector-store/load-docs.ts data`
> `npx tsx pinecone-vector-store/load-docs.ts data`
where data is the directory containing your input files. Using the _data_ directory in the example above will read all of the files in that directory using the llamaindexTS default readers for each file type.
@@ -29,6 +29,6 @@ where data is the directory containing your input files. Using the _data_ direct
To query using the resulting vector store:
> `npx ts-node pinecone-vector-store/query.ts`
> `npx tsx pinecone-vector-store/query.ts`
The script will prompt for a question, then process and present the answer using the PineconeVectorStore data and your OpenAI API key. It will continue to prompt until you enter `q`, `quit` or `exit` as the next query.
+1 -1
View File
@@ -8,4 +8,4 @@ Add your OpenAI API Key into a file called `.env` in the parent folder of this d
OPEN_API_KEY=sk-you-key
```
Now, open a new terminal window and inside `examples`, run `npx ts-node qdrantdb/preFilters.ts`.
Now, open a new terminal window and inside `examples`, run `npx tsx qdrantdb/preFilters.ts`.
@@ -7,7 +7,7 @@ import {
import { TextFileReader } from "llamaindex/readers/TextFileReader";
class ZipReader extends FileReader {
loadDataAsContent(fileContent: Buffer): Promise<Document<Metadata>[]> {
loadDataAsContent(fileContent: Uint8Array): Promise<Document<Metadata>[]> {
throw new Error("Implement me");
}
}
+8 -6
View File
@@ -12,10 +12,9 @@
"e2e": "turbo run e2e",
"test": "turbo run test",
"type-check": "tsc -b --diagnostics",
"release": "pnpm run check-minor-version && pnpm run build:release && changeset publish",
"release-snapshot": "pnpm run check-minor-version && pnpm run build:release && changeset publish --tag snapshot",
"check-minor-version": "node ./scripts/check-minor-version.mjs",
"new-version": "changeset version && pnpm run check-minor-version && pnpm format:write && pnpm run build:release",
"release": "pnpm run build:release && changeset publish",
"release-snapshot": "pnpm run build:release && changeset publish --tag snapshot",
"new-version": "changeset version && pnpm format:write && pnpm run build:release",
"new-snapshot": "pnpm run build:release && changeset version --snapshot"
},
"devDependencies": {
@@ -24,14 +23,14 @@
"eslint": "^8.57.0",
"eslint-config-next": "^14.2.4",
"eslint-config-prettier": "^9.1.0",
"eslint-config-turbo": "^1.13.4",
"eslint-config-turbo": "^2.0.5",
"eslint-plugin-react": "7.34.1",
"husky": "^9.0.11",
"lint-staged": "^15.2.7",
"madge": "^7.0.0",
"prettier": "^3.3.2",
"prettier-plugin-organize-imports": "^3.2.4",
"turbo": "^1.13.4",
"turbo": "^2.0.5",
"typescript": "^5.5.2"
},
"packageManager": "pnpm@9.4.0",
@@ -40,6 +39,9 @@
"trim": "1.0.1",
"@babel/traverse": "7.23.2",
"protobufjs": "7.2.6"
},
"patchedDependencies": {
"bunchee@5.2.1": "patches/bunchee@5.2.1.patch"
}
},
"lint-staged": {
@@ -1,5 +1,32 @@
# @llamaindex/autotool-02-next-example
## 0.1.18
### Patch Changes
- Updated dependencies [83ebdfb]
- llamaindex@0.4.8
- @llamaindex/autotool@1.0.0
## 0.1.17
### Patch Changes
- Updated dependencies [41fe871]
- Updated dependencies [321c39d]
- Updated dependencies [f7f1af0]
- llamaindex@0.4.7
- @llamaindex/autotool@1.0.0
## 0.1.16
### Patch Changes
- Updated dependencies [1feb23b]
- Updated dependencies [08c55ec]
- llamaindex@0.4.6
- @llamaindex/autotool@1.0.0
## 0.1.15
### Patch Changes
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/autotool-02-next-example",
"private": true,
"version": "0.1.15",
"version": "0.1.18",
"scripts": {
"dev": "next dev",
"build": "next build",
+1 -1
View File
@@ -51,7 +51,7 @@
"unplugin": "^1.10.1"
},
"peerDependencies": {
"llamaindex": "^0.4.5",
"llamaindex": "^0.4.8",
"openai": "^4",
"typescript": "^4"
},
+7
View File
@@ -0,0 +1,7 @@
# @llamaindex/cloud
## 0.1.1
### Patch Changes
- 321c39d: fix: generate api as class
+18
View File
@@ -0,0 +1,18 @@
# @llamaindex/cloud
> LlamaCloud is a new generation of managed parsing, ingestion, and retrieval services, designed to bring production-grade context-augmentation to your LLM and RAG applications.
## Usage
```ts
import { OpenAPI } from "@llamaindex/cloud/api";
OpenAPI.TOKEN = "YOUR_API_KEY";
OpenAPI.BASE = "https://api.cloud.llamaindex.ai/";
// ...
```
For more information, see the [API documentation](https://docs.cloud.llamaindex.ai/).
## License
MIT
+18
View File
@@ -0,0 +1,18 @@
import { defineConfig } from "@hey-api/openapi-ts";
export default defineConfig({
// you can download this file to get the latest version of the OpenAPI document
// @link https://api.cloud.llamaindex.ai/api/openapi.json
input: "./openapi.json",
output: {
path: "./src/client",
format: "prettier",
lint: "eslint",
},
services: {
asClass: true,
},
types: {
enums: "javascript",
},
});
File diff suppressed because it is too large Load Diff
+40
View File
@@ -0,0 +1,40 @@
{
"name": "@llamaindex/cloud",
"version": "0.1.1",
"type": "module",
"license": "MIT",
"scripts": {
"generate": "pnpm dlx @hey-api/openapi-ts",
"build": "pnpm run generate && bunchee"
},
"files": [
"openapi.json",
"dist"
],
"exports": {
"./openapi.json": "./openapi.json",
"./api": {
"require": {
"types": "./dist/api.d.cts",
"default": "./dist/api.cjs"
},
"import": {
"types": "./dist/api.d.ts",
"default": "./dist/api.js"
},
"default": {
"types": "./dist/api.d.ts",
"default": "./dist/api.js"
}
}
},
"repository": {
"type": "git",
"url": "https://github.com/himself65/LlamaIndexTS.git",
"directory": "packages/cloud"
},
"devDependencies": {
"@hey-api/openapi-ts": "^0.48.0",
"bunchee": "^5.2.1"
}
}
+1
View File
@@ -0,0 +1 @@
export * from "./client";
+15
View File
@@ -0,0 +1,15 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist/type",
"tsBuildInfoFile": "./dist/.tsbuildinfo",
"emitDeclarationOnly": true,
"moduleResolution": "Bundler",
"skipLibCheck": true,
"strict": true,
"lib": ["DOM", "ESNext"]
},
"include": ["./src"],
"exclude": ["node_modules"]
}
+24
View File
@@ -1,5 +1,29 @@
# @llamaindex/community
## 0.0.12
### Patch Changes
- Updated dependencies [83ebdfb]
- llamaindex@0.4.8
## 0.0.11
### Patch Changes
- Updated dependencies [41fe871]
- Updated dependencies [321c39d]
- Updated dependencies [f7f1af0]
- llamaindex@0.4.7
## 0.0.10
### Patch Changes
- Updated dependencies [1feb23b]
- Updated dependencies [08c55ec]
- llamaindex@0.4.6
## 0.0.9
### Patch Changes
-8
View File
@@ -1,8 +0,0 @@
{
"name": "@llamaindex/community",
"version": "0.0.5",
"exports": {
".": "./src/index.ts",
"./type": "./src/type.ts"
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/community",
"description": "Community package for LlamaIndexTS",
"version": "0.0.9",
"version": "0.0.12",
"type": "module",
"types": "dist/type/index.d.ts",
"main": "dist/cjs/index.js",
+9
View File
@@ -0,0 +1,9 @@
# @llamaindex/core
## 0.0.2
### Patch Changes
- f10b41d: fix: release files
- Updated dependencies [41fe871]
- @llamaindex/env@0.1.7
+70
View File
@@ -0,0 +1,70 @@
{
"name": "@llamaindex/core",
"type": "module",
"version": "0.0.2",
"description": "LlamaIndex Core Module",
"exports": {
"./decorator": {
"require": {
"types": "./dist/decorator/index.d.cts",
"default": "./dist/decorator/index.cjs"
},
"import": {
"types": "./dist/decorator/index.d.ts",
"default": "./dist/decorator/index.js"
},
"default": {
"types": "./dist/decorator/index.d.ts",
"default": "./dist/decorator/index.js"
}
},
"./global": {
"require": {
"types": "./dist/global/index.d.cts",
"default": "./dist/global/index.cjs"
},
"import": {
"types": "./dist/global/index.d.ts",
"default": "./dist/global/index.js"
},
"default": {
"types": "./dist/global/index.d.ts",
"default": "./dist/global/index.js"
}
},
"./schema": {
"require": {
"types": "./dist/schema/index.d.cts",
"default": "./dist/schema/index.cjs"
},
"import": {
"types": "./dist/schema/index.d.ts",
"default": "./dist/schema/index.js"
},
"default": {
"types": "./dist/schema/index.d.ts",
"default": "./dist/schema/index.js"
}
}
},
"files": [
"dist"
],
"scripts": {
"dev": "bunchee --watch",
"build": "bunchee"
},
"repository": {
"type": "git",
"directory": "packages/core",
"url": "https://github.com/himself65/LlamaIndexTS.git"
},
"devDependencies": {
"bunchee": "^5.2.1"
},
"dependencies": {
"@llamaindex/env": "workspace:*",
"@types/node": "^20.14.9",
"zod": "^3.23.8"
}
}
@@ -1,11 +1,11 @@
import { getEnv } from "@llamaindex/env";
import type { BaseNode } from "../../Node.js";
import { getChunkSize } from "../settings/chunk-size.js";
import { Settings } from "../global";
import type { BaseNode } from "../schema/node";
const emitOnce = false;
export function chunkSizeCheck<
This extends BaseNode,
This extends { id_: string },
Args extends any[],
Return,
>(
@@ -17,7 +17,7 @@ export function chunkSizeCheck<
) {
return function (this: This, ...args: Args) {
const content = contentGetter.call(this, ...args);
const chunkSize = getChunkSize();
const chunkSize = Settings.chunkSize;
const enableChunkSizeCheck = getEnv("ENABLE_CHUNK_SIZE_CHECK") === "true";
if (
enableChunkSizeCheck &&
@@ -25,7 +25,7 @@ export function chunkSizeCheck<
content.length > chunkSize
) {
console.warn(
`Node (${this.id_}) is larger than chunk size: ${content.length}`,
`Node (${this.id_}) is larger than chunk size: ${content.length} > ${chunkSize}`,
);
if (!emitOnce) {
console.warn(
+1
View File
@@ -0,0 +1 @@
export { Settings } from "./settings";
+17
View File
@@ -0,0 +1,17 @@
import {
getChunkSize,
setChunkSize,
withChunkSize,
} from "./settings/chunk-size";
export const Settings = {
get chunkSize(): number | undefined {
return getChunkSize();
},
set chunkSize(chunkSize: number | undefined) {
setChunkSize(chunkSize);
},
withChunkSize<Result>(chunkSize: number, fn: () => Result): Result {
return withChunkSize(chunkSize, fn);
},
};
@@ -1,14 +1,16 @@
import { AsyncLocalStorage } from "@llamaindex/env";
const chunkSizeAsyncLocalStorage = new AsyncLocalStorage<number | undefined>();
const globalChunkSize: number | null = null;
let globalChunkSize: number | null = null;
export function getChunkSize(): number | undefined {
return globalChunkSize ?? chunkSizeAsyncLocalStorage.getStore();
}
export function setChunkSize(chunkSize: number | undefined) {
chunkSizeAsyncLocalStorage.enterWith(chunkSize);
if (chunkSize !== undefined) {
globalChunkSize = chunkSize;
}
}
export function withChunkSize<Result>(
+1
View File
@@ -0,0 +1 @@
export * from "./schema";
+2
View File
@@ -0,0 +1,2 @@
export * from "./node";
export * from "./zod";
+452
View File
@@ -0,0 +1,452 @@
import { createSHA256, path, randomUUID } from "@llamaindex/env";
import { chunkSizeCheck, lazyInitHash } from "../decorator";
export enum NodeRelationship {
SOURCE = "SOURCE",
PREVIOUS = "PREVIOUS",
NEXT = "NEXT",
PARENT = "PARENT",
CHILD = "CHILD",
}
export enum ObjectType {
TEXT = "TEXT",
IMAGE = "IMAGE",
INDEX = "INDEX",
DOCUMENT = "DOCUMENT",
IMAGE_DOCUMENT = "IMAGE_DOCUMENT",
}
export enum MetadataMode {
ALL = "ALL",
EMBED = "EMBED",
LLM = "LLM",
NONE = "NONE",
}
export type Metadata = Record<string, any>;
export interface RelatedNodeInfo<T extends Metadata = Metadata> {
nodeId: string;
nodeType?: ObjectType;
metadata: T;
hash?: string;
}
export type RelatedNodeType<T extends Metadata = Metadata> =
| RelatedNodeInfo<T>
| RelatedNodeInfo<T>[];
export type BaseNodeParams<T extends Metadata = Metadata> = {
id_?: string;
metadata?: T;
excludedEmbedMetadataKeys?: string[];
excludedLlmMetadataKeys?: string[];
relationships?: Partial<Record<NodeRelationship, RelatedNodeType<T>>>;
hash?: string;
embedding?: number[];
};
/**
* Generic abstract class for retrievable nodes
*/
export abstract class BaseNode<T extends Metadata = Metadata> {
/**
* The unique ID of the Node/Document. The trailing underscore is here
* to avoid collisions with the id keyword in Python.
*
* Set to a UUID by default.
*/
id_: string;
embedding?: number[];
// Metadata fields
metadata: T;
excludedEmbedMetadataKeys: string[];
excludedLlmMetadataKeys: string[];
relationships: Partial<Record<NodeRelationship, RelatedNodeType<T>>>;
@lazyInitHash
accessor hash: string = "";
protected constructor(init?: BaseNodeParams<T>) {
const {
id_,
metadata,
excludedEmbedMetadataKeys,
excludedLlmMetadataKeys,
relationships,
hash,
embedding,
} = init || {};
this.id_ = id_ ?? randomUUID();
this.metadata = metadata ?? ({} as T);
this.excludedEmbedMetadataKeys = excludedEmbedMetadataKeys ?? [];
this.excludedLlmMetadataKeys = excludedLlmMetadataKeys ?? [];
this.relationships = relationships ?? {};
this.embedding = embedding;
}
abstract get type(): ObjectType;
abstract getContent(metadataMode: MetadataMode): string;
abstract getMetadataStr(metadataMode: MetadataMode): string;
// todo: set value as a generic type
abstract setContent(value: unknown): void;
get sourceNode(): RelatedNodeInfo<T> | undefined {
const relationship = this.relationships[NodeRelationship.SOURCE];
if (Array.isArray(relationship)) {
throw new Error("Source object must be a single RelatedNodeInfo object");
}
return relationship;
}
get prevNode(): RelatedNodeInfo<T> | undefined {
const relationship = this.relationships[NodeRelationship.PREVIOUS];
if (Array.isArray(relationship)) {
throw new Error(
"Previous object must be a single RelatedNodeInfo object",
);
}
return relationship;
}
get nextNode(): RelatedNodeInfo<T> | undefined {
const relationship = this.relationships[NodeRelationship.NEXT];
if (Array.isArray(relationship)) {
throw new Error("Next object must be a single RelatedNodeInfo object");
}
return relationship;
}
get parentNode(): RelatedNodeInfo<T> | undefined {
const relationship = this.relationships[NodeRelationship.PARENT];
if (Array.isArray(relationship)) {
throw new Error("Parent object must be a single RelatedNodeInfo object");
}
return relationship;
}
get childNodes(): RelatedNodeInfo<T>[] | undefined {
const relationship = this.relationships[NodeRelationship.CHILD];
if (!Array.isArray(relationship)) {
throw new Error(
"Child object must be a an array of RelatedNodeInfo objects",
);
}
return relationship;
}
abstract generateHash(): string;
getEmbedding(): number[] {
if (this.embedding === undefined) {
throw new Error("Embedding not set");
}
return this.embedding;
}
asRelatedNodeInfo(): RelatedNodeInfo<T> {
return {
nodeId: this.id_,
metadata: this.metadata,
hash: this.hash,
};
}
/**
* Called by built in JSON.stringify (see https://javascript.info/json)
* Properties are read-only as they are not deep-cloned (not necessary for stringification).
* @see toMutableJSON - use to return a mutable JSON instead
*/
toJSON(): Record<string, any> {
return {
...this,
type: this.type,
// hash is an accessor property, so it's not included in the rest operator
hash: this.hash,
};
}
clone(): BaseNode {
return jsonToNode(this.toMutableJSON()) as BaseNode;
}
/**
* Converts the object to a JSON representation.
* Properties can be safely modified as a deep clone of the properties are created.
* @return {Record<string, any>} - The JSON representation of the object.
*/
toMutableJSON(): Record<string, any> {
return structuredClone(this.toJSON());
}
}
export type TextNodeParams<T extends Metadata = Metadata> =
BaseNodeParams<T> & {
text?: string;
textTemplate?: string;
startCharIdx?: number;
endCharIdx?: number;
metadataSeparator?: string;
};
/**
* TextNode is the default node type for text. Most common node type in LlamaIndex.TS
*/
export class TextNode<T extends Metadata = Metadata> extends BaseNode<T> {
text: string;
textTemplate: string;
startCharIdx?: number;
endCharIdx?: number;
// textTemplate: NOTE write your own formatter if needed
// metadataTemplate: NOTE write your own formatter if needed
metadataSeparator: string;
constructor(init: TextNodeParams<T> = {}) {
super(init);
const { text, textTemplate, startCharIdx, endCharIdx, metadataSeparator } =
init;
this.text = text ?? "";
this.textTemplate = textTemplate ?? "";
if (startCharIdx) {
this.startCharIdx = startCharIdx;
}
if (endCharIdx) {
this.endCharIdx = endCharIdx;
}
this.metadataSeparator = metadataSeparator ?? "\n";
}
/**
* Generate a hash of the text node.
* The ID is not part of the hash as it can change independent of content.
* @returns
*/
generateHash() {
const hashFunction = createSHA256();
hashFunction.update(`type=${this.type}`);
hashFunction.update(
`startCharIdx=${this.startCharIdx} endCharIdx=${this.endCharIdx}`,
);
hashFunction.update(this.getContent(MetadataMode.ALL));
return hashFunction.digest();
}
get type() {
return ObjectType.TEXT;
}
@chunkSizeCheck
getContent(metadataMode: MetadataMode = MetadataMode.NONE): string {
const metadataStr = this.getMetadataStr(metadataMode).trim();
return `${metadataStr}\n\n${this.text}`.trim();
}
getMetadataStr(metadataMode: MetadataMode): string {
if (metadataMode === MetadataMode.NONE) {
return "";
}
const usableMetadataKeys = new Set(Object.keys(this.metadata).sort());
if (metadataMode === MetadataMode.LLM) {
for (const key of this.excludedLlmMetadataKeys) {
usableMetadataKeys.delete(key);
}
} else if (metadataMode === MetadataMode.EMBED) {
for (const key of this.excludedEmbedMetadataKeys) {
usableMetadataKeys.delete(key);
}
}
return [...usableMetadataKeys]
.map((key) => `${key}: ${this.metadata[key]}`)
.join(this.metadataSeparator);
}
setContent(value: string) {
this.text = value;
this.hash = this.generateHash();
}
getNodeInfo() {
return { start: this.startCharIdx, end: this.endCharIdx };
}
getText() {
return this.getContent(MetadataMode.NONE);
}
}
export type IndexNodeParams<T extends Metadata = Metadata> =
TextNodeParams<T> & {
indexId: string;
};
export class IndexNode<T extends Metadata = Metadata> extends TextNode<T> {
indexId: string;
constructor(init?: IndexNodeParams<T>) {
super(init);
const { indexId } = init || {};
this.indexId = indexId ?? "";
}
get type() {
return ObjectType.INDEX;
}
}
/**
* A document is just a special text node with a docId.
*/
export class Document<T extends Metadata = Metadata> extends TextNode<T> {
constructor(init?: TextNodeParams<T>) {
super(init);
}
get type() {
return ObjectType.DOCUMENT;
}
}
export function jsonToNode(json: any, type?: ObjectType) {
if (!json.type && !type) {
throw new Error("Node type not found");
}
const nodeType = type || json.type;
switch (nodeType) {
case ObjectType.TEXT:
return new TextNode(json);
case ObjectType.INDEX:
return new IndexNode(json);
case ObjectType.DOCUMENT:
return new Document(json);
case ObjectType.IMAGE_DOCUMENT:
return new ImageDocument(json);
default:
throw new Error(`Invalid node type: ${nodeType}`);
}
}
export type ImageType = string | Blob | URL;
export type ImageNodeParams<T extends Metadata = Metadata> =
TextNodeParams<T> & {
image: ImageType;
};
export class ImageNode<T extends Metadata = Metadata> extends TextNode<T> {
image: ImageType; // image as blob
constructor(init: ImageNodeParams<T>) {
super(init);
const { image } = init;
this.image = image;
}
get type() {
return ObjectType.IMAGE;
}
getUrl(): URL {
// id_ stores the relative path, convert it to the URL of the file
const absPath = path.resolve(this.id_);
return new URL(`file://${absPath}`);
}
// Calculates the image part of the hash
private generateImageHash() {
const hashFunction = createSHA256();
if (this.image instanceof Blob) {
// TODO: ideally we should use the blob's content to calculate the hash:
// hashFunction.update(new Uint8Array(await this.image.arrayBuffer()));
// as this is async, we're using the node's ID for the time being
hashFunction.update(this.id_);
} else if (this.image instanceof URL) {
hashFunction.update(this.image.toString());
} else if (typeof this.image === "string") {
hashFunction.update(this.image);
} else {
throw new Error(
`Unknown image type: ${typeof this.image}. Can't calculate hash`,
);
}
return hashFunction.digest();
}
generateHash() {
const hashFunction = createSHA256();
// calculates hash based on hash of both components (image and text)
hashFunction.update(super.generateHash());
hashFunction.update(this.generateImageHash());
return hashFunction.digest();
}
}
export class ImageDocument<T extends Metadata = Metadata> extends ImageNode<T> {
constructor(init: ImageNodeParams<T>) {
super(init);
}
get type() {
return ObjectType.IMAGE_DOCUMENT;
}
}
/**
* A node with a similarity score
*/
export interface NodeWithScore<T extends Metadata = Metadata> {
node: BaseNode<T>;
score?: number;
}
export enum ModalityType {
TEXT = "TEXT",
IMAGE = "IMAGE",
}
type NodesByType = {
[P in ModalityType]?: BaseNode[];
};
export function splitNodesByType(nodes: BaseNode[]): NodesByType {
const result: NodesByType = {};
for (const node of nodes) {
let type: ModalityType;
if (node instanceof ImageNode) {
type = ModalityType.IMAGE;
} else if (node instanceof TextNode) {
type = ModalityType.TEXT;
} else {
throw new Error(`Unknown node type: ${node.type}`);
}
if (type in result) {
result[type]?.push(node);
} else {
result[type] = [node];
}
}
return result;
}
+16
View File
@@ -0,0 +1,16 @@
import { z } from "zod";
export const toolMetadataSchema = z.object({
description: z.string(),
name: z.string(),
parameters: z.record(z.any()),
});
export const baseToolSchema = z.object({
call: z.optional(z.function()),
metadata: toolMetadataSchema,
});
export const baseToolWithCallSchema = baseToolSchema.extend({
call: z.function(),
});
+25
View File
@@ -0,0 +1,25 @@
import { Settings } from "@llamaindex/core/global";
import { TextNode } from "@llamaindex/core/schema";
import { env } from "process";
import { afterEach, describe, expect, test, vi } from "vitest";
describe("chunkSizeCheck", () => {
afterEach(() => {
Settings.chunkSize = undefined;
env.ENABLE_CHUNK_SIZE_CHECK = undefined;
});
test("should warn when content is larger than chunk size", () => {
env.ENABLE_CHUNK_SIZE_CHECK = "true";
let message = "";
const consoleMock = vi
.spyOn(console, "warn")
.mockImplementation((msg) => (message += msg + "\n"));
Settings.chunkSize = 0;
const node = new TextNode();
expect(message).toEqual("");
node.setContent("a".repeat(1024));
expect(message).toContain("is larger than chunk size");
});
});
+12
View File
@@ -0,0 +1,12 @@
{
"name": "@llamaindex/core-tests",
"private": true,
"type": "module",
"scripts": {
"test": "vitest"
},
"devDependencies": {
"@llamaindex/core": "workspace:*",
"vitest": "^1.6.0"
}
}
@@ -1,4 +1,4 @@
import { Document, TextNode } from "llamaindex/Node";
import { Document, TextNode } from "@llamaindex/core/schema";
import { beforeEach, describe, expect, test } from "vitest";
describe("Document", () => {
@@ -50,7 +50,6 @@ describe("TextNode", () => {
`
{
"embedding": undefined,
"endCharIdx": undefined,
"excludedEmbedMetadataKeys": [],
"excludedLlmMetadataKeys": [],
"hash": "Z6SWgFPlalaeblMGQGw0KS3qKgmZdEWXKfzEp/K+QN0=",
@@ -62,7 +61,6 @@ describe("TextNode", () => {
"metadataSeparator": "
",
"relationships": {},
"startCharIdx": undefined,
"text": "Hello World",
"textTemplate": "",
"type": "TEXT",
+18
View File
@@ -0,0 +1,18 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"outDir": "./lib",
"module": "node16",
"moduleResolution": "node16",
"target": "ESNext"
},
"include": ["./**/*.ts"],
"references": [
{
"path": "../tsconfig.json"
},
{
"path": "../../env/tsconfig.json"
}
]
}
+15
View File
@@ -0,0 +1,15 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist/type",
"tsBuildInfoFile": "./dist/.tsbuildinfo",
"emitDeclarationOnly": true,
"moduleResolution": "Bundler",
"skipLibCheck": true,
"strict": true,
"types": ["node"]
},
"include": ["./src"],
"exclude": ["node_modules"]
}
+6
View File
@@ -1,5 +1,11 @@
# @llamaindex/env
## 0.1.7
### Patch Changes
- 41fe871: Add support for azure dynamic session tool
## 0.1.6
### Patch Changes
-10
View File
@@ -1,10 +0,0 @@
{
"name": "@llamaindex/env",
"version": "0.1.6",
"exports": {
".": "./src/index.edge-light.ts"
},
"publish": {
"include": ["LICENSE", "README.md", "src/**/*", "jsr.json"]
}
}
+1 -1
View File
@@ -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.6",
"version": "0.1.7",
"type": "module",
"types": "dist/type/index.d.ts",
"main": "dist/cjs/index.js",
+2 -1
View File
@@ -5,6 +5,7 @@
*
* @module
*/
import { createWriteStream } from "node:fs";
import fs from "node:fs/promises";
export { fs };
export { createWriteStream, fs };
+6 -1
View File
@@ -15,12 +15,14 @@ import { ok } from "node:assert";
import { createHash, randomUUID } from "node:crypto";
import { EOL } from "node:os";
import path from "node:path";
import { Readable } from "node:stream";
import {
ReadableStream,
TransformStream,
WritableStream,
} from "node:stream/web";
import { fs } from "./fs/node.js";
import { fileURLToPath } from "node:url";
import { createWriteStream, fs } from "./fs/node.js";
import type { SHA256 } from "./polyfill.js";
export function createSHA256(): SHA256 {
@@ -38,11 +40,14 @@ export function createSHA256(): SHA256 {
export { Tokenizers, tokenizers, type Tokenizer } from "./tokenizers/node.js";
export { AsyncLocalStorage, CustomEvent, getEnv, setEnvs } from "./utils.js";
export {
createWriteStream,
EOL,
fileURLToPath,
fs,
ok,
path,
randomUUID,
Readable,
ReadableStream,
TransformStream,
WritableStream,
+24
View File
@@ -1,5 +1,29 @@
# @llamaindex/experimental
## 0.0.43
### Patch Changes
- Updated dependencies [83ebdfb]
- llamaindex@0.4.8
## 0.0.42
### Patch Changes
- Updated dependencies [41fe871]
- Updated dependencies [321c39d]
- Updated dependencies [f7f1af0]
- llamaindex@0.4.7
## 0.0.41
### Patch Changes
- Updated dependencies [1feb23b]
- Updated dependencies [08c55ec]
- llamaindex@0.4.6
## 0.0.40
### Patch Changes
-8
View File
@@ -1,8 +0,0 @@
{
"name": "@llamaindex/experimental",
"version": "0.0.5",
"exports": {
".": "./src/index.ts",
"./type": "./src/type.ts"
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/experimental",
"description": "Experimental package for LlamaIndexTS",
"version": "0.0.40",
"version": "0.0.43",
"type": "module",
"types": "dist/type/index.d.ts",
"main": "dist/cjs/index.js",
+27
View File
@@ -1,5 +1,32 @@
# llamaindex
## 0.4.8
### Patch Changes
- 83ebdfb: fix: next.js build error
## 0.4.7
### Patch Changes
- 41fe871: Add support for azure dynamic session tool
- 321c39d: fix: generate api as class
- f7f1af0: fix: throw error when no pipeline found
- Updated dependencies [41fe871]
- Updated dependencies [f10b41d]
- Updated dependencies [321c39d]
- @llamaindex/env@0.1.7
- @llamaindex/core@0.0.2
- @llamaindex/cloud@0.1.1
## 0.4.6
### Patch Changes
- 1feb23b: feat: Gemini tool calling for agent support
- 08c55ec: Add metadata to PDFs and use Uint8Array for readers content
## 0.4.5
### Patch Changes
@@ -1,5 +1,29 @@
# @llamaindex/cloudflare-worker-agent-test
## 0.0.27
### Patch Changes
- Updated dependencies [83ebdfb]
- llamaindex@0.4.8
## 0.0.26
### Patch Changes
- Updated dependencies [41fe871]
- Updated dependencies [321c39d]
- Updated dependencies [f7f1af0]
- llamaindex@0.4.7
## 0.0.25
### Patch Changes
- Updated dependencies [1feb23b]
- Updated dependencies [08c55ec]
- llamaindex@0.4.6
## 0.0.24
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/cloudflare-worker-agent-test",
"version": "0.0.24",
"version": "0.0.27",
"type": "module",
"private": true,
"scripts": {
@@ -1,5 +1,29 @@
# @llamaindex/next-agent-test
## 0.1.27
### Patch Changes
- Updated dependencies [83ebdfb]
- llamaindex@0.4.8
## 0.1.26
### Patch Changes
- Updated dependencies [41fe871]
- Updated dependencies [321c39d]
- Updated dependencies [f7f1af0]
- llamaindex@0.4.7
## 0.1.25
### Patch Changes
- Updated dependencies [1feb23b]
- Updated dependencies [08c55ec]
- llamaindex@0.4.6
## 0.1.24
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/next-agent-test",
"version": "0.1.24",
"version": "0.1.27",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,5 +1,29 @@
# test-edge-runtime
## 0.1.26
### Patch Changes
- Updated dependencies [83ebdfb]
- llamaindex@0.4.8
## 0.1.25
### Patch Changes
- Updated dependencies [41fe871]
- Updated dependencies [321c39d]
- Updated dependencies [f7f1af0]
- llamaindex@0.4.7
## 0.1.24
### Patch Changes
- Updated dependencies [1feb23b]
- Updated dependencies [08c55ec]
- llamaindex@0.4.6
## 0.1.23
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/nextjs-edge-runtime-test",
"version": "0.1.23",
"version": "0.1.26",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,5 +1,30 @@
# @llamaindex/next-node-runtime
## 0.0.8
### Patch Changes
- 83ebdfb: fix: next.js build error
- Updated dependencies [83ebdfb]
- llamaindex@0.4.8
## 0.0.7
### Patch Changes
- Updated dependencies [41fe871]
- Updated dependencies [321c39d]
- Updated dependencies [f7f1af0]
- llamaindex@0.4.7
## 0.0.6
### Patch Changes
- Updated dependencies [1feb23b]
- Updated dependencies [08c55ec]
- llamaindex@0.4.6
## 0.0.5
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/next-node-runtime-test",
"version": "0.0.5",
"version": "0.0.8",
"private": true,
"scripts": {
"dev": "next dev",
@@ -0,0 +1,68 @@
"use server";
import {
OpenAI,
OpenAIAgent,
QueryEngineTool,
Settings,
VectorStoreIndex,
} from "llamaindex";
import { HuggingFaceEmbedding } from "llamaindex/embeddings/HuggingFaceEmbedding";
import { SimpleDirectoryReader } from "llamaindex/readers/SimpleDirectoryReader";
Settings.llm = new OpenAI({
// eslint-disable-next-line turbo/no-undeclared-env-vars
apiKey: process.env.NEXT_PUBLIC_OPENAI_KEY ?? "FAKE_KEY_TO_PASS_TESTS",
model: "gpt-4o",
});
Settings.embedModel = new HuggingFaceEmbedding({
modelType: "BAAI/bge-small-en-v1.5",
quantized: false,
});
Settings.callbackManager.on("llm-tool-call", (event) => {
console.log(event.detail.payload);
});
Settings.callbackManager.on("llm-tool-result", (event) => {
console.log(event.detail.payload);
});
export async function getOpenAIModelRequest(query: string) {
try {
const currentDir = __dirname;
// load our data and create a query engine
const reader = new SimpleDirectoryReader();
const documents = await reader.loadData(currentDir);
const index = await VectorStoreIndex.fromDocuments(documents);
const retriever = index.asRetriever({
similarityTopK: 10,
});
const queryEngine = index.asQueryEngine({
retriever,
});
// define the query engine as a tool
const tools = [
new QueryEngineTool({
queryEngine: queryEngine,
metadata: {
name: "deployment_details_per_env",
description: `This tool can answer detailed questions about deployments happened in various environments.`,
},
}),
];
// create the agent
const agent = new OpenAIAgent({ tools });
const { response } = await agent.chat({
message: query,
});
return {
message: response,
};
} catch (err) {
console.error(err);
return {
errors: "Error Calling OpenAI Model",
};
}
}
@@ -0,0 +1,10 @@
import { getOpenAIModelRequest } from "@/actions/openai";
import { NextRequest, NextResponse } from "next/server";
// POST /api/openai
export async function POST(request: NextRequest) {
const body = await request.json();
const content = await getOpenAIModelRequest(body.query);
return NextResponse.json(content, { status: 200 });
}
@@ -1,5 +1,29 @@
# @llamaindex/waku-query-engine-test
## 0.0.27
### Patch Changes
- Updated dependencies [83ebdfb]
- llamaindex@0.4.8
## 0.0.26
### Patch Changes
- Updated dependencies [41fe871]
- Updated dependencies [321c39d]
- Updated dependencies [f7f1af0]
- llamaindex@0.4.7
## 0.0.25
### Patch Changes
- Updated dependencies [1feb23b]
- Updated dependencies [08c55ec]
- llamaindex@0.4.6
## 0.0.24
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/waku-query-engine-test",
"version": "0.0.24",
"version": "0.0.27",
"type": "module",
"private": true,
"scripts": {
-11
View File
@@ -1,11 +0,0 @@
{
"name": "@llamaindex/llamaindex",
"version": "0.4.5",
"exports": "./src/index.ts",
"imports": {
"@llamaindex/env": "jsr:@llamaindex/env@0.1.6"
},
"publish": {
"include": ["LICENSE", "README.md", "src/**/*", "jsr.json"]
}
}
+9 -5
View File
@@ -1,6 +1,6 @@
{
"name": "llamaindex",
"version": "0.4.5",
"version": "0.4.8",
"license": "MIT",
"type": "module",
"keywords": [
@@ -22,17 +22,20 @@
"dependencies": {
"@anthropic-ai/sdk": "^0.21.1",
"@aws-crypto/sha256-js": "^5.2.0",
"@azure/identity": "^4.2.1",
"@datastax/astra-db-ts": "^1.2.1",
"@google-cloud/vertexai": "^1.2.0",
"@google/generative-ai": "^0.12.0",
"@grpc/grpc-js": "^1.10.8",
"@huggingface/inference": "^2.7.0",
"@llamaindex/cloud": "0.0.7",
"@llamaindex/cloud": "workspace:*",
"@llamaindex/core": "workspace:*",
"@llamaindex/env": "workspace:*",
"@mistralai/mistralai": "^0.4.0",
"@pinecone-database/pinecone": "^2.2.2",
"@qdrant/js-client-rest": "^1.9.0",
"@types/lodash": "^4.17.5",
"@types/lodash": "^4.17.4",
"@types/node": "^20.14.5",
"@types/papaparse": "^5.3.14",
"@types/pg": "^8.11.6",
"@xenova/transformers": "^2.17.2",
@@ -60,7 +63,8 @@
"tiktoken": "^1.0.15",
"unpdf": "^0.10.1",
"wikipedia": "^2.1.2",
"wink-nlp": "^2.3.0"
"wink-nlp": "^2.3.0",
"zod": "^3.23.8"
},
"peerDependencies": {
"@notionhq/client": "^2.2.15"
@@ -148,7 +152,7 @@
"repository": {
"type": "git",
"url": "https://github.com/run-llama/LlamaIndexTS.git",
"directory": "packages/core"
"directory": "packages/llamaindex"
},
"scripts": {
"lint": "eslint .",
+1 -1
View File
@@ -1,4 +1,4 @@
import type { NodeWithScore } from "./Node.js";
import type { NodeWithScore } from "@llamaindex/core/schema";
import type {
ChatMessage,
ChatResponse,
+5 -447
View File
@@ -1,448 +1,6 @@
import { createSHA256, path, randomUUID } from "@llamaindex/env";
import { chunkSizeCheck, lazyInitHash } from "./internal/decorator/node.js";
console.warn(
'Package "llamaindex/Node" is deprecated, and will be removed in the next major release.',
);
console.warn("Please import from the @llamaindex/core/schema package instead.");
export enum NodeRelationship {
SOURCE = "SOURCE",
PREVIOUS = "PREVIOUS",
NEXT = "NEXT",
PARENT = "PARENT",
CHILD = "CHILD",
}
export enum ObjectType {
TEXT = "TEXT",
IMAGE = "IMAGE",
INDEX = "INDEX",
DOCUMENT = "DOCUMENT",
IMAGE_DOCUMENT = "IMAGE_DOCUMENT",
}
export enum MetadataMode {
ALL = "ALL",
EMBED = "EMBED",
LLM = "LLM",
NONE = "NONE",
}
export type Metadata = Record<string, any>;
export interface RelatedNodeInfo<T extends Metadata = Metadata> {
nodeId: string;
nodeType?: ObjectType;
metadata: T;
hash?: string;
}
export type RelatedNodeType<T extends Metadata = Metadata> =
| RelatedNodeInfo<T>
| RelatedNodeInfo<T>[];
export type BaseNodeParams<T extends Metadata = Metadata> = {
id_?: string;
metadata?: T;
excludedEmbedMetadataKeys?: string[];
excludedLlmMetadataKeys?: string[];
relationships?: Partial<Record<NodeRelationship, RelatedNodeType<T>>>;
hash?: string;
embedding?: number[];
};
/**
* Generic abstract class for retrievable nodes
*/
export abstract class BaseNode<T extends Metadata = Metadata> {
/**
* The unique ID of the Node/Document. The trailing underscore is here
* to avoid collisions with the id keyword in Python.
*
* Set to a UUID by default.
*/
id_: string;
embedding?: number[];
// Metadata fields
metadata: T;
excludedEmbedMetadataKeys: string[];
excludedLlmMetadataKeys: string[];
relationships: Partial<Record<NodeRelationship, RelatedNodeType<T>>>;
@lazyInitHash
accessor hash: string = "";
protected constructor(init?: BaseNodeParams<T>) {
const {
id_,
metadata,
excludedEmbedMetadataKeys,
excludedLlmMetadataKeys,
relationships,
hash,
embedding,
} = init || {};
this.id_ = id_ ?? randomUUID();
this.metadata = metadata ?? ({} as T);
this.excludedEmbedMetadataKeys = excludedEmbedMetadataKeys ?? [];
this.excludedLlmMetadataKeys = excludedLlmMetadataKeys ?? [];
this.relationships = relationships ?? {};
this.embedding = embedding;
}
abstract get type(): ObjectType;
abstract getContent(metadataMode: MetadataMode): string;
abstract getMetadataStr(metadataMode: MetadataMode): string;
// todo: set value as a generic type
abstract setContent(value: unknown): void;
get sourceNode(): RelatedNodeInfo<T> | undefined {
const relationship = this.relationships[NodeRelationship.SOURCE];
if (Array.isArray(relationship)) {
throw new Error("Source object must be a single RelatedNodeInfo object");
}
return relationship;
}
get prevNode(): RelatedNodeInfo<T> | undefined {
const relationship = this.relationships[NodeRelationship.PREVIOUS];
if (Array.isArray(relationship)) {
throw new Error(
"Previous object must be a single RelatedNodeInfo object",
);
}
return relationship;
}
get nextNode(): RelatedNodeInfo<T> | undefined {
const relationship = this.relationships[NodeRelationship.NEXT];
if (Array.isArray(relationship)) {
throw new Error("Next object must be a single RelatedNodeInfo object");
}
return relationship;
}
get parentNode(): RelatedNodeInfo<T> | undefined {
const relationship = this.relationships[NodeRelationship.PARENT];
if (Array.isArray(relationship)) {
throw new Error("Parent object must be a single RelatedNodeInfo object");
}
return relationship;
}
get childNodes(): RelatedNodeInfo<T>[] | undefined {
const relationship = this.relationships[NodeRelationship.CHILD];
if (!Array.isArray(relationship)) {
throw new Error(
"Child object must be a an array of RelatedNodeInfo objects",
);
}
return relationship;
}
abstract generateHash(): string;
getEmbedding(): number[] {
if (this.embedding === undefined) {
throw new Error("Embedding not set");
}
return this.embedding;
}
asRelatedNodeInfo(): RelatedNodeInfo<T> {
return {
nodeId: this.id_,
metadata: this.metadata,
hash: this.hash,
};
}
/**
* Called by built in JSON.stringify (see https://javascript.info/json)
* Properties are read-only as they are not deep-cloned (not necessary for stringification).
* @see toMutableJSON - use to return a mutable JSON instead
*/
toJSON(): Record<string, any> {
return {
...this,
type: this.type,
// hash is an accessor property, so it's not included in the rest operator
hash: this.hash,
};
}
clone(): BaseNode {
return jsonToNode(this.toMutableJSON()) as BaseNode;
}
/**
* Converts the object to a JSON representation.
* Properties can be safely modified as a deep clone of the properties are created.
* @return {Record<string, any>} - The JSON representation of the object.
*/
toMutableJSON(): Record<string, any> {
return structuredClone(this.toJSON());
}
}
export type TextNodeParams<T extends Metadata = Metadata> =
BaseNodeParams<T> & {
text?: string;
textTemplate?: string;
startCharIdx?: number;
endCharIdx?: number;
metadataSeparator?: string;
};
/**
* TextNode is the default node type for text. Most common node type in LlamaIndex.TS
*/
export class TextNode<T extends Metadata = Metadata> extends BaseNode<T> {
text: string;
textTemplate: string;
startCharIdx?: number;
endCharIdx?: number;
// textTemplate: NOTE write your own formatter if needed
// metadataTemplate: NOTE write your own formatter if needed
metadataSeparator: string;
constructor(init: TextNodeParams<T> = {}) {
super(init);
const { text, textTemplate, startCharIdx, endCharIdx, metadataSeparator } =
init;
this.text = text ?? "";
this.textTemplate = textTemplate ?? "";
if (startCharIdx) {
this.startCharIdx = startCharIdx;
}
this.endCharIdx = endCharIdx;
this.metadataSeparator = metadataSeparator ?? "\n";
}
/**
* Generate a hash of the text node.
* The ID is not part of the hash as it can change independent of content.
* @returns
*/
generateHash() {
const hashFunction = createSHA256();
hashFunction.update(`type=${this.type}`);
hashFunction.update(
`startCharIdx=${this.startCharIdx} endCharIdx=${this.endCharIdx}`,
);
hashFunction.update(this.getContent(MetadataMode.ALL));
return hashFunction.digest();
}
get type() {
return ObjectType.TEXT;
}
@chunkSizeCheck
getContent(metadataMode: MetadataMode = MetadataMode.NONE): string {
const metadataStr = this.getMetadataStr(metadataMode).trim();
return `${metadataStr}\n\n${this.text}`.trim();
}
getMetadataStr(metadataMode: MetadataMode): string {
if (metadataMode === MetadataMode.NONE) {
return "";
}
const usableMetadataKeys = new Set(Object.keys(this.metadata).sort());
if (metadataMode === MetadataMode.LLM) {
for (const key of this.excludedLlmMetadataKeys) {
usableMetadataKeys.delete(key);
}
} else if (metadataMode === MetadataMode.EMBED) {
for (const key of this.excludedEmbedMetadataKeys) {
usableMetadataKeys.delete(key);
}
}
return [...usableMetadataKeys]
.map((key) => `${key}: ${this.metadata[key]}`)
.join(this.metadataSeparator);
}
setContent(value: string) {
this.text = value;
this.hash = this.generateHash();
}
getNodeInfo() {
return { start: this.startCharIdx, end: this.endCharIdx };
}
getText() {
return this.getContent(MetadataMode.NONE);
}
}
export type IndexNodeParams<T extends Metadata = Metadata> =
TextNodeParams<T> & {
indexId: string;
};
export class IndexNode<T extends Metadata = Metadata> extends TextNode<T> {
indexId: string;
constructor(init?: IndexNodeParams<T>) {
super(init);
const { indexId } = init || {};
this.indexId = indexId ?? "";
}
get type() {
return ObjectType.INDEX;
}
}
/**
* A document is just a special text node with a docId.
*/
export class Document<T extends Metadata = Metadata> extends TextNode<T> {
constructor(init?: TextNodeParams<T>) {
super(init);
}
get type() {
return ObjectType.DOCUMENT;
}
}
export function jsonToNode(json: any, type?: ObjectType) {
if (!json.type && !type) {
throw new Error("Node type not found");
}
const nodeType = type || json.type;
switch (nodeType) {
case ObjectType.TEXT:
return new TextNode(json);
case ObjectType.INDEX:
return new IndexNode(json);
case ObjectType.DOCUMENT:
return new Document(json);
case ObjectType.IMAGE_DOCUMENT:
return new ImageDocument(json);
default:
throw new Error(`Invalid node type: ${nodeType}`);
}
}
export type ImageType = string | Blob | URL;
export type ImageNodeParams<T extends Metadata = Metadata> =
TextNodeParams<T> & {
image: ImageType;
};
export class ImageNode<T extends Metadata = Metadata> extends TextNode<T> {
image: ImageType; // image as blob
constructor(init: ImageNodeParams<T>) {
super(init);
const { image } = init;
this.image = image;
}
get type() {
return ObjectType.IMAGE;
}
getUrl(): URL {
// id_ stores the relative path, convert it to the URL of the file
const absPath = path.resolve(this.id_);
return new URL(`file://${absPath}`);
}
// Calculates the image part of the hash
private generateImageHash() {
const hashFunction = createSHA256();
if (this.image instanceof Blob) {
// TODO: ideally we should use the blob's content to calculate the hash:
// hashFunction.update(new Uint8Array(await this.image.arrayBuffer()));
// as this is async, we're using the node's ID for the time being
hashFunction.update(this.id_);
} else if (this.image instanceof URL) {
hashFunction.update(this.image.toString());
} else if (typeof this.image === "string") {
hashFunction.update(this.image);
} else {
throw new Error(
`Unknown image type: ${typeof this.image}. Can't calculate hash`,
);
}
return hashFunction.digest();
}
generateHash() {
const hashFunction = createSHA256();
// calculates hash based on hash of both components (image and text)
hashFunction.update(super.generateHash());
hashFunction.update(this.generateImageHash());
return hashFunction.digest();
}
}
export class ImageDocument<T extends Metadata = Metadata> extends ImageNode<T> {
constructor(init: ImageNodeParams<T>) {
super(init);
}
get type() {
return ObjectType.IMAGE_DOCUMENT;
}
}
/**
* A node with a similarity score
*/
export interface NodeWithScore<T extends Metadata = Metadata> {
node: BaseNode<T>;
score?: number;
}
export enum ModalityType {
TEXT = "TEXT",
IMAGE = "IMAGE",
}
type NodesByType = {
[P in ModalityType]?: BaseNode[];
};
export function splitNodesByType(nodes: BaseNode[]): NodesByType {
const result: NodesByType = {};
for (const node of nodes) {
let type: ModalityType;
if (node instanceof ImageNode) {
type = ModalityType.IMAGE;
} else if (node instanceof TextNode) {
type = ModalityType.TEXT;
} else {
throw new Error(`Unknown node type: ${node.type}`);
}
if (type in result) {
result[type]?.push(node);
} else {
result[type] = [node];
}
}
return result;
}
export * from "@llamaindex/core/schema";
+1 -1
View File
@@ -1,4 +1,4 @@
import type { NodeWithScore } from "./Node.js";
import type { NodeWithScore } from "@llamaindex/core/schema";
import type { ServiceContext } from "./ServiceContext.js";
import type { MessageContent } from "./index.edge.js";
+4 -8
View File
@@ -1,3 +1,4 @@
import { Settings as CoreSettings } from "@llamaindex/core/global";
import { CallbackManager } from "./callbacks/CallbackManager.js";
import { OpenAI } from "./llm/openai.js";
@@ -17,11 +18,6 @@ import {
setEmbeddedModel,
withEmbeddedModel,
} from "./internal/settings/EmbedModel.js";
import {
getChunkSize,
setChunkSize,
withChunkSize,
} from "./internal/settings/chunk-size.js";
import type { LLM } from "./llm/types.js";
import type { NodeParser } from "./nodeParsers/types.js";
@@ -148,15 +144,15 @@ class GlobalSettings implements Config {
}
set chunkSize(chunkSize: number | undefined) {
setChunkSize(chunkSize);
CoreSettings.chunkSize = chunkSize;
}
get chunkSize(): number | undefined {
return getChunkSize();
return CoreSettings.chunkSize;
}
withChunkSize<Result>(chunkSize: number, fn: () => Result): Result {
return withChunkSize(chunkSize, fn);
return CoreSettings.withChunkSize(chunkSize, fn);
}
get chunkOverlap(): number | undefined {
+16 -6
View File
@@ -12,6 +12,7 @@ import { consoleLogger, emptyLogger } from "../internal/logger.js";
import { getCallbackManager } from "../internal/settings/CallbackManager.js";
import { isAsyncIterable } from "../internal/utils.js";
import type { ChatMessage, LLM, MessageContent } from "../llm/index.js";
import { ObjectRetriever } from "../objects/index.js";
import type { BaseToolWithCall, ToolOutput } from "../types.js";
import type {
AgentTaskContext,
@@ -126,12 +127,21 @@ export type AgentParamsBase<
>
? AdditionalMessageOptions
: never,
> = {
llm?: AI;
chatHistory?: ChatMessage<AdditionalMessageOptions>[];
systemPrompt?: MessageContent;
verbose?: boolean;
};
> =
| {
llm?: AI;
chatHistory?: ChatMessage<AdditionalMessageOptions>[];
systemPrompt?: MessageContent;
verbose?: boolean;
tools: BaseToolWithCall[];
}
| {
llm?: AI;
chatHistory?: ChatMessage<AdditionalMessageOptions>[];
systemPrompt?: MessageContent;
verbose?: boolean;
toolRetriever: ObjectRetriever<BaseToolWithCall>;
};
/**
* Worker will schedule tasks and handle the task execution
+2
View File
@@ -3,6 +3,7 @@ import { ObjectRetriever } from "../objects/index.js";
import { Settings } from "../Settings.js";
import type { BaseToolWithCall } from "../types.js";
import { AgentRunner, AgentWorker, type AgentParamsBase } from "./base.js";
import { validateAgentParams } from "./utils.js";
type LLMParamsBase = AgentParamsBase<LLM>;
@@ -22,6 +23,7 @@ export class LLMAgentWorker extends AgentWorker<LLM> {
export class LLMAgent extends AgentRunner<LLM> {
constructor(params: LLMAgentParams) {
validateAgentParams(params);
const llm = params.llm ?? (Settings.llm ? (Settings.llm as LLM) : null);
if (!llm)
throw new Error(
+5 -23
View File
@@ -11,35 +11,18 @@ import {
type LLM,
} from "../llm/index.js";
import { extractText } from "../llm/utils.js";
import { ObjectRetriever } from "../objects/index.js";
import { Settings } from "../Settings.js";
import type {
BaseTool,
BaseToolWithCall,
JSONObject,
JSONValue,
} from "../types.js";
import type { BaseTool, JSONObject, JSONValue } from "../types.js";
import { AgentRunner, AgentWorker, type AgentParamsBase } from "./base.js";
import type { TaskHandler } from "./types.js";
import {
callTool,
consumeAsyncIterable,
createReadableStream,
validateAgentParams,
} from "./utils.js";
type ReACTAgentParamsBase = AgentParamsBase<LLM>;
type ReACTAgentParamsWithTools = ReACTAgentParamsBase & {
tools: BaseToolWithCall[];
};
type ReACTAgentParamsWithToolRetriever = ReACTAgentParamsBase & {
toolRetriever: ObjectRetriever<BaseToolWithCall>;
};
export type ReACTAgentParams =
| ReACTAgentParamsWithTools
| ReACTAgentParamsWithToolRetriever;
export type ReACTAgentParams = AgentParamsBase<LLM>;
type BaseReason = {
type: unknown;
@@ -342,9 +325,8 @@ export class ReACTAgentWorker extends AgentWorker<LLM, ReACTAgentStore> {
}
export class ReActAgent extends AgentRunner<LLM, ReACTAgentStore> {
constructor(
params: ReACTAgentParamsWithTools | ReACTAgentParamsWithToolRetriever,
) {
constructor(params: ReACTAgentParams) {
validateAgentParams(params);
super({
llm: params.llm ?? Settings.llm,
chatHistory: params.chatHistory ?? [],
+22
View File
@@ -1,4 +1,6 @@
import { baseToolWithCallSchema } from "@llamaindex/core/schema";
import { ReadableStream } from "@llamaindex/env";
import { z } from "zod";
import type { Logger } from "../internal/logger.js";
import { getCallbackManager } from "../internal/settings/CallbackManager.js";
import {
@@ -17,6 +19,7 @@ import type {
ToolCallLLMMessageOptions,
} from "../llm/index.js";
import type { BaseTool, JSONObject, JSONValue, ToolOutput } from "../types.js";
import type { AgentParamsBase } from "./base.js";
import type { TaskHandler } from "./types.js";
type StepToolsResponseParams<Model extends LLM> = {
@@ -61,6 +64,7 @@ export async function stepToolsStreaming<Model extends LLM>({
// check if first chunk has tool calls, if so, this is a function call
// otherwise, it's a regular message
const hasToolCall = !!(value.options && "toolCall" in value.options);
enqueueOutput({
taskStep: step,
output: finalStream,
@@ -78,6 +82,14 @@ export async function stepToolsStreaming<Model extends LLM>({
});
}
}
// If there are toolCalls but they didn't get read into the stream, used for Gemini
if (!toolCalls.size && value.options && "toolCall" in value.options) {
value.options.toolCall.forEach((toolCall) => {
toolCalls.set(toolCall.id, toolCall);
});
}
step.context.store.messages = [
...step.context.store.messages,
{
@@ -288,3 +300,13 @@ export function createReadableStream<T>(
},
});
}
export function validateAgentParams<AI extends LLM>(
params: AgentParamsBase<AI>,
) {
if ("tools" in params) {
z.array(baseToolWithCallSchema).parse(params.tools);
} else {
// todo: check `params.toolRetriever` when migrate to @llamaindex/core
}
}
@@ -1,6 +1,6 @@
import type { Anthropic } from "@anthropic-ai/sdk";
import type { NodeWithScore } from "@llamaindex/core/schema";
import { CustomEvent } from "@llamaindex/env";
import type { NodeWithScore } from "../Node.js";
import type { AgentEndEvent, AgentStartEvent } from "../agent/types.js";
import {
EventCaller,
@@ -1,4 +1,4 @@
import type { Document } from "../Node.js";
import type { Document } from "@llamaindex/core/schema";
import type { BaseRetriever } from "../Retriever.js";
import { RetrieverQueryEngine } from "../engines/query/RetrieverQueryEngine.js";
import type { TransformComponent } from "../ingestion/types.js";
@@ -8,10 +8,12 @@ import type { QueryEngine } from "../types.js";
import type { CloudRetrieveParams } from "./LlamaCloudRetriever.js";
import { LlamaCloudRetriever } from "./LlamaCloudRetriever.js";
import { getPipelineCreate } from "./config.js";
import type { CloudConstructorParams } from "./types.js";
import { getAppBaseUrl, getClient } from "./utils.js";
import type { CloudConstructorParams } from "./constants.js";
import { getAppBaseUrl, initService } from "./utils.js";
import { PipelinesService, ProjectsService } from "@llamaindex/cloud/api";
import { getEnv } from "@llamaindex/env";
import { Settings } from "../Settings.js";
import { OpenAIEmbedding } from "../embeddings/OpenAIEmbedding.js";
import { SimpleNodeParser } from "../nodeParsers/SimpleNodeParser.js";
@@ -20,10 +22,11 @@ export class LlamaCloudIndex {
constructor(params: CloudConstructorParams) {
this.params = params;
initService(this.params);
}
private async waitForPipelineIngestion(
verbose = false,
verbose = Settings.debug,
raiseOnError = false,
): Promise<void> {
const pipelineId = await this.getPipelineId(
@@ -31,18 +34,17 @@ export class LlamaCloudIndex {
this.params.projectName,
);
const client = await getClient({
...this.params,
baseUrl: this.params.baseUrl,
});
if (verbose) {
console.log("Waiting for pipeline ingestion: ");
}
while (true) {
const pipelineStatus =
await client.pipelines.getPipelineStatus(pipelineId);
await PipelinesService.getPipelineStatusApiV1PipelinesPipelineIdStatusGet(
{
pipelineId,
},
);
if (pipelineStatus.status === "SUCCESS") {
if (verbose) {
@@ -71,7 +73,7 @@ export class LlamaCloudIndex {
private async waitForDocumentIngestion(
docIds: string[],
verbose = false,
verbose = Settings.debug,
raiseOnError = false,
): Promise<void> {
const pipelineId = await this.getPipelineId(
@@ -79,11 +81,6 @@ export class LlamaCloudIndex {
this.params.projectName,
);
const client = await getClient({
...this.params,
baseUrl: this.params.baseUrl,
});
if (verbose) {
console.log("Loading data: ");
}
@@ -94,10 +91,10 @@ export class LlamaCloudIndex {
const docsToRemove = new Set<string>();
for (const doc of pendingDocs) {
const { status } = await client.pipelines.getPipelineDocumentStatus(
pipelineId,
doc,
);
const { status } =
await PipelinesService.getPipelineDocumentStatusApiV1PipelinesPipelineIdDocumentsDocumentIdStatusGet(
{ pipelineId, documentId: doc },
);
if (status === "NOT_STARTED" || status === "IN_PROGRESS") {
continue;
@@ -140,12 +137,7 @@ export class LlamaCloudIndex {
name: string,
projectName: string,
): Promise<string> {
const client = await getClient({
...this.params,
baseUrl: this.params.baseUrl,
});
const pipelines = await client.pipelines.searchPipelines({
const pipelines = await PipelinesService.searchPipelinesApiV1PipelinesGet({
projectName,
pipelineName: name,
});
@@ -166,10 +158,7 @@ export class LlamaCloudIndex {
apiKey: getEnv("OPENAI_API_KEY"),
}),
];
const appUrl = getAppBaseUrl(params.baseUrl);
const client = await getClient({ ...params, baseUrl: appUrl });
const apiUrl = getAppBaseUrl();
const pipelineCreateParams = await getPipelineCreate({
pipelineName: params.name,
@@ -178,21 +167,23 @@ export class LlamaCloudIndex {
transformations: params.transformations ?? defaultTransformations,
});
const project = await client.projects.upsertProject({
name: params.projectName ?? "default",
const project = await ProjectsService.upsertProjectApiV1ProjectsPut({
requestBody: {
name: params.projectName ?? "default",
},
});
if (!project.id) {
throw new Error("Project ID should be defined");
}
const pipeline = await client.pipelines.upsertPipeline({
const pipeline = await PipelinesService.upsertPipelineApiV1PipelinesPut({
projectId: project.id,
body: {
requestBody: {
name: params.name,
configuredTransformations:
pipelineCreateParams.configuredTransformations,
pipelineType: pipelineCreateParams.pipelineType,
configured_transformations:
pipelineCreateParams.configured_transformations,
pipeline_type: pipelineCreateParams.pipeline_type,
},
});
@@ -204,21 +195,26 @@ export class LlamaCloudIndex {
console.log(`Created pipeline ${pipeline.id} with name ${params.name}`);
}
await client.pipelines.upsertBatchPipelineDocuments(
pipeline.id,
params.documents.map((doc) => ({
metadata: doc.metadata,
text: doc.text,
excludedEmbedMetadataKeys: doc.excludedLlmMetadataKeys,
excludedLlmMetadataKeys: doc.excludedEmbedMetadataKeys,
id: doc.id_,
})),
await PipelinesService.upsertBatchPipelineDocumentsApiV1PipelinesPipelineIdDocumentsPut(
{
pipelineId: pipeline.id,
requestBody: params.documents.map((doc) => ({
metadata: doc.metadata,
text: doc.text,
excluded_embed_metadata_keys: doc.excludedEmbedMetadataKeys,
excluded_llm_metadata_keys: doc.excludedEmbedMetadataKeys,
id: doc.id_,
})),
},
);
while (true) {
const pipelineStatus = await client.pipelines.getPipelineStatus(
pipeline.id,
);
const pipelineStatus =
await PipelinesService.getPipelineStatusApiV1PipelinesPipelineIdStatusGet(
{
pipelineId: pipeline.id,
},
);
if (pipelineStatus.status === "SUCCESS") {
console.info(
@@ -229,14 +225,14 @@ export class LlamaCloudIndex {
if (pipelineStatus.status === "ERROR") {
console.error(
`Some documents failed to ingest, check your pipeline logs at ${appUrl}/project/${project.id}/deploy/${pipeline.id}`,
`Some documents failed to ingest, check your pipeline logs at ${apiUrl}/project/${project.id}/deploy/${pipeline.id}`,
);
throw new Error("Some documents failed to ingest");
}
if (pipelineStatus.status === "PARTIAL_SUCCESS") {
console.info(
`Documents ingestion partially succeeded, to check a more complete status check your pipeline at ${appUrl}/project/${project.id}/deploy/${pipeline.id}`,
`Documents ingestion partially succeeded, to check a more complete status check your pipeline at ${apiUrl}/project/${project.id}/deploy/${pipeline.id}`,
);
break;
}
@@ -250,7 +246,7 @@ export class LlamaCloudIndex {
if (params.verbose) {
console.info(
`Ingestion completed, find your index at ${appUrl}/project/${project.id}/deploy/${pipeline.id}`,
`Ingestion completed, find your index at ${apiUrl}/project/${project.id}/deploy/${pipeline.id}`,
);
}
@@ -281,10 +277,6 @@ export class LlamaCloudIndex {
}
async insert(document: Document) {
const appUrl = getAppBaseUrl(this.params.baseUrl);
const client = await getClient({ ...this.params, baseUrl: appUrl });
const pipelineId = await this.getPipelineId(
this.params.name,
this.params.projectName,
@@ -294,24 +286,25 @@ export class LlamaCloudIndex {
throw new Error("We couldn't find the pipeline ID for the given name");
}
await client.pipelines.createBatchPipelineDocuments(pipelineId, [
await PipelinesService.createBatchPipelineDocumentsApiV1PipelinesPipelineIdDocumentsPost(
{
metadata: document.metadata,
text: document.text,
excludedEmbedMetadataKeys: document.excludedLlmMetadataKeys,
excludedLlmMetadataKeys: document.excludedEmbedMetadataKeys,
id: document.id_,
pipelineId: pipelineId,
requestBody: [
{
metadata: document.metadata,
text: document.text,
excluded_embed_metadata_keys: document.excludedLlmMetadataKeys,
excluded_llm_metadata_keys: document.excludedEmbedMetadataKeys,
id: document.id_,
},
],
},
]);
);
await this.waitForDocumentIngestion([document.id_]);
}
async delete(document: Document) {
const appUrl = getAppBaseUrl(this.params.baseUrl);
const client = await getClient({ ...this.params, baseUrl: appUrl });
const pipelineId = await this.getPipelineId(
this.params.name,
this.params.projectName,
@@ -321,16 +314,17 @@ export class LlamaCloudIndex {
throw new Error("We couldn't find the pipeline ID for the given name");
}
await client.pipelines.deletePipelineDocument(pipelineId, document.id_);
await PipelinesService.deletePipelineDocumentApiV1PipelinesPipelineIdDocumentsDocumentIdDelete(
{
pipelineId,
documentId: document.id_,
},
);
await this.waitForPipelineIngestion();
}
async refreshDoc(document: Document) {
const appUrl = getAppBaseUrl(this.params.baseUrl);
const client = await getClient({ ...this.params, baseUrl: appUrl });
const pipelineId = await this.getPipelineId(
this.params.name,
this.params.projectName,
@@ -340,15 +334,20 @@ export class LlamaCloudIndex {
throw new Error("We couldn't find the pipeline ID for the given name");
}
await client.pipelines.upsertBatchPipelineDocuments(pipelineId, [
await PipelinesService.upsertBatchPipelineDocumentsApiV1PipelinesPipelineIdDocumentsPut(
{
metadata: document.metadata,
text: document.text,
excludedEmbedMetadataKeys: document.excludedLlmMetadataKeys,
excludedLlmMetadataKeys: document.excludedEmbedMetadataKeys,
id: document.id_,
pipelineId,
requestBody: [
{
metadata: document.metadata,
text: document.text,
excluded_embed_metadata_keys: document.excludedLlmMetadataKeys,
excluded_llm_metadata_keys: document.excludedEmbedMetadataKeys,
id: document.id_,
},
],
},
]);
);
await this.waitForDocumentIngestion([document.id_]);
}
@@ -1,30 +1,33 @@
import type { LlamaCloudApi, LlamaCloudApiClient } from "@llamaindex/cloud";
import type { NodeWithScore } from "../Node.js";
import { ObjectType, jsonToNode } from "../Node.js";
import {
type MetadataFilters,
PipelinesService,
type RetrievalParams,
type TextNodeWithScore,
} from "@llamaindex/cloud/api";
import type { NodeWithScore } from "@llamaindex/core/schema";
import { jsonToNode, ObjectType } from "@llamaindex/core/schema";
import type { BaseRetriever, RetrieveParams } from "../Retriever.js";
import { wrapEventCaller } from "../internal/context/EventCaller.js";
import { getCallbackManager } from "../internal/settings/CallbackManager.js";
import { extractText } from "../llm/utils.js";
import type { ClientParams, CloudConstructorParams } from "./types.js";
import { DEFAULT_PROJECT_NAME } from "./types.js";
import { getClient } from "./utils.js";
import type { ClientParams, CloudConstructorParams } from "./constants.js";
import { DEFAULT_PROJECT_NAME } from "./constants.js";
import { initService } from "./utils.js";
export type CloudRetrieveParams = Omit<
LlamaCloudApi.RetrievalParams,
RetrievalParams,
"query" | "searchFilters" | "className" | "denseSimilarityTopK"
> & { similarityTopK?: number };
export class LlamaCloudRetriever implements BaseRetriever {
client?: LlamaCloudApiClient;
clientParams: ClientParams;
retrieveParams: CloudRetrieveParams;
projectName: string = DEFAULT_PROJECT_NAME;
pipelineName: string;
private resultNodesToNodeWithScore(
nodes: LlamaCloudApi.TextNodeWithScore[],
nodes: TextNodeWithScore[],
): NodeWithScore[] {
return nodes.map((node: LlamaCloudApi.TextNodeWithScore) => {
return nodes.map((node: TextNodeWithScore) => {
return {
// Currently LlamaCloud only supports text nodes
node: jsonToNode(node.node, ObjectType.TEXT),
@@ -35,6 +38,7 @@ export class LlamaCloudRetriever implements BaseRetriever {
constructor(params: CloudConstructorParams & CloudRetrieveParams) {
this.clientParams = { apiKey: params.apiKey, baseUrl: params.baseUrl };
initService(this.clientParams);
this.retrieveParams = params;
this.pipelineName = params.name;
if (params.projectName) {
@@ -42,32 +46,26 @@ export class LlamaCloudRetriever implements BaseRetriever {
}
}
private async getClient(): Promise<LlamaCloudApiClient> {
if (!this.client) {
this.client = await getClient(this.clientParams);
}
return this.client;
}
@wrapEventCaller
async retrieve({
query,
preFilters,
}: RetrieveParams): Promise<NodeWithScore[]> {
const client = await this.getClient();
const pipelines = await client?.pipelines.searchPipelines({
const pipelines = await PipelinesService.searchPipelinesApiV1PipelinesGet({
projectName: this.projectName,
pipelineName: this.pipelineName,
});
if (!pipelines) {
if (pipelines.length === 0 || !pipelines[0].id) {
throw new Error(
`No pipeline found with name ${this.pipelineName} in project ${this.projectName}`,
);
}
const pipeline = await client?.pipelines.getPipeline(pipelines[0].id);
const pipeline =
await PipelinesService.getPipelineApiV1PipelinesPipelineIdGet({
pipelineId: pipelines[0].id,
});
if (!pipeline) {
throw new Error(
@@ -75,19 +73,16 @@ export class LlamaCloudRetriever implements BaseRetriever {
);
}
const results = await client?.pipelines.runSearch(pipeline.id, {
...this.retrieveParams,
query: extractText(query),
searchFilters: preFilters as LlamaCloudApi.MetadataFilters,
});
const results =
await PipelinesService.runSearchApiV1PipelinesPipelineIdRetrievePost({
pipelineId: pipeline.id,
requestBody: {
...this.retrieveParams,
query: extractText(query),
search_filters: preFilters as MetadataFilters,
},
});
const nodes = this.resultNodesToNodeWithScore(results.retrievalNodes);
getCallbackManager().dispatchEvent("retrieve", {
query,
nodes,
});
return nodes;
return this.resultNodesToNodeWithScore(results.retrieval_nodes);
}
}
+13 -11
View File
@@ -1,24 +1,27 @@
import { LlamaCloudApi } from "@llamaindex/cloud";
import { BaseNode } from "../Node.js";
import type {
ConfiguredTransformationItem,
PipelineCreate,
PipelineType,
} from "@llamaindex/cloud/api";
import { BaseNode } from "@llamaindex/core/schema";
import { OpenAIEmbedding } from "../embeddings/OpenAIEmbedding.js";
import type { TransformComponent } from "../ingestion/types.js";
import { SimpleNodeParser } from "../nodeParsers/SimpleNodeParser.js";
export type GetPipelineCreateParams = {
pipelineName: string;
pipelineType: any; // TODO: PlatformApi.PipelineType is not exported
pipelineType: PipelineType;
transformations?: TransformComponent[];
inputNodes?: BaseNode[];
};
function getTransformationConfig(
transformation: TransformComponent,
): LlamaCloudApi.ConfiguredTransformationItem {
): ConfiguredTransformationItem {
if (transformation instanceof SimpleNodeParser) {
return {
configurableTransformationType: "SENTENCE_AWARE_NODE_PARSER",
configurable_transformation_type: "SENTENCE_AWARE_NODE_PARSER",
component: {
// TODO: API doesnt accept camelCase
chunk_size: transformation.textSplitter.chunkSize, // TODO: set to public in SentenceSplitter
chunk_overlap: transformation.textSplitter.chunkOverlap, // TODO: set to public in SentenceSplitter
include_metadata: transformation.includeMetadata,
@@ -28,9 +31,8 @@ function getTransformationConfig(
}
if (transformation instanceof OpenAIEmbedding) {
return {
configurableTransformationType: "OPENAI_EMBEDDING",
configurable_transformation_type: "OPENAI_EMBEDDING",
component: {
// TODO: API doesnt accept camelCase
model: transformation.model,
api_key: transformation.apiKey,
embed_batch_size: transformation.embedBatchSize,
@@ -43,12 +45,12 @@ function getTransformationConfig(
export async function getPipelineCreate(
params: GetPipelineCreateParams,
): Promise<LlamaCloudApi.PipelineCreate> {
): Promise<PipelineCreate> {
const { pipelineName, pipelineType, transformations = [] } = params;
return {
name: pipelineName,
configuredTransformations: transformations.map(getTransformationConfig),
pipelineType: pipelineType,
configured_transformations: transformations.map(getTransformationConfig),
pipeline_type: pipelineType,
};
}
@@ -1,6 +1,5 @@
import type { ServiceContext } from "../ServiceContext.js";
export const DEFAULT_PIPELINE_NAME = "default";
export const DEFAULT_PROJECT_NAME = "Default";
export const DEFAULT_BASE_URL = "https://api.cloud.llamaindex.ai";
+1 -1
View File
@@ -1,6 +1,6 @@
export type { CloudConstructorParams } from "./constants.js";
export { LlamaCloudIndex } from "./LlamaCloudIndex.js";
export {
LlamaCloudRetriever,
type CloudRetrieveParams,
} from "./LlamaCloudRetriever.js";
export type { CloudConstructorParams } from "./types.js";
+9 -23
View File
@@ -1,36 +1,22 @@
import type { LlamaCloudApiClient } from "@llamaindex/cloud";
import { OpenAPI } from "@llamaindex/cloud/api";
import { getEnv } from "@llamaindex/env";
import type { ClientParams } from "./types.js";
import { DEFAULT_BASE_URL } from "./types.js";
import type { ClientParams } from "./constants.js";
import { DEFAULT_BASE_URL } from "./constants.js";
function getBaseUrl(baseUrl?: string): string {
return baseUrl ?? getEnv("LLAMA_CLOUD_BASE_URL") ?? DEFAULT_BASE_URL;
}
export function getAppBaseUrl(baseUrl?: string): string {
return getBaseUrl(baseUrl).replace(/api\./, "");
export function getAppBaseUrl(): string {
return OpenAPI.BASE.replace(/api\./, "");
}
export async function getClient({
apiKey,
baseUrl,
}: ClientParams = {}): Promise<LlamaCloudApiClient> {
const { LlamaCloudApiClient } = await import("@llamaindex/cloud");
// Get the environment variables or use defaults
baseUrl = getBaseUrl(baseUrl);
apiKey = apiKey ?? getEnv("LLAMA_CLOUD_API_KEY");
if (!apiKey) {
export function initService({ apiKey, baseUrl }: ClientParams = {}) {
OpenAPI.TOKEN = apiKey ?? getEnv("LLAMA_CLOUD_API_KEY");
OpenAPI.BASE = getBaseUrl(baseUrl);
if (!OpenAPI.TOKEN) {
throw new Error(
"API Key is required for LlamaCloudIndex. Please pass the apiKey parameter",
);
}
const client = new LlamaCloudApiClient({
token: apiKey,
environment: baseUrl,
});
return client;
}
@@ -1,5 +1,5 @@
import type { ImageType } from "@llamaindex/core/schema";
import _ from "lodash";
import type { ImageType } from "../Node.js";
import { lazyLoadTransformers } from "../internal/deps/transformers.js";
import { MultiModalEmbedding } from "./MultiModalEmbedding.js";
// only import type, to avoid bundling error
@@ -1,4 +1,4 @@
import type { ImageType } from "../Node.js";
import type { ImageType } from "@llamaindex/core/schema";
import { MultiModalEmbedding } from "./MultiModalEmbedding.js";
/**
@@ -5,7 +5,7 @@ import {
splitNodesByType,
type BaseNode,
type ImageType,
} from "../Node.js";
} from "@llamaindex/core/schema";
import type { MessageContentDetail } from "../llm/types.js";
import { extractImage, extractSingleText } from "../llm/utils.js";
import { BaseEmbedding, batchEmbeddings } from "./types.js";
+2 -2
View File
@@ -1,6 +1,6 @@
import type { BaseNode } from "@llamaindex/core/schema";
import { MetadataMode } from "@llamaindex/core/schema";
import { type Tokenizers } from "@llamaindex/env";
import type { BaseNode } from "../Node.js";
import { MetadataMode } from "../Node.js";
import type { TransformComponent } from "../ingestion/types.js";
import type { MessageContentDetail } from "../llm/types.js";
import { extractSingleText } from "../llm/utils.js";
+1 -1
View File
@@ -1,7 +1,7 @@
import type { ImageType } from "@llamaindex/core/schema";
import { fs } from "@llamaindex/env";
import _ from "lodash";
import { filetypemime } from "magic-bytes.js";
import type { ImageType } from "../Node.js";
import { DEFAULT_SIMILARITY_TOP_K } from "../constants.js";
import type { VectorStoreQueryMode } from "../storage/vectorStore/types.js";
@@ -1,4 +1,4 @@
import { type NodeWithScore } from "../../Node.js";
import { type NodeWithScore } from "@llamaindex/core/schema";
import type { ContextSystemPrompt } from "../../Prompt.js";
import { defaultContextSystemPrompt } from "../../Prompt.js";
import type { BaseRetriever } from "../../Retriever.js";
@@ -1,6 +1,6 @@
import type { NodeWithScore } from "@llamaindex/core/schema";
import type { ChatHistory } from "../../ChatHistory.js";
import type { EngineResponse } from "../../EngineResponse.js";
import type { NodeWithScore } from "../../Node.js";
import type { ChatMessage } from "../../llm/index.js";
import type { MessageContent } from "../../llm/types.js";
@@ -1,5 +1,5 @@
import type { NodeWithScore } from "@llamaindex/core/schema";
import type { EngineResponse } from "../../EngineResponse.js";
import type { NodeWithScore } from "../../Node.js";
import type { BaseRetriever } from "../../Retriever.js";
import { wrapEventCaller } from "../../internal/context/EventCaller.js";
import type { BaseNodePostprocessor } from "../../postprocessors/index.js";
@@ -1,5 +1,5 @@
import type { NodeWithScore } from "@llamaindex/core/schema";
import { EngineResponse } from "../../EngineResponse.js";
import type { NodeWithScore } from "../../Node.js";
import type { ServiceContext } from "../../ServiceContext.js";
import { llmFromSettingsOrContext } from "../../Settings.js";
import { PromptMixin } from "../../prompts/index.js";
@@ -1,6 +1,6 @@
import type { NodeWithScore } from "@llamaindex/core/schema";
import { TextNode } from "@llamaindex/core/schema";
import type { EngineResponse } from "../../EngineResponse.js";
import type { NodeWithScore } from "../../Node.js";
import { TextNode } from "../../Node.js";
import { LLMQuestionGenerator } from "../../QuestionGenerator.js";
import type { ServiceContext } from "../../ServiceContext.js";
import { PromptMixin } from "../../prompts/Mixin.js";

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