mirror of
https://github.com/run-llama/LlamaIndexTS.git
synced 2026-07-16 07:14:29 -04:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 216ba1f22b | |||
| 74686f5776 | |||
| 1ebf9e67a4 | |||
| aeefc77da0 | |||
| 13d8d7cbbe | |||
| 9c34e44b85 | |||
| cb2dc802d9 | |||
| 5a6cc0e32e | |||
| a63256eb84 | |||
| 0a160b97a0 | |||
| 95602c7959 | |||
| 20bc466ca1 | |||
| efb1c56ba5 | |||
| 286499388d |
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"llamaindex": patch
|
||||
"@llamaindex/edge": patch
|
||||
---
|
||||
|
||||
refactor: use ollama official sdk
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"llamaindex": patch
|
||||
"@llamaindex/edge": patch
|
||||
---
|
||||
|
||||
feat: support output to json format
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v3
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v3
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
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: Add auth token to .npmrc file
|
||||
run: |
|
||||
cat << EOF >> ".npmrc"
|
||||
//registry.npmjs.org/:_authToken=$NPM_TOKEN
|
||||
EOF
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
- name: Get changeset status
|
||||
id: get-changeset-status
|
||||
run: |
|
||||
pnpm changeset status --output .changeset/status.json
|
||||
new_version=$(jq -r '.releases[] | select(.name == "llamaindex") | .newVersion' < .changeset/status.json)
|
||||
rm -v .changeset/status.json
|
||||
echo "new-version=${new_version}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Create Release Pull Request or Publish to npm
|
||||
id: changesets
|
||||
uses: changesets/action@v1
|
||||
with:
|
||||
commit: Release ${{ steps.get-changeset-status.outputs.new-version }}
|
||||
title: Release ${{ steps.get-changeset-status.outputs.new-version }}
|
||||
# update version PR with the latest changesets
|
||||
version: pnpm new-version
|
||||
# build package and call changeset publish
|
||||
publish: pnpm release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
@@ -17,16 +17,18 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version: [18.x, 20.x, 21.x]
|
||||
node-version: [18.x, 20.x, 22.x]
|
||||
name: E2E on Node.js ${{ matrix.node-version }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
|
||||
- uses: pnpm/action-setup@v3
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: "pnpm"
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
@@ -37,13 +39,13 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version: [18.x, 20.x, 21.x]
|
||||
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@v2
|
||||
- uses: pnpm/action-setup@v3
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
@@ -58,7 +60,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v3
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
@@ -87,7 +89,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v3
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
@@ -105,7 +107,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v3
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
|
||||
+5
-11
@@ -91,16 +91,10 @@ Please send a descriptive changeset for each PR.
|
||||
|
||||
## Publishing (maintainers only)
|
||||
|
||||
To publish a new version of the library, first create a new version:
|
||||
The [Release Github Action](.github/workflows/release.yml) is automatically generating and updating a
|
||||
PR called "Release {version}".
|
||||
|
||||
```shell
|
||||
pnpm new-version
|
||||
```
|
||||
This PR will update the `package.json` and `CHANGELOG.md` files of each package according to
|
||||
the current changesets in the [.changeset](.changeset/) folder.
|
||||
|
||||
If everything looks good, commit the generated files and release the new version:
|
||||
|
||||
```shell
|
||||
pnpm release
|
||||
git push # push to the main branch
|
||||
git push --tags
|
||||
```
|
||||
If this PR is merged it will automatically add version tags to the repository and publish the updated packages to NPM.
|
||||
|
||||
@@ -114,14 +114,21 @@ Add the following config to your `next.config.js` to ignore specific packages in
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
experimental: {
|
||||
serverComponentsExternalPackages: ["pdf2json", "@zilliz/milvus2-sdk-node"],
|
||||
serverComponentsExternalPackages: [
|
||||
"pdf2json",
|
||||
"@zilliz/milvus2-sdk-node",
|
||||
"sharp",
|
||||
"onnxruntime-node",
|
||||
],
|
||||
},
|
||||
webpack: (config) => {
|
||||
config.resolve.alias = {
|
||||
...config.resolve.alias,
|
||||
sharp$: false,
|
||||
"onnxruntime-node$": false,
|
||||
};
|
||||
config.externals.push({
|
||||
pdf2json: "commonjs pdf2json",
|
||||
"@zilliz/milvus2-sdk-node": "commonjs @zilliz/milvus2-sdk-node",
|
||||
sharp: "commonjs sharp",
|
||||
"onnxruntime-node": "commonjs onnxruntime-node",
|
||||
});
|
||||
|
||||
return config;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# docs
|
||||
|
||||
## 0.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [87142b2]
|
||||
- Updated dependencies [5a6cc0e]
|
||||
- Updated dependencies [87142b2]
|
||||
- llamaindex@0.2.11
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# Jina AI
|
||||
|
||||
To use Jina AI embeddings, you need to import `JinaAIEmbedding` from `llamaindex`.
|
||||
|
||||
```ts
|
||||
import { JinaAIEmbedding, Settings } from "llamaindex";
|
||||
|
||||
Settings.embedModel = new JinaAIEmbedding();
|
||||
|
||||
const document = new Document({ text: essay, id_: "essay" });
|
||||
|
||||
const index = await VectorStoreIndex.fromDocuments([document]);
|
||||
|
||||
const queryEngine = index.asQueryEngine();
|
||||
|
||||
const query = "What is the meaning of life?";
|
||||
|
||||
const results = await queryEngine.query({
|
||||
query,
|
||||
});
|
||||
```
|
||||
@@ -0,0 +1,71 @@
|
||||
# Jina AI Reranker
|
||||
|
||||
The Jina AI Reranker is a postprocessor that uses the Jina AI Reranker API to rerank the results of a search query.
|
||||
|
||||
## Setup
|
||||
|
||||
Firstly, you will need to install the `llamaindex` package.
|
||||
|
||||
```bash
|
||||
pnpm install llamaindex
|
||||
```
|
||||
|
||||
Now, you will need to sign up for an API key at [Jina AI](https://jina.ai/reranker). Once you have your API key you can import the necessary modules and create a new instance of the `JinaAIReranker` class.
|
||||
|
||||
```ts
|
||||
import {
|
||||
JinaAIReranker,
|
||||
Document,
|
||||
OpenAI,
|
||||
VectorStoreIndex,
|
||||
Settings,
|
||||
} from "llamaindex";
|
||||
```
|
||||
|
||||
## Load and index documents
|
||||
|
||||
For this example, we will use a single document. In a real-world scenario, you would have multiple documents to index.
|
||||
|
||||
```ts
|
||||
const document = new Document({ text: essay, id_: "essay" });
|
||||
|
||||
Settings.llm = new OpenAI({ model: "gpt-3.5-turbo", temperature: 0.1 });
|
||||
|
||||
const index = await VectorStoreIndex.fromDocuments([document]);
|
||||
```
|
||||
|
||||
## Increase similarity topK to retrieve more results
|
||||
|
||||
The default value for `similarityTopK` is 2. This means that only the most similar document will be returned. To retrieve more results, you can increase the value of `similarityTopK`.
|
||||
|
||||
```ts
|
||||
const retriever = index.asRetriever();
|
||||
retriever.similarityTopK = 5;
|
||||
```
|
||||
|
||||
## Create a new instance of the JinaAIReranker class
|
||||
|
||||
Then you can create a new instance of the `JinaAIReranker` class and pass in the number of results you want to return.
|
||||
The Jina AI Reranker API key is set in the `JINAAI_API_KEY` environment variable.
|
||||
|
||||
```bash
|
||||
export JINAAI_API_KEY=<YOUR API KEY>
|
||||
```
|
||||
|
||||
```ts
|
||||
const nodePostprocessor = new JinaAIReranker({
|
||||
topN: 5,
|
||||
});
|
||||
```
|
||||
|
||||
## Create a query engine with the retriever and node postprocessor
|
||||
|
||||
```ts
|
||||
const queryEngine = index.asQueryEngine({
|
||||
retriever,
|
||||
nodePostprocessors: [nodePostprocessor],
|
||||
});
|
||||
|
||||
// log the response
|
||||
const response = await queryEngine.query("Where did the author grown up?");
|
||||
```
|
||||
@@ -163,7 +163,7 @@ const config = {
|
||||
"docusaurus-plugin-typedoc",
|
||||
{
|
||||
entryPoints: ["../../packages/core/src/index.ts"],
|
||||
tsconfig: "../../packages/core/tsconfig.json",
|
||||
tsconfig: "../../tsconfig.json",
|
||||
readme: "none",
|
||||
sourceLinkTemplate:
|
||||
"https://github.com/run-llama/LlamaIndexTS/blob/{gitRevision}/{path}#L{line}",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docs",
|
||||
"version": "0.0.4",
|
||||
"version": "0.0.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
@@ -20,6 +20,7 @@
|
||||
"@llamaindex/examples": "workspace:*",
|
||||
"@mdx-js/react": "^3.0.1",
|
||||
"clsx": "^2.1.0",
|
||||
"llamaindex": "workspace:*",
|
||||
"postcss": "^8.4.38",
|
||||
"prism-react-renderer": "^2.3.1",
|
||||
"raw-loader": "^4.0.2",
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
import * as fs from "fs";
|
||||
import { ClipEmbedding, similarity, SimilarityType } from "llamaindex";
|
||||
|
||||
async function loadImageFromDisk(path: string) {
|
||||
try {
|
||||
const file = fs.readFileSync(path);
|
||||
return new Blob([file]);
|
||||
} catch (error) {
|
||||
console.error(`Error loading image from disk: ${error}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const clip = new ClipEmbedding();
|
||||
|
||||
@@ -23,8 +12,7 @@ async function main() {
|
||||
// Get image embedding
|
||||
const image =
|
||||
"https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/football-match.jpg";
|
||||
const blobImage = await loadImageFromDisk("./data/football-match.jpg");
|
||||
const imageEmbedding = await clip.getImageEmbedding(blobImage || image);
|
||||
const imageEmbedding = await clip.getImageEmbedding(image);
|
||||
|
||||
// Calc similarity
|
||||
const sim1 = similarity(
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 54 KiB |
@@ -4,7 +4,6 @@ import {
|
||||
VectorStoreIndex,
|
||||
storageContextFromDefaults,
|
||||
} from "llamaindex";
|
||||
import { DocStoreStrategy } from "llamaindex/ingestion/strategies/index";
|
||||
|
||||
import * as path from "path";
|
||||
|
||||
@@ -32,7 +31,6 @@ async function generateDatasource() {
|
||||
});
|
||||
await VectorStoreIndex.fromDocuments(documents, {
|
||||
storageContext,
|
||||
docStoreStrategy: DocStoreStrategy.NONE,
|
||||
});
|
||||
});
|
||||
console.log(`Storage successfully generated in ${ms / 1000}s.`);
|
||||
|
||||
@@ -3,20 +3,21 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "node --loader ts-node/esm ./src/simple-directory-reader.ts",
|
||||
"start:csv": "node --loader ts-node/esm ./src/csv.ts",
|
||||
"start:docx": "node --loader ts-node/esm ./src/docx.ts",
|
||||
"start:html": "node --loader ts-node/esm ./src/html.ts",
|
||||
"start:markdown": "node --loader ts-node/esm ./src/markdown.ts",
|
||||
"start:pdf": "node --loader ts-node/esm ./src/pdf.ts",
|
||||
"start:llamaparse": "node --loader ts-node/esm ./src/llamaparse.ts"
|
||||
"start": "node --import tsx ./src/simple-directory-reader.ts",
|
||||
"start:csv": "node --import tsx ./src/csv.ts",
|
||||
"start:docx": "node --import tsx ./src/docx.ts",
|
||||
"start:html": "node --import tsx ./src/html.ts",
|
||||
"start:markdown": "node --import tsx ./src/markdown.ts",
|
||||
"start:pdf": "node --import tsx ./src/pdf.ts",
|
||||
"start:llamaparse": "node --import tsx ./src/llamaparse.ts",
|
||||
"start:notion": "node --import tsx ./src/notion.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"llamaindex": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.12.7",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.3"
|
||||
"tsx": "^4.7.2",
|
||||
"typescript": "^5.4.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { createInterface } from "node:readline/promises";
|
||||
|
||||
program
|
||||
.argument("[page]", "Notion page id (must be provided)")
|
||||
.action(async (page, _options, command) => {
|
||||
.action(async (page, _options) => {
|
||||
// Initializing a client
|
||||
|
||||
if (!process.env.NOTION_TOKEN) {
|
||||
@@ -55,7 +55,7 @@ program
|
||||
.filter((page) => page !== null);
|
||||
console.log("Found pages:");
|
||||
console.table(pages);
|
||||
console.log(`To run, run ts-node ${command.name()} [page id]`);
|
||||
console.log(`To run, run with [page id]`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# llamaindex
|
||||
|
||||
## 0.2.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 87142b2: refactor: use ollama official sdk
|
||||
- 5a6cc0e: feat: support jina ai embedding and reranker
|
||||
- 87142b2: feat: support output to json format
|
||||
|
||||
## 0.2.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -2,7 +2,7 @@ import { consola } from "consola";
|
||||
import { Anthropic, FunctionTool, Settings, type LLM } from "llamaindex";
|
||||
import { AnthropicAgent } from "llamaindex/agent/anthropic";
|
||||
import { extractText } from "llamaindex/llm/utils";
|
||||
import { ok } from "node:assert";
|
||||
import { ok, strictEqual } from "node:assert";
|
||||
import { beforeEach, test } from "node:test";
|
||||
import { sumNumbersTool } from "./fixtures/tools.js";
|
||||
import { mockLLMEvent } from "./utils.js";
|
||||
@@ -71,10 +71,12 @@ await test("anthropic agent", async (t) => {
|
||||
},
|
||||
],
|
||||
});
|
||||
const { response } = await agent.chat({
|
||||
const { response, sources } = await agent.chat({
|
||||
message: "What is the weather in San Francisco?",
|
||||
});
|
||||
consola.debug("response:", response.message.content);
|
||||
|
||||
strictEqual(sources.length, 1);
|
||||
ok(extractText(response.message.content).includes("35"));
|
||||
});
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
SummaryIndex,
|
||||
VectorStoreIndex,
|
||||
type LLM,
|
||||
type ToolOutput,
|
||||
} from "llamaindex";
|
||||
import { extractText } from "llamaindex/llm/utils";
|
||||
import { ok, strictEqual } from "node:assert";
|
||||
@@ -222,10 +223,12 @@ await test("agent with object function call", async (t) => {
|
||||
),
|
||||
],
|
||||
});
|
||||
const { response } = await agent.chat({
|
||||
const { response, sources } = await agent.chat({
|
||||
message: "What is the weather in San Francisco?",
|
||||
});
|
||||
consola.debug("response:", response.message.content);
|
||||
|
||||
strictEqual(sources.length, 1);
|
||||
ok(extractText(response.message.content).includes("72"));
|
||||
});
|
||||
});
|
||||
@@ -253,10 +256,12 @@ await test("agent", async (t) => {
|
||||
},
|
||||
],
|
||||
});
|
||||
const { response } = await agent.chat({
|
||||
const { response, sources } = await agent.chat({
|
||||
message: "What is the weather in San Francisco?",
|
||||
});
|
||||
consola.debug("response:", response.message.content);
|
||||
|
||||
strictEqual(sources.length, 1);
|
||||
ok(extractText(response.message.content).includes("35"));
|
||||
});
|
||||
|
||||
@@ -290,9 +295,10 @@ await test("agent", async (t) => {
|
||||
const agent = new OpenAIAgent({
|
||||
tools: [showUniqueId],
|
||||
});
|
||||
const { response } = await agent.chat({
|
||||
const { response, sources } = await agent.chat({
|
||||
message: "My name is Alex Yang. What is my unique id?",
|
||||
});
|
||||
strictEqual(sources.length, 1);
|
||||
ok(extractText(response.message.content).includes(uniqueId));
|
||||
});
|
||||
|
||||
@@ -301,10 +307,11 @@ await test("agent", async (t) => {
|
||||
tools: [sumNumbersTool],
|
||||
});
|
||||
|
||||
const { response } = await openaiAgent.chat({
|
||||
const { response, sources } = await openaiAgent.chat({
|
||||
message: "how much is 1 + 1?",
|
||||
});
|
||||
|
||||
strictEqual(sources.length, 1);
|
||||
ok(extractText(response.message.content).includes("2"));
|
||||
});
|
||||
});
|
||||
@@ -319,18 +326,21 @@ await test("agent stream", async (t) => {
|
||||
tools: [sumNumbersTool, divideNumbersTool],
|
||||
});
|
||||
|
||||
const { response } = await agent.chat({
|
||||
const stream = await agent.chat({
|
||||
message: "Divide 16 by 2 then add 20",
|
||||
stream: true,
|
||||
});
|
||||
|
||||
let message = "";
|
||||
let soruces: ToolOutput[] = [];
|
||||
|
||||
for await (const chunk of response) {
|
||||
message += chunk.delta;
|
||||
for await (const { response, sources: _sources } of stream) {
|
||||
message += response.delta;
|
||||
soruces = _sources;
|
||||
}
|
||||
|
||||
strictEqual(fn.mock.callCount(), 2);
|
||||
strictEqual(soruces.length, 2);
|
||||
ok(message.includes("28"));
|
||||
Settings.callbackManager.off("llm-tool-call", fn);
|
||||
});
|
||||
|
||||
@@ -4,14 +4,11 @@
|
||||
"outDir": "./lib",
|
||||
"module": "node16",
|
||||
"moduleResolution": "node16",
|
||||
"target": "ESNext"
|
||||
"target": "ESNext",
|
||||
"lib": ["ES2022"],
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": [
|
||||
"./**/*.ts",
|
||||
"./mock-module.js",
|
||||
"./mock-register.js",
|
||||
"./fixtures"
|
||||
],
|
||||
"include": ["./node", "./mock-module.js", "./mock-register.js", "./fixtures"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../core/tsconfig.json"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "llamaindex",
|
||||
"version": "0.2.10",
|
||||
"version": "0.2.11",
|
||||
"expectedMinorVersion": "2",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
@@ -12,7 +12,6 @@
|
||||
"@llamaindex/cloud": "0.0.5",
|
||||
"@llamaindex/env": "workspace:*",
|
||||
"@mistralai/mistralai": "^0.1.3",
|
||||
"@notionhq/client": "^2.2.15",
|
||||
"@pinecone-database/pinecone": "^2.2.0",
|
||||
"@qdrant/js-client-rest": "^1.8.2",
|
||||
"@types/lodash": "^4.17.0",
|
||||
@@ -31,7 +30,7 @@
|
||||
"mammoth": "^1.7.1",
|
||||
"md-utils-ts": "^2.0.0",
|
||||
"mongodb": "^6.5.0",
|
||||
"notion-md-crawler": "^0.0.2",
|
||||
"notion-md-crawler": "^1.0.0",
|
||||
"ollama": "^0.5.0",
|
||||
"openai": "^4.38.0",
|
||||
"papaparse": "^5.4.1",
|
||||
@@ -45,7 +44,11 @@
|
||||
"wikipedia": "^2.1.2",
|
||||
"wink-nlp": "^1.14.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@notionhq/client": "^2.2.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@notionhq/client": "^2.2.15",
|
||||
"@swc/cli": "^0.3.12",
|
||||
"@swc/core": "^1.4.16",
|
||||
"concurrently": "^8.2.2",
|
||||
|
||||
@@ -326,6 +326,37 @@ export class ImageNode<T extends Metadata = Metadata> extends TextNode<T> {
|
||||
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> {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { pipeline, randomUUID } from "@llamaindex/env";
|
||||
import {
|
||||
type ChatEngine,
|
||||
type ChatEngineParamsNonStreaming,
|
||||
type ChatEngineParamsStreaming,
|
||||
} from "../engines/chat/index.js";
|
||||
@@ -171,8 +172,9 @@ export async function* createTaskImpl<
|
||||
}
|
||||
|
||||
export type AgentStreamChatResponse<Options extends object> = {
|
||||
response: ReadableStream<ChatResponseChunk<Options>>;
|
||||
sources: ToolOutput[];
|
||||
response: ChatResponseChunk<Options>;
|
||||
// sources of the response, will emit when new tool outputs are available
|
||||
sources?: ToolOutput[];
|
||||
};
|
||||
|
||||
export type AgentChatResponse<Options extends object> = {
|
||||
@@ -276,7 +278,12 @@ export abstract class AgentRunner<
|
||||
>
|
||||
? AdditionalMessageOptions
|
||||
: never,
|
||||
> {
|
||||
> implements
|
||||
ChatEngine<
|
||||
AgentChatResponse<AdditionalMessageOptions>,
|
||||
ReadableStream<AgentStreamChatResponse<AdditionalMessageOptions>>
|
||||
>
|
||||
{
|
||||
readonly #llm: AI;
|
||||
readonly #tools:
|
||||
| BaseToolWithCall[]
|
||||
@@ -370,13 +377,13 @@ export abstract class AgentRunner<
|
||||
): Promise<AgentChatResponse<AdditionalMessageOptions>>;
|
||||
async chat(
|
||||
params: ChatEngineParamsStreaming,
|
||||
): Promise<AgentStreamChatResponse<AdditionalMessageOptions>>;
|
||||
): Promise<ReadableStream<AgentStreamChatResponse<AdditionalMessageOptions>>>;
|
||||
@wrapEventCaller
|
||||
async chat(
|
||||
params: ChatEngineParamsNonStreaming | ChatEngineParamsStreaming,
|
||||
): Promise<
|
||||
| AgentChatResponse<AdditionalMessageOptions>
|
||||
| AgentStreamChatResponse<AdditionalMessageOptions>
|
||||
| ReadableStream<AgentStreamChatResponse<AdditionalMessageOptions>>
|
||||
> {
|
||||
const task = await this.createTask(params.message, !!params.stream);
|
||||
const stepOutput = await pipeline(
|
||||
@@ -397,14 +404,26 @@ export abstract class AgentRunner<
|
||||
const { output, taskStep } = stepOutput;
|
||||
this.#chatHistory = [...taskStep.context.store.messages];
|
||||
if (isAsyncIterable(output)) {
|
||||
return {
|
||||
response: output,
|
||||
sources: [...taskStep.context.store.toolOutputs],
|
||||
} satisfies AgentStreamChatResponse<AdditionalMessageOptions>;
|
||||
return output.pipeThrough<
|
||||
AgentStreamChatResponse<AdditionalMessageOptions>
|
||||
>(
|
||||
new TransformStream({
|
||||
transform(chunk, controller) {
|
||||
controller.enqueue({
|
||||
response: chunk,
|
||||
get sources() {
|
||||
return [...taskStep.context.store.toolOutputs];
|
||||
},
|
||||
});
|
||||
},
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
return {
|
||||
response: output,
|
||||
sources: [...taskStep.context.store.toolOutputs],
|
||||
get sources() {
|
||||
return [...taskStep.context.store.toolOutputs];
|
||||
},
|
||||
} satisfies AgentChatResponse<AdditionalMessageOptions>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { RetrieverQueryEngine } from "../engines/query/RetrieverQueryEngine.js";
|
||||
import type { TransformComponent } from "../ingestion/types.js";
|
||||
import type { BaseNodePostprocessor } from "../postprocessors/types.js";
|
||||
import type { BaseSynthesizer } from "../synthesizers/types.js";
|
||||
import type { BaseQueryEngine } from "../types.js";
|
||||
import type { QueryEngine } from "../types.js";
|
||||
import type { CloudRetrieveParams } from "./LlamaCloudRetriever.js";
|
||||
import { LlamaCloudRetriever } from "./LlamaCloudRetriever.js";
|
||||
import { getPipelineCreate } from "./config.js";
|
||||
@@ -178,7 +178,7 @@ export class LlamaCloudIndex {
|
||||
preFilters?: unknown;
|
||||
nodePostprocessors?: BaseNodePostprocessor[];
|
||||
} & CloudRetrieveParams,
|
||||
): BaseQueryEngine {
|
||||
): QueryEngine {
|
||||
const retriever = new LlamaCloudRetriever({
|
||||
...this.params,
|
||||
...params,
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { getEnv } from "@llamaindex/env";
|
||||
import { OpenAIEmbedding } from "./OpenAIEmbedding.js";
|
||||
|
||||
export class JinaAIEmbedding extends OpenAIEmbedding {
|
||||
constructor(init?: Partial<OpenAIEmbedding>) {
|
||||
const {
|
||||
apiKey = getEnv("JINAAI_API_KEY"),
|
||||
additionalSessionOptions = {},
|
||||
model = "jina-embeddings-v2-base-en",
|
||||
...rest
|
||||
} = init ?? {};
|
||||
|
||||
if (!apiKey) {
|
||||
throw new Error(
|
||||
"Set Jina AI API Key in JINAAI_API_KEY env variable. Get one for free or top up your key at https://jina.ai/embeddings",
|
||||
);
|
||||
}
|
||||
|
||||
additionalSessionOptions.baseURL =
|
||||
additionalSessionOptions.baseURL ?? "https://api.jina.ai/v1";
|
||||
|
||||
super({
|
||||
apiKey,
|
||||
additionalSessionOptions,
|
||||
model,
|
||||
...rest,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from "./ClipEmbedding.js";
|
||||
export * from "./HuggingFaceEmbedding.js";
|
||||
export * from "./JinaAIEmbedding.js";
|
||||
export * from "./MistralAIEmbedding.js";
|
||||
export * from "./MultiModalEmbedding.js";
|
||||
export { OllamaEmbedding } from "./OllamaEmbedding.js";
|
||||
|
||||
@@ -12,7 +12,7 @@ import { wrapEventCaller } from "../../internal/context/EventCaller.js";
|
||||
import type { ChatMessage, LLM } from "../../llm/index.js";
|
||||
import { extractText, streamReducer } from "../../llm/utils.js";
|
||||
import { PromptMixin } from "../../prompts/index.js";
|
||||
import type { BaseQueryEngine } from "../../types.js";
|
||||
import type { QueryEngine } from "../../types.js";
|
||||
import type {
|
||||
ChatEngine,
|
||||
ChatEngineParamsNonStreaming,
|
||||
@@ -33,13 +33,13 @@ export class CondenseQuestionChatEngine
|
||||
extends PromptMixin
|
||||
implements ChatEngine
|
||||
{
|
||||
queryEngine: BaseQueryEngine;
|
||||
queryEngine: QueryEngine;
|
||||
chatHistory: ChatHistory;
|
||||
llm: LLM;
|
||||
condenseMessagePrompt: CondenseQuestionPrompt;
|
||||
|
||||
constructor(init: {
|
||||
queryEngine: BaseQueryEngine;
|
||||
queryEngine: QueryEngine;
|
||||
chatHistory: ChatMessage[];
|
||||
serviceContext?: ServiceContext;
|
||||
condenseMessagePrompt?: CondenseQuestionPrompt;
|
||||
|
||||
@@ -23,21 +23,21 @@ export interface ChatEngineParamsNonStreaming extends ChatEngineParamsBase {
|
||||
stream?: false | null;
|
||||
}
|
||||
|
||||
export interface ChatEngineAgentParams extends ChatEngineParamsBase {
|
||||
toolChoice?: string | Record<string, any>;
|
||||
stream?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* A ChatEngine is used to handle back and forth chats between the application and the LLM.
|
||||
*/
|
||||
export interface ChatEngine {
|
||||
export interface ChatEngine<
|
||||
// synchronous response
|
||||
R = Response,
|
||||
// asynchronous response
|
||||
AR extends AsyncIterable<unknown> = AsyncIterable<R>,
|
||||
> {
|
||||
/**
|
||||
* Send message along with the class's current chat history to the LLM.
|
||||
* @param params
|
||||
*/
|
||||
chat(params: ChatEngineParamsStreaming): Promise<AsyncIterable<Response>>;
|
||||
chat(params: ChatEngineParamsNonStreaming): Promise<Response>;
|
||||
chat(params: ChatEngineParamsStreaming): Promise<AR>;
|
||||
chat(params: ChatEngineParamsNonStreaming): Promise<R>;
|
||||
|
||||
/**
|
||||
* Resets the chat history so that it's empty.
|
||||
|
||||
@@ -7,7 +7,7 @@ import { PromptMixin } from "../../prompts/Mixin.js";
|
||||
import type { BaseSynthesizer } from "../../synthesizers/index.js";
|
||||
import { ResponseSynthesizer } from "../../synthesizers/index.js";
|
||||
import type {
|
||||
BaseQueryEngine,
|
||||
QueryEngine,
|
||||
QueryEngineParamsNonStreaming,
|
||||
QueryEngineParamsStreaming,
|
||||
} from "../../types.js";
|
||||
@@ -15,10 +15,7 @@ import type {
|
||||
/**
|
||||
* A query engine that uses a retriever to query an index and then synthesizes the response.
|
||||
*/
|
||||
export class RetrieverQueryEngine
|
||||
extends PromptMixin
|
||||
implements BaseQueryEngine
|
||||
{
|
||||
export class RetrieverQueryEngine extends PromptMixin implements QueryEngine {
|
||||
retriever: BaseRetriever;
|
||||
responseSynthesizer: BaseSynthesizer;
|
||||
nodePostprocessors: BaseNodePostprocessor[];
|
||||
|
||||
@@ -7,14 +7,14 @@ import type { BaseSelector } from "../../selectors/index.js";
|
||||
import { LLMSingleSelector } from "../../selectors/index.js";
|
||||
import { TreeSummarize } from "../../synthesizers/index.js";
|
||||
import type {
|
||||
BaseQueryEngine,
|
||||
QueryBundle,
|
||||
QueryEngine,
|
||||
QueryEngineParamsNonStreaming,
|
||||
QueryEngineParamsStreaming,
|
||||
} from "../../types.js";
|
||||
|
||||
type RouterQueryEngineTool = {
|
||||
queryEngine: BaseQueryEngine;
|
||||
queryEngine: QueryEngine;
|
||||
description: string;
|
||||
};
|
||||
|
||||
@@ -54,9 +54,9 @@ async function combineResponses(
|
||||
/**
|
||||
* A query engine that uses multiple query engines and selects the best one.
|
||||
*/
|
||||
export class RouterQueryEngine extends PromptMixin implements BaseQueryEngine {
|
||||
export class RouterQueryEngine extends PromptMixin implements QueryEngine {
|
||||
private selector: BaseSelector;
|
||||
private queryEngines: BaseQueryEngine[];
|
||||
private queryEngines: QueryEngine[];
|
||||
private metadatas: RouterQueryEngineMetadata[];
|
||||
private summarizer: TreeSummarize;
|
||||
private verbose: boolean;
|
||||
|
||||
@@ -11,8 +11,8 @@ import {
|
||||
} from "../../synthesizers/index.js";
|
||||
|
||||
import type {
|
||||
BaseQueryEngine,
|
||||
BaseTool,
|
||||
QueryEngine,
|
||||
QueryEngineParamsNonStreaming,
|
||||
QueryEngineParamsStreaming,
|
||||
ToolMetadata,
|
||||
@@ -24,10 +24,7 @@ import type { BaseQuestionGenerator, SubQuestion } from "./types.js";
|
||||
/**
|
||||
* SubQuestionQueryEngine decomposes a question into subquestions and then
|
||||
*/
|
||||
export class SubQuestionQueryEngine
|
||||
extends PromptMixin
|
||||
implements BaseQueryEngine
|
||||
{
|
||||
export class SubQuestionQueryEngine extends PromptMixin implements QueryEngine {
|
||||
responseSynthesizer: BaseSynthesizer;
|
||||
questionGen: BaseQuestionGenerator;
|
||||
queryEngines: BaseTool[];
|
||||
|
||||
@@ -8,7 +8,7 @@ import type { BaseDocumentStore } from "../storage/docStore/types.js";
|
||||
import type { BaseIndexStore } from "../storage/indexStore/types.js";
|
||||
import type { VectorStore } from "../storage/vectorStore/types.js";
|
||||
import type { BaseSynthesizer } from "../synthesizers/types.js";
|
||||
import type { BaseQueryEngine } from "../types.js";
|
||||
import type { QueryEngine } from "../types.js";
|
||||
import { IndexStruct } from "./IndexStruct.js";
|
||||
import { IndexStructType } from "./json-to-index-struct.js";
|
||||
|
||||
@@ -87,7 +87,7 @@ export abstract class BaseIndex<T> {
|
||||
abstract asQueryEngine(options?: {
|
||||
retriever?: BaseRetriever;
|
||||
responseSynthesizer?: BaseSynthesizer;
|
||||
}): BaseQueryEngine;
|
||||
}): QueryEngine;
|
||||
|
||||
/**
|
||||
* Insert a document into the index.
|
||||
|
||||
@@ -17,7 +17,7 @@ import type { StorageContext } from "../../storage/StorageContext.js";
|
||||
import { storageContextFromDefaults } from "../../storage/StorageContext.js";
|
||||
import type { BaseDocumentStore } from "../../storage/docStore/types.js";
|
||||
import type { BaseSynthesizer } from "../../synthesizers/index.js";
|
||||
import type { BaseQueryEngine } from "../../types.js";
|
||||
import type { QueryEngine } from "../../types.js";
|
||||
import type { BaseIndexInit } from "../BaseIndex.js";
|
||||
import { BaseIndex, KeywordTable } from "../BaseIndex.js";
|
||||
import { IndexStructType } from "../json-to-index-struct.js";
|
||||
@@ -234,7 +234,7 @@ export class KeywordTableIndex extends BaseIndex<KeywordTable> {
|
||||
responseSynthesizer?: BaseSynthesizer;
|
||||
preFilters?: unknown;
|
||||
nodePostprocessors?: BaseNodePostprocessor[];
|
||||
}): BaseQueryEngine {
|
||||
}): QueryEngine {
|
||||
const { retriever, responseSynthesizer } = options ?? {};
|
||||
return new RetrieverQueryEngine(
|
||||
retriever ?? this.asRetriever(),
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
CompactAndRefine,
|
||||
ResponseSynthesizer,
|
||||
} from "../../synthesizers/index.js";
|
||||
import type { BaseQueryEngine } from "../../types.js";
|
||||
import type { QueryEngine } from "../../types.js";
|
||||
import type { BaseIndexInit } from "../BaseIndex.js";
|
||||
import { BaseIndex } from "../BaseIndex.js";
|
||||
import { IndexList, IndexStructType } from "../json-to-index-struct.js";
|
||||
@@ -171,7 +171,7 @@ export class SummaryIndex extends BaseIndex<IndexList> {
|
||||
responseSynthesizer?: BaseSynthesizer;
|
||||
preFilters?: unknown;
|
||||
nodePostprocessors?: BaseNodePostprocessor[];
|
||||
}): BaseQueryEngine & RetrieverQueryEngine {
|
||||
}): QueryEngine & RetrieverQueryEngine {
|
||||
let { retriever, responseSynthesizer } = options ?? {};
|
||||
|
||||
if (!retriever) {
|
||||
|
||||
@@ -37,7 +37,7 @@ import type {
|
||||
import type { BaseIndexStore } from "../../storage/indexStore/types.js";
|
||||
import { VectorStoreQueryMode } from "../../storage/vectorStore/types.js";
|
||||
import type { BaseSynthesizer } from "../../synthesizers/types.js";
|
||||
import type { BaseQueryEngine } from "../../types.js";
|
||||
import type { QueryEngine } from "../../types.js";
|
||||
import type { BaseIndexInit } from "../BaseIndex.js";
|
||||
import { BaseIndex } from "../BaseIndex.js";
|
||||
import { IndexDict, IndexStructType } from "../json-to-index-struct.js";
|
||||
@@ -284,7 +284,7 @@ export class VectorStoreIndex extends BaseIndex<IndexDict> {
|
||||
responseSynthesizer?: BaseSynthesizer;
|
||||
preFilters?: MetadataFilters;
|
||||
nodePostprocessors?: BaseNodePostprocessor[];
|
||||
}): BaseQueryEngine & RetrieverQueryEngine {
|
||||
}): QueryEngine & RetrieverQueryEngine {
|
||||
const { retriever, responseSynthesizer } = options ?? {};
|
||||
return new RetrieverQueryEngine(
|
||||
retriever ?? this.asRetriever(),
|
||||
|
||||
@@ -94,20 +94,20 @@ export class IngestionPipeline {
|
||||
documents?: Document[],
|
||||
nodes?: BaseNode[],
|
||||
): Promise<BaseNode[]> {
|
||||
const inputNodes: BaseNode[] = [];
|
||||
const inputNodes: BaseNode[][] = [];
|
||||
if (documents) {
|
||||
inputNodes.push(...documents);
|
||||
inputNodes.push(documents);
|
||||
}
|
||||
if (nodes) {
|
||||
inputNodes.push(...nodes);
|
||||
inputNodes.push(nodes);
|
||||
}
|
||||
if (this.documents) {
|
||||
inputNodes.push(...this.documents);
|
||||
inputNodes.push(this.documents);
|
||||
}
|
||||
if (this.reader) {
|
||||
inputNodes.push(...(await this.reader.loadData()));
|
||||
inputNodes.push(await this.reader.loadData());
|
||||
}
|
||||
return inputNodes;
|
||||
return inputNodes.flat();
|
||||
}
|
||||
|
||||
async run(
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
import { getEnv } from "@llamaindex/env";
|
||||
import type { NodeWithScore } from "../../Node.js";
|
||||
import { MetadataMode } from "../../Node.js";
|
||||
import type { BaseNodePostprocessor } from "../types.js";
|
||||
|
||||
interface JinaAIRerankerResult {
|
||||
index: number;
|
||||
document?: {
|
||||
text?: string;
|
||||
};
|
||||
relevance_score: number;
|
||||
}
|
||||
|
||||
export class JinaAIReranker implements BaseNodePostprocessor {
|
||||
model: string = "jina-reranker-v1-base-en";
|
||||
topN?: number;
|
||||
apiKey?: string = undefined;
|
||||
|
||||
constructor(init?: Partial<JinaAIReranker>) {
|
||||
this.topN = init?.topN ?? 2;
|
||||
this.model = init?.model ?? "jina-reranker-v1-base-en";
|
||||
this.apiKey = getEnv("JINAAI_API_KEY");
|
||||
|
||||
if (!this.apiKey) {
|
||||
throw new Error(
|
||||
"Set Jina AI API Key in JINAAI_API_KEY env variable. Get one for free or top up your key at https://jina.ai/reranker",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async rerank(
|
||||
query: string,
|
||||
documents: string[],
|
||||
topN: number | undefined = this.topN,
|
||||
): Promise<JinaAIRerankerResult[]> {
|
||||
const url = "https://api.jina.ai/v1/rerank";
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${this.apiKey}`,
|
||||
};
|
||||
const data = {
|
||||
model: this.model,
|
||||
query: query,
|
||||
documents: documents,
|
||||
top_n: topN,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
const jsonData = await response.json();
|
||||
|
||||
return jsonData.results;
|
||||
} catch (error) {
|
||||
console.error("Error while reranking:", error);
|
||||
throw new Error("Failed to rerank documents due to an API error");
|
||||
}
|
||||
}
|
||||
|
||||
async postprocessNodes(
|
||||
nodes: NodeWithScore[],
|
||||
query?: string,
|
||||
): Promise<NodeWithScore[]> {
|
||||
if (nodes.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (query === undefined) {
|
||||
throw new Error("JinaAIReranker requires a query");
|
||||
}
|
||||
|
||||
const documents = nodes.map((n) => n.node.getContent(MetadataMode.ALL));
|
||||
const results = await this.rerank(query, documents, this.topN);
|
||||
const newNodes: NodeWithScore[] = [];
|
||||
|
||||
for (const result of results) {
|
||||
const node = nodes[result.index];
|
||||
newNodes.push({
|
||||
node: node.node,
|
||||
score: result.relevance_score,
|
||||
});
|
||||
}
|
||||
|
||||
return newNodes;
|
||||
}
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
export * from "./CohereRerank.js";
|
||||
export * from "./JinaAIReranker.js";
|
||||
|
||||
@@ -19,7 +19,7 @@ export class ImageReader implements FileReader {
|
||||
file: string,
|
||||
fs: GenericFileSystem = defaultFS,
|
||||
): Promise<Document[]> {
|
||||
const dataBuffer = await fs.readFile(file);
|
||||
const dataBuffer = await fs.readRawFile(file);
|
||||
const blob = new Blob([dataBuffer]);
|
||||
return [new ImageDocument({ image: blob, id_: file })];
|
||||
}
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
import type { Client } from "@notionhq/client";
|
||||
import type { Crawler, Pages } from "notion-md-crawler";
|
||||
import type { Crawler, CrawlerOptions, Page } from "notion-md-crawler";
|
||||
import { crawler, pageToString } from "notion-md-crawler";
|
||||
import { Document } from "../Node.js";
|
||||
import type { BaseReader } from "./type.js";
|
||||
|
||||
type OptionalSerializers = Parameters<Crawler>[number]["serializers"];
|
||||
|
||||
/**
|
||||
* Options for initializing the NotionReader class
|
||||
* @typedef {Object} NotionReaderOptions
|
||||
* @property {Client} client - The Notion Client object for API interactions
|
||||
* @property {OptionalSerializers} [serializers] - Option to customize serialization. See [the url](https://github.com/TomPenguin/notion-md-crawler/tree/main) for details.
|
||||
*/
|
||||
type NotionReaderOptions = {
|
||||
client: Client;
|
||||
serializers?: OptionalSerializers;
|
||||
};
|
||||
type NotionReaderOptions = Pick<CrawlerOptions, "client" | "serializers">;
|
||||
|
||||
/**
|
||||
* Notion pages are retrieved recursively and converted to Document objects.
|
||||
@@ -25,7 +13,7 @@ type NotionReaderOptions = {
|
||||
* Please refer to [this document](https://www.notion.so/help/create-integrations-with-the-notion-api) for details.
|
||||
*/
|
||||
export class NotionReader implements BaseReader {
|
||||
private crawl: ReturnType<Crawler>;
|
||||
private readonly crawl: ReturnType<Crawler>;
|
||||
|
||||
/**
|
||||
* Constructor for the NotionReader class
|
||||
@@ -37,10 +25,10 @@ export class NotionReader implements BaseReader {
|
||||
|
||||
/**
|
||||
* Converts Pages to an array of Document objects
|
||||
* @param {Pages} pages - The Notion pages to convert (Return value of `loadPages`)
|
||||
* @param {Page} pages - The Notion pages to convert (Return value of `loadPages`)
|
||||
* @returns {Document[]} An array of Document objects
|
||||
*/
|
||||
toDocuments(pages: Pages): Document[] {
|
||||
toDocuments(pages: Page[]): Document[] {
|
||||
return Object.values(pages).map((page) => {
|
||||
const text = pageToString(page);
|
||||
return new Document({
|
||||
@@ -54,10 +42,21 @@ export class NotionReader implements BaseReader {
|
||||
/**
|
||||
* Loads recursively the Notion page with the specified root page ID.
|
||||
* @param {string} rootPageId - The root Notion page ID
|
||||
* @returns {Promise<Pages>} A Promise that resolves to a Pages object(Convertible with the `toDocuments` method)
|
||||
* @returns {Promise<Page[]>} A Promise that resolves to a Pages object(Convertible with the `toDocuments` method)
|
||||
*/
|
||||
async loadPages(rootPageId: string): Promise<Pages> {
|
||||
return this.crawl(rootPageId);
|
||||
async loadPages(rootPageId: string): Promise<Page[]> {
|
||||
const iter = this.crawl(rootPageId);
|
||||
const pages: Page[] = [];
|
||||
for await (const result of iter) {
|
||||
if (result.success) {
|
||||
pages.push(result.page);
|
||||
} else {
|
||||
console.error(
|
||||
`Failed to load page (${result.failure.parentId}): ${result.failure.reason}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { CompleteFileSystem } from "@llamaindex/env";
|
||||
import { defaultFS, path } from "@llamaindex/env";
|
||||
import { Document } from "../Node.js";
|
||||
import { Document, type Metadata } from "../Node.js";
|
||||
import { walk } from "../storage/FileSystem.js";
|
||||
import { TextFileReader } from "./TextFileReader.js";
|
||||
import type { BaseReader } from "./type.js";
|
||||
@@ -89,6 +89,7 @@ export class SimpleDirectoryReader implements BaseReader {
|
||||
}
|
||||
|
||||
const fileDocs = await reader.loadData(filePath, fs);
|
||||
fileDocs.forEach(addMetaData(filePath));
|
||||
|
||||
// Observer can still cancel addition of the resulting docs from this file
|
||||
if (this.doObserverCheck("file", filePath, ReaderStatus.COMPLETE)) {
|
||||
@@ -124,3 +125,10 @@ export class SimpleDirectoryReader implements BaseReader {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function addMetaData(filePath: string): (doc: Document<Metadata>) => void {
|
||||
return (doc: Document<Metadata>) => {
|
||||
doc.metadata["file_path"] = path.resolve(filePath);
|
||||
doc.metadata["file_name"] = path.basename(filePath);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { JSONSchemaType } from "ajv";
|
||||
import type { BaseQueryEngine, BaseTool, ToolMetadata } from "../types.js";
|
||||
import type { BaseTool, QueryEngine, ToolMetadata } from "../types.js";
|
||||
|
||||
const DEFAULT_NAME = "query_engine_tool";
|
||||
const DEFAULT_DESCRIPTION =
|
||||
@@ -17,7 +17,7 @@ const DEFAULT_PARAMETERS: JSONSchemaType<QueryEngineParam> = {
|
||||
};
|
||||
|
||||
export type QueryEngineToolParams = {
|
||||
queryEngine: BaseQueryEngine;
|
||||
queryEngine: QueryEngine;
|
||||
metadata: ToolMetadata<JSONSchemaType<QueryEngineParam>>;
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@ export type QueryEngineParam = {
|
||||
};
|
||||
|
||||
export class QueryEngineTool implements BaseTool<QueryEngineParam> {
|
||||
private queryEngine: BaseQueryEngine;
|
||||
private queryEngine: QueryEngine;
|
||||
metadata: ToolMetadata<JSONSchemaType<QueryEngineParam>>;
|
||||
|
||||
constructor({ queryEngine, metadata }: QueryEngineToolParams) {
|
||||
|
||||
@@ -22,7 +22,7 @@ export interface QueryEngineParamsNonStreaming extends QueryEngineParamsBase {
|
||||
/**
|
||||
* A query engine is a question answerer that can use one or more steps.
|
||||
*/
|
||||
export interface BaseQueryEngine {
|
||||
export interface QueryEngine {
|
||||
/**
|
||||
* Query the query engine and get a response.
|
||||
* @param params
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Document } from "llamaindex/Node";
|
||||
import { Document, ImageDocument } from "llamaindex/Node";
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
describe("Document", () => {
|
||||
@@ -6,4 +6,16 @@ describe("Document", () => {
|
||||
const doc = new Document({ text: "text", id_: "docId" });
|
||||
expect(doc).toBeDefined();
|
||||
});
|
||||
|
||||
test("should generate different hash for different image contents", () => {
|
||||
const imageNode1 = new ImageDocument({
|
||||
id_: "image",
|
||||
image: "data:image/png;base64,sample_image_content1",
|
||||
});
|
||||
const imageNode2 = new ImageDocument({
|
||||
id_: "image",
|
||||
image: "data:image/png;base64,sample_image_content2",
|
||||
});
|
||||
expect(imageNode1.hash).not.toBe(imageNode2.hash);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Document } from "llamaindex/Node";
|
||||
import { IngestionPipeline } from "llamaindex/ingestion/IngestionPipeline";
|
||||
import { test } from "vitest";
|
||||
|
||||
// Refs: https://github.com/run-llama/LlamaIndexTS/pull/760
|
||||
test("load large data should not cause RangeError #760", async () => {
|
||||
const pipeline = new IngestionPipeline({
|
||||
reader: {
|
||||
loadData: async () => {
|
||||
return Array.from(
|
||||
{ length: 1e6 },
|
||||
(_, i) =>
|
||||
new Document({
|
||||
id_: `${i}`,
|
||||
text: "some text",
|
||||
}),
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
await pipeline.prepareInput();
|
||||
});
|
||||
@@ -1,5 +1,13 @@
|
||||
# test-edge-runtime
|
||||
|
||||
## 0.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [87142b2]
|
||||
- Updated dependencies [87142b2]
|
||||
- @llamaindex/edge@0.2.11
|
||||
|
||||
## 0.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "test-edge-runtime",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.3",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
@@ -14,7 +14,7 @@
|
||||
"react-dom": "^18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/node": "^20.12.7",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"typescript": "^5"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/edge",
|
||||
"version": "0.2.10",
|
||||
"version": "0.2.11",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
@@ -11,7 +11,6 @@
|
||||
"@llamaindex/cloud": "0.0.5",
|
||||
"@llamaindex/env": "workspace:*",
|
||||
"@mistralai/mistralai": "^0.1.3",
|
||||
"@notionhq/client": "^2.2.15",
|
||||
"@pinecone-database/pinecone": "^2.2.0",
|
||||
"@qdrant/js-client-rest": "^1.8.2",
|
||||
"@types/lodash": "^4.17.0",
|
||||
@@ -30,7 +29,7 @@
|
||||
"mammoth": "^1.7.1",
|
||||
"md-utils-ts": "^2.0.0",
|
||||
"mongodb": "^6.5.0",
|
||||
"notion-md-crawler": "^0.0.2",
|
||||
"notion-md-crawler": "^1.0.0",
|
||||
"ollama": "^0.5.0",
|
||||
"openai": "^4.38.0",
|
||||
"papaparse": "^5.4.1",
|
||||
@@ -82,5 +81,17 @@
|
||||
"update:deps": "node scripts/update-deps.js",
|
||||
"build:core": "pnpm --filter llamaindex build && cp -r ../core/dist . && rm -rf dist/cjs",
|
||||
"build": "pnpm run update:deps && pnpm run build:core && pnpm copy"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@notionhq/client": "^2.2.15",
|
||||
"@swc/cli": "^0.3.12",
|
||||
"@swc/core": "^1.4.16",
|
||||
"concurrently": "^8.2.2",
|
||||
"glob": "^10.3.12",
|
||||
"madge": "^7.0.0",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@notionhq/client": "^2.2.15"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ const edgePackagePath = path.join(process.cwd(), "package.json");
|
||||
const edgePackage = readJson(edgePackagePath);
|
||||
const corePackage = readJson(corePackagePath);
|
||||
edgePackage.dependencies = corePackage.dependencies;
|
||||
edgePackage.devDependencies = corePackage.devDependencies;
|
||||
edgePackage.peerDependencies = corePackage.peerDependencies;
|
||||
edgePackage.version = corePackage.version;
|
||||
writeJson(edgePackagePath, edgePackage);
|
||||
execSync("pnpm install --lockfile-only", { stdio: "inherit" });
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @llamaindex/experimental
|
||||
|
||||
## 0.0.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [87142b2]
|
||||
- Updated dependencies [5a6cc0e]
|
||||
- Updated dependencies [87142b2]
|
||||
- llamaindex@0.2.11
|
||||
|
||||
## 0.0.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/experimental",
|
||||
"description": "Experimental package for LlamaIndexTS",
|
||||
"version": "0.0.13",
|
||||
"version": "0.0.14",
|
||||
"type": "module",
|
||||
"types": "dist/type/index.d.ts",
|
||||
"main": "dist/cjs/index.js",
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Response } from "llamaindex";
|
||||
import { serviceContextFromDefaults, type ServiceContext } from "llamaindex";
|
||||
|
||||
import type {
|
||||
BaseQueryEngine,
|
||||
QueryEngine,
|
||||
QueryEngineParamsNonStreaming,
|
||||
QueryEngineParamsStreaming,
|
||||
} from "llamaindex";
|
||||
@@ -89,7 +89,7 @@ type OutputProcessor = typeof defaultOutputProcessor;
|
||||
/**
|
||||
* A JSON query engine that uses JSONPath to query a JSON object.
|
||||
*/
|
||||
export class JSONQueryEngine implements BaseQueryEngine {
|
||||
export class JSONQueryEngine implements QueryEngine {
|
||||
jsonValue: JSONSchemaType;
|
||||
jsonSchema: JSONSchemaType;
|
||||
serviceContext: ServiceContext;
|
||||
|
||||
Generated
+42
-47
@@ -70,6 +70,9 @@ importers:
|
||||
clsx:
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0
|
||||
llamaindex:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/core
|
||||
postcss:
|
||||
specifier: ^8.4.38
|
||||
version: 8.4.38
|
||||
@@ -178,12 +181,12 @@ importers:
|
||||
'@types/node':
|
||||
specifier: ^20.12.7
|
||||
version: 20.12.7
|
||||
ts-node:
|
||||
specifier: ^10.9.2
|
||||
version: 10.9.2(@swc/core@1.4.16(@swc/helpers@0.5.2))(@types/node@20.12.7)(typescript@5.4.3)
|
||||
tsx:
|
||||
specifier: ^4.7.2
|
||||
version: 4.7.2
|
||||
typescript:
|
||||
specifier: ^5.4.3
|
||||
version: 5.4.3
|
||||
specifier: ^5.4.5
|
||||
version: 5.4.5
|
||||
|
||||
packages/core:
|
||||
dependencies:
|
||||
@@ -208,9 +211,6 @@ importers:
|
||||
'@mistralai/mistralai':
|
||||
specifier: ^0.1.3
|
||||
version: 0.1.3(encoding@0.1.13)
|
||||
'@notionhq/client':
|
||||
specifier: ^2.2.15
|
||||
version: 2.2.15(encoding@0.1.13)
|
||||
'@pinecone-database/pinecone':
|
||||
specifier: ^2.2.0
|
||||
version: 2.2.0
|
||||
@@ -266,8 +266,8 @@ importers:
|
||||
specifier: ^6.5.0
|
||||
version: 6.5.0
|
||||
notion-md-crawler:
|
||||
specifier: ^0.0.2
|
||||
version: 0.0.2(encoding@0.1.13)
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0(encoding@0.1.13)
|
||||
ollama:
|
||||
specifier: ^0.5.0
|
||||
version: 0.5.0
|
||||
@@ -305,6 +305,9 @@ importers:
|
||||
specifier: ^1.14.3
|
||||
version: 1.14.3
|
||||
devDependencies:
|
||||
'@notionhq/client':
|
||||
specifier: ^2.2.15
|
||||
version: 2.2.15(encoding@0.1.13)
|
||||
'@swc/cli':
|
||||
specifier: ^0.3.12
|
||||
version: 0.3.12(@swc/core@1.4.16(@swc/helpers@0.5.2))(chokidar@3.6.0)
|
||||
@@ -371,9 +374,6 @@ importers:
|
||||
'@mistralai/mistralai':
|
||||
specifier: ^0.1.3
|
||||
version: 0.1.3(encoding@0.1.13)
|
||||
'@notionhq/client':
|
||||
specifier: ^2.2.15
|
||||
version: 2.2.15(encoding@0.1.13)
|
||||
'@pinecone-database/pinecone':
|
||||
specifier: ^2.2.0
|
||||
version: 2.2.0
|
||||
@@ -429,8 +429,8 @@ importers:
|
||||
specifier: ^6.5.0
|
||||
version: 6.5.0
|
||||
notion-md-crawler:
|
||||
specifier: ^0.0.2
|
||||
version: 0.0.2(encoding@0.1.13)
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0(encoding@0.1.13)
|
||||
ollama:
|
||||
specifier: ^0.5.0
|
||||
version: 0.5.0
|
||||
@@ -467,6 +467,28 @@ importers:
|
||||
wink-nlp:
|
||||
specifier: ^1.14.3
|
||||
version: 1.14.3
|
||||
devDependencies:
|
||||
'@notionhq/client':
|
||||
specifier: ^2.2.15
|
||||
version: 2.2.15(encoding@0.1.13)
|
||||
'@swc/cli':
|
||||
specifier: ^0.3.12
|
||||
version: 0.3.12(@swc/core@1.4.16(@swc/helpers@0.5.2))(chokidar@3.6.0)
|
||||
'@swc/core':
|
||||
specifier: ^1.4.16
|
||||
version: 1.4.16(@swc/helpers@0.5.2)
|
||||
concurrently:
|
||||
specifier: ^8.2.2
|
||||
version: 8.2.2
|
||||
glob:
|
||||
specifier: ^10.3.12
|
||||
version: 10.3.12
|
||||
madge:
|
||||
specifier: ^7.0.0
|
||||
version: 7.0.0(typescript@5.4.5)
|
||||
typescript:
|
||||
specifier: ^5.4.5
|
||||
version: 5.4.5
|
||||
|
||||
packages/edge/e2e/test-edge-runtime:
|
||||
dependencies:
|
||||
@@ -484,8 +506,8 @@ importers:
|
||||
version: 18.2.0(react@18.2.0)
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^20
|
||||
version: 20.11.20
|
||||
specifier: ^20.12.7
|
||||
version: 20.12.7
|
||||
'@types/react':
|
||||
specifier: ^18
|
||||
version: 18.2.65
|
||||
@@ -2542,9 +2564,6 @@ packages:
|
||||
'@types/node@18.19.31':
|
||||
resolution: {integrity: sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==}
|
||||
|
||||
'@types/node@20.11.20':
|
||||
resolution: {integrity: sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==}
|
||||
|
||||
'@types/node@20.12.7':
|
||||
resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==}
|
||||
|
||||
@@ -6128,8 +6147,8 @@ packages:
|
||||
resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
notion-md-crawler@0.0.2:
|
||||
resolution: {integrity: sha512-lE3/DFMrg7GSbl1sBfDuLVLyxw+yjdarPVm1JGfQ6eONEbNGgO+BdZxpwwZQ1uYeEJurAXMXb/AXT8GKYjKAyg==}
|
||||
notion-md-crawler@1.0.0:
|
||||
resolution: {integrity: sha512-mdB6zn/i32qO2C7X7wZLDpWvFryO3bPYMuBfFgmTPomnfEtIejdQJNVaZzw2GapM82lfWZ5dfsZp3s3UL4p1Fg==}
|
||||
|
||||
npm-run-path@2.0.2:
|
||||
resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==}
|
||||
@@ -11356,10 +11375,6 @@ snapshots:
|
||||
dependencies:
|
||||
undici-types: 5.26.5
|
||||
|
||||
'@types/node@20.11.20':
|
||||
dependencies:
|
||||
undici-types: 5.26.5
|
||||
|
||||
'@types/node@20.12.7':
|
||||
dependencies:
|
||||
undici-types: 5.26.5
|
||||
@@ -15772,7 +15787,7 @@ snapshots:
|
||||
|
||||
normalize-url@8.0.1: {}
|
||||
|
||||
notion-md-crawler@0.0.2(encoding@0.1.13):
|
||||
notion-md-crawler@1.0.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@notionhq/client': 2.2.15(encoding@0.1.13)
|
||||
md-utils-ts: 2.0.0
|
||||
@@ -17787,26 +17802,6 @@ snapshots:
|
||||
|
||||
ts-graphviz@1.8.2: {}
|
||||
|
||||
ts-node@10.9.2(@swc/core@1.4.16(@swc/helpers@0.5.2))(@types/node@20.12.7)(typescript@5.4.3):
|
||||
dependencies:
|
||||
'@cspotcode/source-map-support': 0.8.1
|
||||
'@tsconfig/node10': 1.0.9
|
||||
'@tsconfig/node12': 1.0.11
|
||||
'@tsconfig/node14': 1.0.3
|
||||
'@tsconfig/node16': 1.0.4
|
||||
'@types/node': 20.12.7
|
||||
acorn: 8.11.3
|
||||
acorn-walk: 8.3.2
|
||||
arg: 4.1.3
|
||||
create-require: 1.1.1
|
||||
diff: 4.0.2
|
||||
make-error: 1.3.6
|
||||
typescript: 5.4.3
|
||||
v8-compile-cache-lib: 3.0.1
|
||||
yn: 3.1.1
|
||||
optionalDependencies:
|
||||
'@swc/core': 1.4.16(@swc/helpers@0.5.2)
|
||||
|
||||
ts-node@10.9.2(@swc/core@1.4.16(@swc/helpers@0.5.2))(@types/node@20.12.7)(typescript@5.4.5):
|
||||
dependencies:
|
||||
'@cspotcode/source-map-support': 0.8.1
|
||||
|
||||
Reference in New Issue
Block a user