mirror of
https://github.com/run-llama/LlamaIndexTS.git
synced 2026-07-01 22:14:03 -04:00
Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f322c5d202 | |||
| 376d29a78f | |||
| 224d507ab5 | |||
| 1f680d731d | |||
| f0a1cc51b4 | |||
| fee3280799 | |||
| 54925bf1ae | |||
| 91d02a4fc0 | |||
| 086b94038e | |||
| 5d5716b339 | |||
| fb6db454d4 | |||
| e4d4e0d024 | |||
| 17724d961e | |||
| 6776910c93 | |||
| 15962b36f0 | |||
| 3d9a802734 | |||
| 9cd8f8b0cf | |||
| b44330cbc6 | |||
| 3d5ba0873c | |||
| d917cdc3fa | |||
| b370edf329 | |||
| ec59acd329 | |||
| c69e740c56 | |||
| 6cf6ae631c | |||
| 2562244fb6 | |||
| a2691ee163 | |||
| ab700ea546 | |||
| e775afc3f2 | |||
| 92f07824a7 | |||
| b7cfe5bce6 | |||
| 3ccfb28352 | |||
| 325aa51e51 | |||
| d1d9bd6e41 | |||
| 9a71382243 | |||
| b974eea341 | |||
| e82632f83d | |||
| 1a65ead849 | |||
| 50b7d1b7bb | |||
| 09beb72f5b | |||
| 9bbbc67c8e | |||
| b3681bf681 | |||
| b548b1443b | |||
| 0e980d962d | |||
| 3ed6acc6a6 | |||
| 56746c240f | |||
| 5c1c2c7f5b | |||
| a699086f46 | |||
| 454c204112 | |||
| 277468160d | |||
| a0f424e592 | |||
| 3ae832ca28 | |||
| 16ef5dd631 | |||
| c4bd0a5215 | |||
| f5c8ca7dfb | |||
| 36ddec44af | |||
| c147d8a271 | |||
| 1c444d58b6 | |||
| 1f910f7566 | |||
| 99826cff43 | |||
| e8f8bea969 | |||
| 304484b77a | |||
| 29fed77d58 | |||
| db070588c8 | |||
| 76deca7fea | |||
| f326ab86d2 | |||
| ca8d9709e0 | |||
| e0af059221 | |||
| 8bf5b4acfd | |||
| 93a003baa0 | |||
| 5d9b0bd3f0 | |||
| 9a5525e1b3 | |||
| 7dce3d28d3 | |||
| d4c1482c1c | |||
| 3a96a483a6 | |||
| 7467fce2d4 | |||
| 06af08cac4 | |||
| 83ebdfb1c5 | |||
| 835b1ac000 | |||
| f10b41dbc1 | |||
| 41fe871e2f | |||
| 321c39ddc7 | |||
| f7f1af0139 |
@@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
name: Publish Preview
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
pre_release:
|
||||
name: Pre Release
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
|
||||
- name: Pre Release
|
||||
run: pnpx pkg-pr-new publish ./packages/*
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
@@ -67,3 +67,4 @@ jobs:
|
||||
with:
|
||||
commit_message: "chore: update lock file"
|
||||
branch: changeset-release/main
|
||||
file_pattern: "pnpm-lock.yaml"
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
@@ -97,7 +97,7 @@ jobs:
|
||||
name: Build LlamaIndex Example (${{ matrix.packages }})
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
@@ -116,7 +116,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
|
||||
+7
-7
@@ -4,11 +4,11 @@
|
||||
|
||||
This is a monorepo built with Turborepo
|
||||
|
||||
Right now there are two packages of importance:
|
||||
Right now, for first-time contributors, these three packages are of the highest importance:
|
||||
|
||||
packages/llamaindex which is the main NPM library llamaindex
|
||||
|
||||
examples is where the demo code lives
|
||||
- `packages/llamaindex` which is the main NPM library `llamaindex`
|
||||
- `examples` is where the demo code lives
|
||||
- `apps/docs` is where the code for the documentation of https://ts.llamaindex.ai/ is located
|
||||
|
||||
### Turborepo docs
|
||||
|
||||
@@ -43,11 +43,11 @@ pnpm run test
|
||||
|
||||
To write new test cases write them in [packages/llamaindex/tests](/packages/llamaindex/tests)
|
||||
|
||||
We use Jest https://jestjs.io/ to write our test cases. Jest comes with a bunch of built in assertions using the expect function: https://jestjs.io/docs/expect
|
||||
We use Vitest https://vitest.dev to write our test cases. Vitest comes with a bunch of built-in assertions using the expect function: https://vitest.dev/api/expect.html#expect
|
||||
|
||||
### Demo applications
|
||||
|
||||
There is an existing ["example"](/examples/README.md) demos folder with mainly NodeJS scripts. Feel free to add additional demos to that folder. If you would like to try out your changes in the core package with a new demo, you need to run the build command in the README.
|
||||
There is an existing ["example"](/examples/README.md) demos folder with mainly NodeJS scripts. Feel free to add additional demos to that folder. If you would like to try out your changes in the `llamaindex` package with a new demo, you need to run the build command in the README.
|
||||
|
||||
You can create new demo applications in the apps folder. Just run pnpm init in the folder after you create it to create its own package.json
|
||||
|
||||
@@ -81,7 +81,7 @@ Any changes you make should be reflected in the browser. If you need to regenera
|
||||
|
||||
## Changeset
|
||||
|
||||
We use [changesets](https://github.com/changesets/changesets) for managing versions and changelogs. To create a new changeset, run:
|
||||
We use [changesets](https://github.com/changesets/changesets) for managing versions and changelogs. To create a new changeset, run in the root folder:
|
||||
|
||||
```
|
||||
pnpm changeset
|
||||
|
||||
@@ -76,7 +76,7 @@ main();
|
||||
node --import tsx ./main.ts
|
||||
```
|
||||
|
||||
### Next.js
|
||||
### React Server Component (Next.js, Waku, Redwood.JS...)
|
||||
|
||||
First, you will need to add a llamaindex plugin to your Next.js project.
|
||||
|
||||
@@ -154,40 +154,6 @@ export async function chatWithAgent(
|
||||
}
|
||||
```
|
||||
|
||||
### Cloudflare Workers
|
||||
|
||||
```ts
|
||||
// src/index.ts
|
||||
export default {
|
||||
async fetch(
|
||||
request: Request,
|
||||
env: Env,
|
||||
ctx: ExecutionContext,
|
||||
): Promise<Response> {
|
||||
const { setEnvs } = await import("@llamaindex/env");
|
||||
// set environment variables so that the OpenAIAgent can use them
|
||||
setEnvs(env);
|
||||
const { OpenAIAgent } = await import("llamaindex");
|
||||
const agent = new OpenAIAgent({
|
||||
tools: [],
|
||||
});
|
||||
const responseStream = await agent.chat({
|
||||
stream: true,
|
||||
message: "Hello? What is the weather today?",
|
||||
});
|
||||
const textEncoder = new TextEncoder();
|
||||
const response = responseStream.pipeThrough(
|
||||
new TransformStream({
|
||||
transform: (chunk, controller) => {
|
||||
controller.enqueue(textEncoder.encode(chunk.response.delta));
|
||||
},
|
||||
}),
|
||||
);
|
||||
return new Response(response);
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## Playground
|
||||
|
||||
Check out our NextJS playground at https://llama-playground.vercel.app/. The source is available at https://github.com/run-llama/ts-playground
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"llamaindex": minor
|
||||
"docs": minor
|
||||
---
|
||||
|
||||
Add deepseek llm class
|
||||
@@ -1,5 +1,164 @@
|
||||
# docs
|
||||
|
||||
## 0.0.52
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 376d29a: feat: added tool calling and agent support for llama3.1 504B
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.0.51
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 086b940: feat: add DeepSeek LLM
|
||||
- 5d5716b: feat: add a reader for JSON data
|
||||
- Updated dependencies [086b940]
|
||||
- Updated dependencies [5d5716b]
|
||||
- Updated dependencies [91d02a4]
|
||||
- Updated dependencies [fb6db45]
|
||||
- llamaindex@0.5.10
|
||||
|
||||
## 0.0.50
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [15962b3]
|
||||
- llamaindex@0.5.9
|
||||
|
||||
## 0.0.49
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d5ba08]
|
||||
- Updated dependencies [d917cdc]
|
||||
- llamaindex@0.5.8
|
||||
|
||||
## 0.0.48
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ec59acd]
|
||||
- llamaindex@0.5.7
|
||||
|
||||
## 0.0.47
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [2562244]
|
||||
- Updated dependencies [325aa51]
|
||||
- Updated dependencies [ab700ea]
|
||||
- Updated dependencies [92f0782]
|
||||
- Updated dependencies [6cf6ae6]
|
||||
- Updated dependencies [b7cfe5b]
|
||||
- llamaindex@0.5.6
|
||||
|
||||
## 0.0.46
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [b974eea]
|
||||
- llamaindex@0.5.5
|
||||
|
||||
## 0.0.45
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [1a65ead]
|
||||
- llamaindex@0.5.4
|
||||
|
||||
## 0.0.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9bbbc67]
|
||||
- Updated dependencies [b3681bf]
|
||||
- llamaindex@0.5.3
|
||||
|
||||
## 0.0.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.2
|
||||
|
||||
## 0.0.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 2774681: Add mixedbread's embeddings and reranking API
|
||||
- Updated dependencies [2774681]
|
||||
- Updated dependencies [a0f424e]
|
||||
- llamaindex@0.5.1
|
||||
|
||||
## 0.0.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 36ddec4: fix: typo in custom page separator parameter for LlamaParse
|
||||
- Updated dependencies [16ef5dd]
|
||||
- Updated dependencies [16ef5dd]
|
||||
- Updated dependencies [36ddec4]
|
||||
- llamaindex@0.5.0
|
||||
- @llamaindex/examples@0.0.7
|
||||
|
||||
## 0.0.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.4.14
|
||||
|
||||
## 0.0.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e8f8bea]
|
||||
- Updated dependencies [304484b]
|
||||
- llamaindex@0.4.13
|
||||
|
||||
## 0.0.38
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f326ab8]
|
||||
- llamaindex@0.4.12
|
||||
|
||||
## 0.0.37
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8bf5b4a]
|
||||
- llamaindex@0.4.11
|
||||
|
||||
## 0.0.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [7dce3d2]
|
||||
- llamaindex@0.4.10
|
||||
|
||||
## 0.0.35
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3a96a48]
|
||||
- llamaindex@0.4.9
|
||||
|
||||
## 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
|
||||
|
||||
@@ -62,7 +62,7 @@ These building blocks can be customized to reflect ranking preferences, as well
|
||||
|
||||
[**Retrievers**](../modules/retriever.md):
|
||||
A retriever defines how to efficiently retrieve relevant context from a knowledge base (i.e. index) when given a query.
|
||||
The specific retrieval logic differs for difference indices, the most popular being dense retrieval against a vector index.
|
||||
The specific retrieval logic differs for different indices, the most popular being dense retrieval against a vector index.
|
||||
|
||||
[**Response Synthesizers**](../modules/response_synthesizer.md):
|
||||
A response synthesizer generates a response from an LLM, using a user query and a given set of retrieved text chunks.
|
||||
|
||||
@@ -15,6 +15,7 @@ LlamaIndex.TS comes with a few built-in agents, but you can also create your own
|
||||
- Anthropic Agent both via Anthropic and Bedrock (in `@llamaIndex/community`)
|
||||
- Gemini Agent
|
||||
- ReACT Agent
|
||||
- Meta3.1 504B via Bedrock (in `@llamaIndex/community`)
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import CodeBlock from "@theme/CodeBlock";
|
||||
import CodeSource from "!raw-loader!../../../../../examples/readers/src/discord";
|
||||
|
||||
# DiscordReader
|
||||
|
||||
DiscordReader is a simple data loader that reads all messages in a given Discord channel and returns them as Document objects.
|
||||
It uses the [@discordjs/rest](https://github.com/discordjs/discord.js/tree/main/packages/rest) library to fetch the messages.
|
||||
|
||||
## Usage
|
||||
|
||||
First step is to create a Discord Application and generating a bot token [here](https://discord.com/developers/applications).
|
||||
In your Discord Application, go to the `OAuth2` tab and generate an invite URL by selecting `bot` and click `Read Messages/View Channels` as wells as `Read Message History`.
|
||||
This will invite the bot with the necessary permissions to read messages.
|
||||
Copy the URL in your browser and select the server you want your bot to join.
|
||||
|
||||
<CodeBlock language="ts">{CodeSource}</CodeBlock>
|
||||
|
||||
### Params
|
||||
|
||||
#### DiscordReader()
|
||||
|
||||
- `discordToken?`: The Discord bot token.
|
||||
- `requestHandler?`: Optionally provide a custom request function for edge environments, e.g. `fetch`. See discord.js for more info.
|
||||
|
||||
#### DiscordReader.loadData
|
||||
|
||||
- `channelIDs`: The ID(s) of discord channels as an array of strings.
|
||||
- `limit?`: Optionally limit the number of messages to read
|
||||
- `additionalInfo?`: An optional flag to include embedded messages and attachment urls in the document.
|
||||
- `oldestFirst?`: An optional flag to return the oldest messages first.
|
||||
|
||||
## API Reference
|
||||
|
||||
- [DiscordReader](../../api/classes/DiscordReader.md)
|
||||
@@ -16,7 +16,15 @@ It is a simple reader that reads all files from a directory and its subdirectori
|
||||
|
||||
<CodeBlock language="ts">{CodeSource}</CodeBlock>
|
||||
|
||||
Currently, it supports reading `.txt`, `.pdf`, `.csv`, `.md`, `.docx`, `.htm`, `.html`, `.jpg`, `.jpeg`, `.png` and `.gif` files, but support for other file types is planned.
|
||||
Currently, the following readers are mapped to specific file types:
|
||||
|
||||
- [TextFileReader](../../api/classes/TextFileReader.md): `.txt`
|
||||
- [PDFReader](../../api/classes/PDFReader.md): `.pdf`
|
||||
- [PapaCSVReader](../../api/classes/PapaCSVReader.md): `.csv`
|
||||
- [MarkdownReader](../../api/classes/MarkdownReader.md): `.md`
|
||||
- [DocxReader](../../api/classes/DocxReader.md): `.docx`
|
||||
- [HTMLReader](../../api/classes/HTMLReader.md): `.htm`, `.html`
|
||||
- [ImageReader](../../api/classes/ImageReader.md): `.jpg`, `.jpeg`, `.png`, `.gif`
|
||||
|
||||
You can modify the reader three different ways:
|
||||
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
# JSONReader
|
||||
|
||||
A simple JSON data loader with various options.
|
||||
Either parses the entire string, cleaning it and treat each line as an embedding or performs a recursive depth-first traversal yielding JSON paths.
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { JSONReader } from "llamaindex";
|
||||
|
||||
const file = "../../PATH/TO/FILE";
|
||||
const content = new TextEncoder().encode("JSON_CONTENT");
|
||||
|
||||
const reader = new JSONReader({ levelsBack: 0, collapseLength: 100 });
|
||||
const docsFromFile = reader.loadData(file);
|
||||
const docsFromContent = reader.loadDataAsContent(content);
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
Basic:
|
||||
|
||||
- `ensureAscii?`: Wether to ensure only ASCII characters be present in the output by converting non-ASCII characters to their unicode escape sequence. Default is `false`.
|
||||
|
||||
- `isJsonLines?`: Wether the JSON is in JSON Lines format. If true, will split into lines, remove empty one and parse each line as JSON. Default is `false`
|
||||
|
||||
- `cleanJson?`: Whether to clean the JSON by filtering out structural characters (`{}, [], and ,`). If set to false, it will just parse the JSON, not removing structural characters. Default is `true`.
|
||||
|
||||
Depth-First-Traversal:
|
||||
|
||||
- `levelsBack?`: Specifies how many levels up the JSON structure to include in the output. `cleanJson` will be ignored. If set to 0, all levels are included. If undefined, parses the entire JSON, treat each line as an embedding and create a document per top-level array. Default is `undefined`
|
||||
|
||||
- `collapseLength?`: The maximum length of JSON string representation to be collapsed into a single line. Only applicable when `levelsBack` is set. Default is `undefined`
|
||||
|
||||
#### Examples
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
Input:
|
||||
|
||||
```json
|
||||
{"a": {"1": {"key1": "value1"}, "2": {"key2": "value2"}}, "b": {"3": {"k3": "v3"}, "4": {"k4": "v4"}}}
|
||||
```
|
||||
|
||||
Default options:
|
||||
|
||||
`LevelsBack` = `undefined` & `cleanJson` = `true`
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
"a": {
|
||||
"1": {
|
||||
"key1": "value1"
|
||||
"2": {
|
||||
"key2": "value2"
|
||||
"b": {
|
||||
"3": {
|
||||
"k3": "v3"
|
||||
"4": {
|
||||
"k4": "v4"
|
||||
```
|
||||
|
||||
Depth-First Traversal all levels:
|
||||
|
||||
`levelsBack` = `0`
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
a 1 key1 value1
|
||||
a 2 key2 value2
|
||||
b 3 k3 v3
|
||||
b 4 k4 v4
|
||||
```
|
||||
|
||||
Depth-First Traversal and Collapse:
|
||||
|
||||
`levelsBack` = `0` & `collapseLength` = `35`
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
a 1 {"key1":"value1"}
|
||||
a 2 {"key2":"value2"}
|
||||
b {"3":{"k3":"v3"},"4":{"k4":"v4"}}
|
||||
```
|
||||
|
||||
Depth-First Traversal limited levels:
|
||||
|
||||
`levelsBack` = `2`
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
1 key1 value1
|
||||
2 key2 value2
|
||||
3 k3 v3
|
||||
4 k4 v4
|
||||
```
|
||||
|
||||
Uncleaned JSON:
|
||||
|
||||
`levelsBack` = `undefined` & `cleanJson` = `false`
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
{"a":{"1":{"key1":"value1"},"2":{"key2":"value2"}},"b":{"3":{"k3":"v3"},"4":{"k4":"v4"}}}
|
||||
```
|
||||
|
||||
ASCII-Conversion:
|
||||
|
||||
Input:
|
||||
|
||||
```json
|
||||
{ "message": "こんにちは世界" }
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
"message": "\u3053\u3093\u306b\u3061\u306f\u4e16\u754c"
|
||||
```
|
||||
|
||||
JSON Lines Format:
|
||||
|
||||
Input:
|
||||
|
||||
```json
|
||||
{"tweet": "Hello world"}\n{"tweet": "こんにちは世界"}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
"tweet": "Hello world"
|
||||
|
||||
"tweet": "こんにちは世界"
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## API Reference
|
||||
|
||||
- [JSONReader](../../api/classes/JSONReader.md)
|
||||
@@ -27,23 +27,30 @@ They can be divided into two groups.
|
||||
|
||||
- `apiKey` is required. Can be set as an environment variable `LLAMA_CLOUD_API_KEY`
|
||||
- `checkInterval` is the interval in seconds to check if the parsing is done. Default is `1`.
|
||||
- `maxTimeout` is the maximum timout to wait for parsing to finish. Default is `2000`
|
||||
- `maxTimeout` is the maximum timeout to wait for parsing to finish. Default is `2000`
|
||||
- `verbose` shows progress of the parsing. Default is `true`
|
||||
- `ignoreErrors` set to false to get errors while parsing. Default is `true` and returns an empty array on error.
|
||||
|
||||
#### Advanced params:
|
||||
|
||||
- `resultType` can be set to `markdown`, `text` or `json`. Defaults to `text`. More information about `json` mode on the next pages.
|
||||
- `language` primarly helps with OCR recognition. Defaults to `en`. Click [here](../../../api/type-aliases/Language.md) for a list of supported languages.
|
||||
- `language` primarily helps with OCR recognition. Defaults to `en`. Click [here](../../../api/type-aliases/Language.md) for a list of supported languages.
|
||||
- `parsingInstructions?` Optional. Can help with complicated document structures. See this [LlamaIndex Blog Post](https://www.llamaindex.ai/blog/launching-the-first-genai-native-document-parsing-platform) for an example.
|
||||
- `skipDiagonalText?` Optional. Set to true to ignore diagonal text. (Text that is not rotated 0, 90, 180 or 270 degrees)
|
||||
- `invalidateCache?` Optional. Set to true to ignore the LlamaCloud cache. All document are kept in cache for 48hours after the job was completed to avoid processing the same document twice. Can be useful for testing when trying to re-parse the same document with, e.g. different `parsingInstructions`.
|
||||
- `doNotCache?` Optional. Set to true to not cache the document.
|
||||
- `fastMode?` Optional. Set to true to use the fast mode. This mode will skip OCR of images, and table/heading reconstruction. Note: Non-compatible with `gpt4oMode`.
|
||||
- `doNotUnrollColumns?` Optional. Set to true to keep the text according to document layout. Reduce reconstruction accuracy, and LLM's/embedings performances in most cases.
|
||||
- `pageSeperator?` Optional. The page seperator to use. Defaults is `\\n---\\n`.
|
||||
- `gpt4oMode` set to true to use GPT-4o to extract content. Default is `false`.
|
||||
- `gpt4oApiKey?` Optional. Set the GPT-4o API key. Lowers the cost of parsing by using your own API key. Your OpenAI account will be charged. Can also be set in the environment variable `LLAMA_CLOUD_GPT4O_API_KEY`.
|
||||
- `doNotUnrollColumns?` Optional. Set to true to keep the text according to document layout. Reduce reconstruction accuracy, and LLMs/embeddings performances in most cases.
|
||||
- `pageSeparator?` Optional. A templated page separator to use to split the text. If the results contain `{page_number}` (e.g. JSON mode), it will be replaced by the next page number. If not set the default separator `\\n---\\n` will be used.
|
||||
- `pagePrefix?` Optional. A templated prefix to add to the beginning of each page. If the results contain `{page_number}`, it will be replaced by the page number.
|
||||
- `pageSuffix?` Optional. A templated suffix to add to the end of each page. If the results contain `{page_number}`, it will be replaced by the page number.
|
||||
- `gpt4oMode` Deprecated. Use vendorMultimodal params. Set to true to use GPT-4o to extract content. Default is `false`.
|
||||
- `gpt4oApiKey?` Deprecated. Use vendorMultimodal params. Optional. Set the GPT-4o API key. Lowers the cost of parsing by using your own API key. Your OpenAI account will be charged. Can also be set in the environment variable `LLAMA_CLOUD_GPT4O_API_KEY`.
|
||||
- `boundingBox?` Optional. Specify an area of the document to parse. Expects the bounding box margins as a string in clockwise order, e.g. `boundingBox = "0.1,0,0,0"` to not parse the top 10% of the document.
|
||||
- `targetPages?` Optional. Specify which pages to parse by specifying them as a comma-separated list. First page is `0`.
|
||||
- `useVendorMultimodalModel` set to true to use a multimodal model. Default is `false`.
|
||||
- `vendorMultimodalModel?` Optional. Specify which multimodal model to use. Default is GPT4o. See [here](https://docs.cloud.llamaindex.ai/llamaparse/features/multimodal) for a list of available models and cost.
|
||||
- `vendorMultimodalApiKey?` Optional. Set the multimodal model API key. Can also be set in the environment variable `LLAMA_CLOUD_VENDOR_MULTIMODAL_API_KEY`.
|
||||
- `numWorkers` as in the python version, is set in `SimpleDirectoryReader`. Default is 1.
|
||||
|
||||
### LlamaParse with SimpleDirectoryReader
|
||||
|
||||
@@ -8,7 +8,7 @@ In JSON mode, LlamaParse will return a data structure representing the parsed ob
|
||||
|
||||
## Usage
|
||||
|
||||
For Json mode, you need to use `loadJson`. The `resultType` is automatically set with this method. Currently it can't be used with `SimpleDirectoryReader`.
|
||||
For Json mode, you need to use `loadJson`. The `resultType` is automatically set with this method.
|
||||
More information about indexing the results on the next page.
|
||||
|
||||
```ts
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
# MixedbreadAI
|
||||
|
||||
Welcome to the mixedbread embeddings guide! This guide will help you use the mixedbread ai's API to generate embeddings for your text documents, ensuring you get the most relevant information, just like picking the freshest bread from the bakery.
|
||||
|
||||
To find out more about the latest features, updates, and available models, visit [mixedbread.ai](https://mixedbread-ai.com/).
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Setup](#setup)
|
||||
2. [Usage with LlamaIndex](#integration-with-llamaindex)
|
||||
3. [Embeddings with Custom Parameters](#embeddings-with-custom-parameters)
|
||||
|
||||
## Setup
|
||||
|
||||
First, you will need to install the `llamaindex` package.
|
||||
|
||||
```bash
|
||||
pnpm install llamaindex
|
||||
```
|
||||
|
||||
Next, sign up for an API key at [mixedbread.ai](https://mixedbread.ai/). Once you have your API key, you can import the necessary modules and create a new instance of the `MixedbreadAIEmbeddings` class.
|
||||
|
||||
```ts
|
||||
import { MixedbreadAIEmbeddings, Document, Settings } from "llamaindex";
|
||||
```
|
||||
|
||||
## Usage with LlamaIndex
|
||||
|
||||
This section will guide you through integrating mixedbread embeddings with LlamaIndex for more advanced usage.
|
||||
|
||||
### Step 1: 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, like a variety of breads in a bakery.
|
||||
|
||||
```ts
|
||||
Settings.embedModel = new MixedbreadAIEmbeddings({
|
||||
apiKey: "<MIXEDBREAD_API_KEY>",
|
||||
model: "mixedbread-ai/mxbai-embed-large-v1",
|
||||
});
|
||||
|
||||
const document = new Document({
|
||||
text: "The true source of happiness.",
|
||||
id_: "bread",
|
||||
});
|
||||
|
||||
const index = await VectorStoreIndex.fromDocuments([document]);
|
||||
```
|
||||
|
||||
### Step 2: Create a Query Engine
|
||||
|
||||
Combine the retriever and the embed model to create a query engine. This setup ensures that your queries are processed to provide the best results, like arranging the bread in the order of freshness and quality.
|
||||
|
||||
Models can require prompts to generate embeddings for queries, in the 'mixedbread-ai/mxbai-embed-large-v1' model's case, the prompt is `Represent this sentence for searching relevant passages:`.
|
||||
|
||||
```ts
|
||||
const queryEngine = index.asQueryEngine();
|
||||
|
||||
const query =
|
||||
"Represent this sentence for searching relevant passages: What is bread?";
|
||||
|
||||
// Log the response
|
||||
const results = await queryEngine.query(query);
|
||||
console.log(results); // Serving up the freshest, most relevant results.
|
||||
```
|
||||
|
||||
## Embeddings with Custom Parameters
|
||||
|
||||
This section will guide you through generating embeddings with custom parameters and usage with f.e. matryoshka and binary embeddings.
|
||||
|
||||
### Step 1: Create an Instance of MixedbreadAIEmbeddings
|
||||
|
||||
Create a new instance of the `MixedbreadAIEmbeddings` class with custom parameters. For example, to use the `mixedbread-ai/mxbai-embed-large-v1` model with a batch size of 64, normalized embeddings, and binary encoding format:
|
||||
|
||||
```ts
|
||||
const embeddings = new MixedbreadAIEmbeddings({
|
||||
apiKey: "<MIXEDBREAD_API_KEY>",
|
||||
model: "mixedbread-ai/mxbai-embed-large-v1",
|
||||
batchSize: 64,
|
||||
normalized: true,
|
||||
dimensions: 512,
|
||||
encodingFormat: MixedbreadAI.EncodingFormat.Binary,
|
||||
});
|
||||
```
|
||||
|
||||
### Step 2: Define Texts
|
||||
|
||||
Define the texts you want to generate embeddings for.
|
||||
|
||||
```ts
|
||||
const texts = ["Bread is life", "Bread is love"];
|
||||
```
|
||||
|
||||
### Step 3: Generate Embeddings
|
||||
|
||||
Use the `embedDocuments` method to generate embeddings for the texts.
|
||||
|
||||
```ts
|
||||
const result = await embeddings.embedDocuments(texts);
|
||||
console.log(result); // Perfectly customized embeddings, ready to serve.
|
||||
```
|
||||
@@ -15,7 +15,7 @@ Settings.llm = new Bedrock({
|
||||
});
|
||||
```
|
||||
|
||||
Currently only supports Anthropic models:
|
||||
Currently only supports Anthropic and Meta models:
|
||||
|
||||
```ts
|
||||
ANTHROPIC_CLAUDE_INSTANT_1 = "anthropic.claude-instant-v1";
|
||||
@@ -25,6 +25,13 @@ ANTHROPIC_CLAUDE_3_SONNET = "anthropic.claude-3-sonnet-20240229-v1:0";
|
||||
ANTHROPIC_CLAUDE_3_HAIKU = "anthropic.claude-3-haiku-20240307-v1:0";
|
||||
ANTHROPIC_CLAUDE_3_OPUS = "anthropic.claude-3-opus-20240229-v1:0"; // available on us-west-2
|
||||
ANTHROPIC_CLAUDE_3_5_SONNET = "anthropic.claude-3-5-sonnet-20240620-v1:0";
|
||||
META_LLAMA2_13B_CHAT = "meta.llama2-13b-chat-v1";
|
||||
META_LLAMA2_70B_CHAT = "meta.llama2-70b-chat-v1";
|
||||
META_LLAMA3_8B_INSTRUCT = "meta.llama3-8b-instruct-v1:0";
|
||||
META_LLAMA3_70B_INSTRUCT = "meta.llama3-70b-instruct-v1:0";
|
||||
META_LLAMA3_1_8B_INSTRUCT = "meta.llama3-1-8b-instruct-v1:0"; // available on us-west-2
|
||||
META_LLAMA3_1_70B_INSTRUCT = "meta.llama3-1-70b-instruct-v1:0"; // available on us-west-2
|
||||
META_LLAMA3_1_405B_INSTRUCT = "meta.llama3-1-405b-instruct-v1:0"; // preview only, available on us-west-2, tool calling supported
|
||||
```
|
||||
|
||||
Sonnet, Haiku and Opus are multimodal, image_url only supports base64 data url format, e.g. `data:image/jpeg;base64,SGVsbG8sIFdvcmxkIQ==`
|
||||
@@ -60,3 +67,72 @@ async function main() {
|
||||
console.log(response.response);
|
||||
}
|
||||
```
|
||||
|
||||
## Agent Example
|
||||
|
||||
```ts
|
||||
import { BEDROCK_MODELS, Bedrock } from "@llamaindex/community";
|
||||
import { FunctionTool, 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"],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const bedrock = new Bedrock({
|
||||
model: BEDROCK_MODELS.META_LLAMA3_1_405B_INSTRUCT,
|
||||
...
|
||||
});
|
||||
|
||||
async function main() {
|
||||
const agent = new LLMAgent({
|
||||
llm: bedrock,
|
||||
tools: [sumNumbers, divideNumbers],
|
||||
});
|
||||
|
||||
const response = await agent.chat({
|
||||
message: "How much is 5 + 5? then divide by 2",
|
||||
});
|
||||
|
||||
console.log(response.message);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# DeepSeek LLM
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { DeepSeekLLM, Settings } from "llamaindex";
|
||||
|
||||
Settings.llm = new DeepSeekLLM({
|
||||
apiKey: "<YOUR_API_KEY>",
|
||||
model: "deepseek-coder", // or "deepseek-chat"
|
||||
});
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```ts
|
||||
import { DeepSeekLLM, Document, VectorStoreIndex, Settings } from "llamaindex";
|
||||
|
||||
const deepseekLlm = new DeepSeekLLM({
|
||||
apiKey: "<YOUR_API_KEY>",
|
||||
model: "deepseek-coder", // or "deepseek-chat"
|
||||
});
|
||||
|
||||
async function main() {
|
||||
const response = await llm.deepseekLlm.chat({
|
||||
messages: [
|
||||
{
|
||||
role: "system",
|
||||
content: "You are an AI assistant",
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: "Tell me about San Francisco",
|
||||
},
|
||||
],
|
||||
stream: false,
|
||||
});
|
||||
console.log(response);
|
||||
}
|
||||
```
|
||||
|
||||
# Limitations
|
||||
|
||||
Currently does not support function calling.
|
||||
|
||||
[Currently does not support json-output param while still is very good at json generating.](https://platform.deepseek.com/api-docs/faq#does-your-api-support-json-output)
|
||||
|
||||
## API platform
|
||||
|
||||
- [DeepSeek platform](https://platform.deepseek.com/)
|
||||
@@ -39,8 +39,9 @@ const index = await VectorStoreIndex.fromDocuments([document]);
|
||||
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;
|
||||
const retriever = index.asRetriever({
|
||||
similarityTopK: 5,
|
||||
});
|
||||
```
|
||||
|
||||
## Create a new instance of the CohereRerank class
|
||||
|
||||
@@ -39,8 +39,9 @@ const index = await VectorStoreIndex.fromDocuments([document]);
|
||||
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;
|
||||
const retriever = index.asRetriever({
|
||||
similarityTopK: 5,
|
||||
});
|
||||
```
|
||||
|
||||
## Create a new instance of the JinaAIReranker class
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
# MixedbreadAI
|
||||
|
||||
Welcome to the mixedbread ai reranker guide! This guide will help you use mixedbread ai's API to rerank search query results, ensuring you get the most relevant information, just like picking the freshest bread from the bakery.
|
||||
|
||||
To find out more about the latest features and updates, visit the [mixedbread.ai](https://mixedbread.ai/).
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Setup](#setup)
|
||||
2. [Usage with LlamaIndex](#integration-with-llamaindex)
|
||||
3. [Simple Reranking Guide](#simple-reranking-guide)
|
||||
4. [Reranking with Objects](#reranking-with-objects)
|
||||
|
||||
## Setup
|
||||
|
||||
First, you will need to install the `llamaindex` package.
|
||||
|
||||
```bash
|
||||
pnpm install llamaindex
|
||||
```
|
||||
|
||||
Next, sign up for an API key at [mixedbread.ai](https://mixedbread.ai/). Once you have your API key, you can import the necessary modules and create a new instance of the `MixedbreadAIReranker` class.
|
||||
|
||||
```ts
|
||||
import {
|
||||
MixedbreadAIReranker,
|
||||
Document,
|
||||
OpenAI,
|
||||
VectorStoreIndex,
|
||||
Settings,
|
||||
} from "llamaindex";
|
||||
```
|
||||
|
||||
## Usage with LlamaIndex
|
||||
|
||||
This section will guide you through integrating mixedbread's reranker with LlamaIndex.
|
||||
|
||||
### Step 1: 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, like a variety of breads in a bakery.
|
||||
|
||||
```ts
|
||||
const document = new Document({
|
||||
text: "This is a sample document.",
|
||||
id_: "sampleDoc",
|
||||
});
|
||||
|
||||
Settings.llm = new OpenAI({ model: "gpt-3.5-turbo", temperature: 0.1 });
|
||||
|
||||
const index = await VectorStoreIndex.fromDocuments([document]);
|
||||
```
|
||||
|
||||
### Step 2: Increase Similarity TopK
|
||||
|
||||
The default value for `similarityTopK` is 2, which means only the most similar document will be returned. To get more results, like picking a variety of fresh breads, you can increase the value of `similarityTopK`.
|
||||
|
||||
```ts
|
||||
const retriever = index.asRetriever({
|
||||
similarityTopK: 5,
|
||||
});
|
||||
```
|
||||
|
||||
### Step 3: Create a MixedbreadAIReranker Instance
|
||||
|
||||
Create a new instance of the `MixedbreadAIReranker` class.
|
||||
|
||||
```ts
|
||||
const nodePostprocessor = new MixedbreadAIReranker({
|
||||
apiKey: "<MIXEDBREAD_API_KEY>",
|
||||
topN: 4,
|
||||
});
|
||||
```
|
||||
|
||||
### Step 4: Create a Query Engine
|
||||
|
||||
Combine the retriever and node postprocessor to create a query engine. This setup ensures that your queries are processed and reranked to provide the best results, like arranging the bread in the order of freshness and quality.
|
||||
|
||||
```ts
|
||||
const queryEngine = index.asQueryEngine({
|
||||
retriever,
|
||||
nodePostprocessors: [nodePostprocessor],
|
||||
});
|
||||
|
||||
// Log the response
|
||||
const response = await queryEngine.query("Where did the author grow up?");
|
||||
console.log(response);
|
||||
```
|
||||
|
||||
With mixedbread's Reranker, you're all set to serve up the most relevant and well-ordered results, just like a skilled baker arranging their best breads for eager customers. Enjoy the perfect blend of technology and culinary delight!
|
||||
|
||||
## Simple Reranking Guide
|
||||
|
||||
This section will guide you through a simple reranking process using mixedbread ai.
|
||||
|
||||
### Step 1: Create an Instance of MixedbreadAIReranker
|
||||
|
||||
Create a new instance of the `MixedbreadAIReranker` class, passing in your API key and the number of results you want to return. It's like setting up your bakery to offer a specific number of freshly baked items.
|
||||
|
||||
```ts
|
||||
const reranker = new MixedbreadAIReranker({
|
||||
apiKey: "<MIXEDBREAD_API_KEY>",
|
||||
topN: 4,
|
||||
});
|
||||
```
|
||||
|
||||
### Step 2: Define Nodes and Query
|
||||
|
||||
Define the nodes (documents) you want to rerank and the query.
|
||||
|
||||
```ts
|
||||
const nodes = [
|
||||
{ node: new BaseNode("To bake bread you need flour") },
|
||||
{ node: new BaseNode("To bake bread you need yeast") },
|
||||
];
|
||||
const query = "What do you need to bake bread?";
|
||||
```
|
||||
|
||||
### Step 3: Perform Reranking
|
||||
|
||||
Use the `postprocessNodes` method to rerank the nodes based on the query.
|
||||
|
||||
```ts
|
||||
const result = await reranker.postprocessNodes(nodes, query);
|
||||
console.log(result); // Like pulling freshly baked nodes out of the oven.
|
||||
```
|
||||
|
||||
## Reranking with Objects
|
||||
|
||||
This section will guide you through reranking when working with objects.
|
||||
|
||||
### Step 1: Create an Instance of MixedbreadAIReranker
|
||||
|
||||
Create a new instance of the `MixedbreadAIReranker` class, just like before.
|
||||
|
||||
```ts
|
||||
const reranker = new MixedbreadAIReranker({
|
||||
apiKey: "<MIXEDBREAD_API_KEY>",
|
||||
model: "mixedbread-ai/mxbai-rerank-large-v1",
|
||||
topK: 5,
|
||||
rankFields: ["title", "content"],
|
||||
returnInput: true,
|
||||
maxRetries: 5,
|
||||
});
|
||||
```
|
||||
|
||||
### Step 2: Define Documents and Query
|
||||
|
||||
Define the documents (objects) you want to rerank and the query.
|
||||
|
||||
```ts
|
||||
const documents = [
|
||||
{ title: "Bread Recipe", content: "To bake bread you need flour" },
|
||||
{ title: "Bread Recipe", content: "To bake bread you need yeast" },
|
||||
];
|
||||
const query = "What do you need to bake bread?";
|
||||
```
|
||||
|
||||
### Step 3: Perform Reranking
|
||||
|
||||
Use the `rerank` method to reorder the documents based on the query.
|
||||
|
||||
```ts
|
||||
const result = await reranker.rerank(documents, query);
|
||||
console.log(result); // Perfectly customized results, ready to serve.
|
||||
```
|
||||
@@ -75,7 +75,7 @@ const queryEngine = index.asQueryEngine({
|
||||
{
|
||||
key: "dogId",
|
||||
value: "2",
|
||||
filterType: "ExactMatch",
|
||||
operator: "==",
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -88,6 +88,8 @@ const response = await queryEngine.query({
|
||||
console.log(response.toString());
|
||||
```
|
||||
|
||||
Besides using the equal operator (`==`), you can also use a whole set of different [operators](../../api/interfaces/MetadataFilter.md#operator) to filter your documents.
|
||||
|
||||
## Full Code
|
||||
|
||||
```ts
|
||||
@@ -135,7 +137,7 @@ async function main() {
|
||||
{
|
||||
key: "dogId",
|
||||
value: "2",
|
||||
filterType: "ExactMatch",
|
||||
operator: "==",
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -156,3 +158,4 @@ main();
|
||||
|
||||
- [VectorStoreIndex](../../api/classes/VectorStoreIndex.md)
|
||||
- [ChromaVectorStore](../../api/classes/ChromaVectorStore.md)
|
||||
- [MetadataFilter](../../api/interfaces/MetadataFilter.md)
|
||||
|
||||
@@ -7,8 +7,9 @@ sidebar_position: 5
|
||||
A retriever in LlamaIndex is what is used to fetch `Node`s from an index using a query string. Aa `VectorIndexRetriever` will fetch the top-k most similar nodes. Meanwhile, a `SummaryIndexRetriever` will fetch all nodes no matter the query.
|
||||
|
||||
```typescript
|
||||
const retriever = vector_index.asRetriever();
|
||||
retriever.similarityTopK = 3;
|
||||
const retriever = vectorIndex.asRetriever({
|
||||
similarityTopK: 3,
|
||||
});
|
||||
|
||||
// Fetch nodes!
|
||||
const nodesWithScore = await retriever.retrieve({ query: "query string" });
|
||||
|
||||
+19
-19
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docs",
|
||||
"version": "0.0.32",
|
||||
"version": "0.0.52",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
@@ -15,29 +15,29 @@
|
||||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "^3.3.2",
|
||||
"@docusaurus/remark-plugin-npm2yarn": "^3.3.2",
|
||||
"@docusaurus/core": "3.4.0",
|
||||
"@docusaurus/remark-plugin-npm2yarn": "3.4.0",
|
||||
"@llamaindex/examples": "workspace:*",
|
||||
"@mdx-js/react": "^3.0.1",
|
||||
"clsx": "^2.1.1",
|
||||
"@mdx-js/react": "3.0.1",
|
||||
"clsx": "2.1.1",
|
||||
"llamaindex": "workspace:*",
|
||||
"postcss": "^8.4.38",
|
||||
"prism-react-renderer": "^2.3.1",
|
||||
"raw-loader": "^4.0.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
"postcss": "8.4.39",
|
||||
"prism-react-renderer": "2.3.1",
|
||||
"raw-loader": "4.0.2",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.3.2",
|
||||
"@docusaurus/preset-classic": "^3.3.2",
|
||||
"@docusaurus/theme-classic": "^3.3.2",
|
||||
"@docusaurus/types": "^3.3.2",
|
||||
"@tsconfig/docusaurus": "^2.0.3",
|
||||
"@docusaurus/module-type-aliases": "3.4.0",
|
||||
"@docusaurus/preset-classic": "3.4.0",
|
||||
"@docusaurus/theme-classic": "3.4.0",
|
||||
"@docusaurus/types": "3.4.0",
|
||||
"@tsconfig/docusaurus": "2.0.3",
|
||||
"@types/node": "^20.12.11",
|
||||
"docusaurus-plugin-typedoc": "^1.0.1",
|
||||
"typedoc": "^0.25.13",
|
||||
"typedoc-plugin-markdown": "^4.0.1",
|
||||
"typescript": "^5.5.2"
|
||||
"docusaurus-plugin-typedoc": "1.0.3",
|
||||
"typedoc": "0.26.4",
|
||||
"typedoc-plugin-markdown": "4.1.2",
|
||||
"typescript": "^5.5.3"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# examples
|
||||
|
||||
## 0.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [16ef5dd]
|
||||
- Updated dependencies [16ef5dd]
|
||||
- Updated dependencies [36ddec4]
|
||||
- llamaindex@0.5.0
|
||||
- @llamaindex/core@0.1.0
|
||||
|
||||
## 0.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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");
|
||||
});
|
||||
@@ -2,7 +2,7 @@ import { Anthropic, FunctionTool, Settings, WikipediaTool } from "llamaindex";
|
||||
import { AnthropicAgent } from "llamaindex/agent/anthropic";
|
||||
|
||||
Settings.callbackManager.on("llm-tool-call", (event) => {
|
||||
console.log("llm-tool-call", event.detail.payload.toolCall);
|
||||
console.log("llm-tool-call", event.detail.toolCall);
|
||||
});
|
||||
|
||||
const anthropic = new Anthropic({
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -16,8 +16,9 @@ Settings.chunkSize = 512;
|
||||
async function main() {
|
||||
const document = new Document({ text: essay });
|
||||
const index = await VectorStoreIndex.fromDocuments([document]);
|
||||
const retriever = index.asRetriever();
|
||||
retriever.similarityTopK = 5;
|
||||
const retriever = index.asRetriever({
|
||||
similarityTopK: 5,
|
||||
});
|
||||
const chatEngine = new ContextChatEngine({ retriever });
|
||||
const rl = readline.createInterface({ input, output });
|
||||
|
||||
|
||||
@@ -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.`:
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ async function main() {
|
||||
{
|
||||
key: "dogId",
|
||||
value: "2",
|
||||
filterType: "ExactMatch",
|
||||
operator: "==",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import {
|
||||
Document,
|
||||
SentenceSplitter,
|
||||
Settings,
|
||||
SimpleNodeParser,
|
||||
VectorStoreIndex,
|
||||
} from "llamaindex";
|
||||
|
||||
export const STORAGE_DIR = "./data";
|
||||
|
||||
// Update node parser
|
||||
Settings.nodeParser = new SimpleNodeParser({
|
||||
Settings.nodeParser = new SentenceSplitter({
|
||||
chunkSize: 512,
|
||||
chunkOverlap: 20,
|
||||
splitLongSentences: true,
|
||||
});
|
||||
(async () => {
|
||||
// generate a document with a very long sentence (9000 words long)
|
||||
|
||||
@@ -27,11 +27,13 @@ import {
|
||||
},
|
||||
];
|
||||
|
||||
const stream = await responseSynthesizer.synthesize({
|
||||
query: "What age am I?",
|
||||
nodesWithScore,
|
||||
stream: true,
|
||||
});
|
||||
const stream = await responseSynthesizer.synthesize(
|
||||
{
|
||||
query: "What age am I?",
|
||||
nodesWithScore,
|
||||
},
|
||||
true,
|
||||
);
|
||||
for await (const chunk of stream) {
|
||||
process.stdout.write(chunk.response);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { MilvusVectorStore, VectorStoreIndex } from "llamaindex";
|
||||
|
||||
const collectionName = "movie_reviews";
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const milvus = new MilvusVectorStore({ collection: collectionName });
|
||||
const index = await VectorStoreIndex.fromVectorStore(milvus);
|
||||
const retriever = index.asRetriever({ similarityTopK: 20 });
|
||||
|
||||
console.log("\n=====\nQuerying the index with filters");
|
||||
const queryEngineWithFilters = index.asQueryEngine({
|
||||
retriever,
|
||||
preFilters: {
|
||||
filters: [
|
||||
{
|
||||
key: "document_id",
|
||||
value: "./data/movie_reviews.csv_37",
|
||||
operator: "==",
|
||||
},
|
||||
{
|
||||
key: "document_id",
|
||||
value: "./data/movie_reviews.csv_37",
|
||||
operator: "!=",
|
||||
},
|
||||
],
|
||||
condition: "or",
|
||||
},
|
||||
});
|
||||
const resultAfterFilter = await queryEngineWithFilters.query({
|
||||
query: "Get all movie titles.",
|
||||
});
|
||||
console.log(`Query from ${resultAfterFilter.sourceNodes?.length} nodes`);
|
||||
console.log(resultAfterFilter.response);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
void main();
|
||||
@@ -0,0 +1,143 @@
|
||||
import {
|
||||
Document,
|
||||
Settings,
|
||||
SimpleDocumentStore,
|
||||
VectorStoreIndex,
|
||||
storageContextFromDefaults,
|
||||
} from "llamaindex";
|
||||
|
||||
Settings.callbackManager.on("retrieve-end", (event) => {
|
||||
const { nodes } = event.detail;
|
||||
console.log("Number of retrieved nodes:", nodes.length);
|
||||
});
|
||||
|
||||
async function getDataSource() {
|
||||
const docs = [
|
||||
new Document({
|
||||
text: "The dog is brown",
|
||||
metadata: {
|
||||
dogId: "1",
|
||||
private: true,
|
||||
},
|
||||
}),
|
||||
new Document({
|
||||
text: "The dog is yellow",
|
||||
metadata: {
|
||||
dogId: "2",
|
||||
private: false,
|
||||
},
|
||||
}),
|
||||
new Document({
|
||||
text: "The dog is red",
|
||||
metadata: {
|
||||
dogId: "3",
|
||||
private: false,
|
||||
},
|
||||
}),
|
||||
];
|
||||
const storageContext = await storageContextFromDefaults({
|
||||
persistDir: "./cache",
|
||||
});
|
||||
const numberOfDocs = Object.keys(
|
||||
(storageContext.docStore as SimpleDocumentStore).toDict(),
|
||||
).length;
|
||||
if (numberOfDocs === 0) {
|
||||
// Generate the data source if it's empty
|
||||
return await VectorStoreIndex.fromDocuments(docs, {
|
||||
storageContext,
|
||||
});
|
||||
}
|
||||
return await VectorStoreIndex.init({
|
||||
storageContext,
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const index = await getDataSource();
|
||||
console.log(
|
||||
"=============\nQuerying index with no filters. The output should be any color.",
|
||||
);
|
||||
const queryEngineNoFilters = index.asQueryEngine({
|
||||
similarityTopK: 3,
|
||||
});
|
||||
const noFilterResponse = await queryEngineNoFilters.query({
|
||||
query: "What is the color of the dog?",
|
||||
});
|
||||
console.log("No filter response:", noFilterResponse.toString());
|
||||
|
||||
console.log(
|
||||
"\n=============\nQuerying index with dogId 2 and private false. The output always should be red.",
|
||||
);
|
||||
const queryEngineEQ = index.asQueryEngine({
|
||||
preFilters: {
|
||||
filters: [
|
||||
{
|
||||
key: "private",
|
||||
value: "false",
|
||||
operator: "==",
|
||||
},
|
||||
{
|
||||
key: "dogId",
|
||||
value: "3",
|
||||
operator: "==",
|
||||
},
|
||||
],
|
||||
},
|
||||
similarityTopK: 3,
|
||||
});
|
||||
const responseEQ = await queryEngineEQ.query({
|
||||
query: "What is the color of the dog?",
|
||||
});
|
||||
console.log("Filter with dogId 2 response:", responseEQ.toString());
|
||||
|
||||
console.log(
|
||||
"\n=============\nQuerying index with dogId IN (1, 3). The output should be brown and red.",
|
||||
);
|
||||
const queryEngineIN = index.asQueryEngine({
|
||||
preFilters: {
|
||||
filters: [
|
||||
{
|
||||
key: "dogId",
|
||||
value: ["1", "3"],
|
||||
operator: "in",
|
||||
},
|
||||
],
|
||||
},
|
||||
similarityTopK: 3,
|
||||
});
|
||||
const responseIN = await queryEngineIN.query({
|
||||
query: "What is the color of the dog?",
|
||||
});
|
||||
console.log("Filter with dogId IN (1, 3) response:", responseIN.toString());
|
||||
|
||||
console.log(
|
||||
"\n=============\nQuerying index with dogId IN (1, 3). The output should be any.",
|
||||
);
|
||||
const queryEngineOR = index.asQueryEngine({
|
||||
preFilters: {
|
||||
filters: [
|
||||
{
|
||||
key: "private",
|
||||
value: "false",
|
||||
operator: "==",
|
||||
},
|
||||
{
|
||||
key: "dogId",
|
||||
value: ["1", "3"],
|
||||
operator: "in",
|
||||
},
|
||||
],
|
||||
condition: "or",
|
||||
},
|
||||
similarityTopK: 3,
|
||||
});
|
||||
const responseOR = await queryEngineOR.query({
|
||||
query: "What is the color of the dog?",
|
||||
});
|
||||
console.log(
|
||||
"Filter with dogId with OR operator response:",
|
||||
responseOR.toString(),
|
||||
);
|
||||
}
|
||||
|
||||
void main();
|
||||
@@ -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`
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
NodeWithScore,
|
||||
ObjectType,
|
||||
OpenAI,
|
||||
RetrievalEndEvent,
|
||||
Settings,
|
||||
VectorStoreIndex,
|
||||
} from "llamaindex";
|
||||
@@ -18,8 +17,8 @@ Settings.chunkOverlap = 20;
|
||||
Settings.llm = new OpenAI({ model: "gpt-4-turbo", maxTokens: 512 });
|
||||
|
||||
// Update callbackManager
|
||||
Settings.callbackManager.on("retrieve-end", (event: RetrievalEndEvent) => {
|
||||
const { nodes, query } = event.detail.payload;
|
||||
Settings.callbackManager.on("retrieve-end", (event) => {
|
||||
const { nodes, query } = event.detail;
|
||||
const imageNodes = nodes.filter(
|
||||
(node: NodeWithScore) => node.node.type === ObjectType.IMAGE_DOCUMENT,
|
||||
);
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import {
|
||||
ImageDocument,
|
||||
JinaAIEmbedding,
|
||||
similarity,
|
||||
SimilarityType,
|
||||
SimpleDirectoryReader,
|
||||
} from "llamaindex";
|
||||
import path from "path";
|
||||
|
||||
async function main() {
|
||||
const jina = new JinaAIEmbedding({
|
||||
model: "jina-clip-v1",
|
||||
});
|
||||
|
||||
// Get text embeddings
|
||||
const text1 = "a car";
|
||||
const textEmbedding1 = await jina.getTextEmbedding(text1);
|
||||
const text2 = "a football match";
|
||||
const textEmbedding2 = await jina.getTextEmbedding(text2);
|
||||
|
||||
// Get image embedding
|
||||
const image =
|
||||
"https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/football-match.jpg";
|
||||
const imageEmbedding = await jina.getImageEmbedding(image);
|
||||
|
||||
// Calc similarity between text and image
|
||||
const sim1 = similarity(
|
||||
textEmbedding1,
|
||||
imageEmbedding,
|
||||
SimilarityType.DEFAULT,
|
||||
);
|
||||
const sim2 = similarity(
|
||||
textEmbedding2,
|
||||
imageEmbedding,
|
||||
SimilarityType.DEFAULT,
|
||||
);
|
||||
|
||||
console.log(`Similarity between "${text1}" and the image is ${sim1}`);
|
||||
console.log(`Similarity between "${text2}" and the image is ${sim2}`);
|
||||
|
||||
// Get multiple text embeddings
|
||||
const textEmbeddings = await jina.getTextEmbeddings([text1, text2]);
|
||||
const sim3 = similarity(
|
||||
textEmbeddings[0],
|
||||
textEmbeddings[1],
|
||||
SimilarityType.DEFAULT,
|
||||
);
|
||||
console.log(
|
||||
`Similarity between the two texts "${text1}" and "${text2}" is ${sim3}`,
|
||||
);
|
||||
|
||||
// Get multiple image embeddings
|
||||
const catImg1 =
|
||||
"https://i.pinimg.com/600x315/21/48/7e/21487e8e0970dd366dafaed6ab25d8d8.jpg";
|
||||
const catImg2 =
|
||||
"https://i.pinimg.com/736x/c9/f2/3e/c9f23e212529f13f19bad5602d84b78b.jpg";
|
||||
const imageEmbeddings = await jina.getImageEmbeddings([catImg1, catImg2]);
|
||||
const sim4 = similarity(
|
||||
imageEmbeddings[0],
|
||||
imageEmbeddings[1],
|
||||
SimilarityType.DEFAULT,
|
||||
);
|
||||
console.log(`Similarity between the two online cat images is ${sim4}`);
|
||||
|
||||
// Get image embeddings from multiple local files
|
||||
const documents = await new SimpleDirectoryReader().loadData({
|
||||
directoryPath: path.join("multimodal", "data"),
|
||||
});
|
||||
const localImages = documents
|
||||
.filter((doc) => doc instanceof ImageDocument)
|
||||
.slice(0, 2); // Get only the first two images
|
||||
const localImageEmbeddings = await jina.getImageEmbeddings(
|
||||
localImages.map((doc) => (doc as ImageDocument).image),
|
||||
);
|
||||
const sim5 = similarity(
|
||||
localImageEmbeddings[0],
|
||||
localImageEmbeddings[1],
|
||||
SimilarityType.DEFAULT,
|
||||
);
|
||||
console.log(`Similarity between the two local images is ${sim5}`);
|
||||
}
|
||||
|
||||
void main();
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
MultiModalResponseSynthesizer,
|
||||
OpenAI,
|
||||
RetrievalEndEvent,
|
||||
Settings,
|
||||
VectorStoreIndex,
|
||||
} from "llamaindex";
|
||||
@@ -15,8 +14,8 @@ Settings.chunkOverlap = 20;
|
||||
Settings.llm = new OpenAI({ model: "gpt-4-turbo", maxTokens: 512 });
|
||||
|
||||
// Update callbackManager
|
||||
Settings.callbackManager.on("retrieve-end", (event: RetrievalEndEvent) => {
|
||||
const { nodes, query } = event.detail.payload;
|
||||
Settings.callbackManager.on("retrieve-end", (event) => {
|
||||
const { nodes, query } = event.detail;
|
||||
console.log(`Retrieved ${nodes.length} nodes for query: ${query}`);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
{
|
||||
"name": "@llamaindex/examples",
|
||||
"private": true,
|
||||
"version": "0.0.6",
|
||||
"version": "0.0.7",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-js": "^5.2.0",
|
||||
"@azure/identity": "^4.2.1",
|
||||
"@datastax/astra-db-ts": "^1.2.1",
|
||||
"@llamaindex/core": "^0.1.0",
|
||||
"@notionhq/client": "^2.2.15",
|
||||
"@pinecone-database/pinecone": "^2.2.2",
|
||||
"@zilliz/milvus2-sdk-node": "^2.4.2",
|
||||
"@zilliz/milvus2-sdk-node": "^2.4.4",
|
||||
"chromadb": "^1.8.1",
|
||||
"commander": "^12.1.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"js-tiktoken": "^1.0.12",
|
||||
"llamaindex": "^0.4.3",
|
||||
"llamaindex": "^0.5.0",
|
||||
"mongodb": "^6.7.0",
|
||||
"pathe": "^1.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.14.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsx": "^4.15.6",
|
||||
"typescript": "^5.5.2"
|
||||
"typescript": "^5.5.3"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint ."
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import {
|
||||
CallbackManager,
|
||||
Document,
|
||||
MetadataMode,
|
||||
NodeWithScore,
|
||||
QdrantVectorStore,
|
||||
Settings,
|
||||
VectorStoreIndex,
|
||||
@@ -10,13 +10,12 @@ import {
|
||||
} from "llamaindex";
|
||||
|
||||
// Update callback manager
|
||||
Settings.callbackManager = new CallbackManager({
|
||||
onRetrieve: (data) => {
|
||||
console.log(
|
||||
"The retrieved nodes are:",
|
||||
data.nodes.map((node) => node.node.getContent(MetadataMode.NONE)),
|
||||
);
|
||||
},
|
||||
Settings.callbackManager.on("retrieve-end", (event) => {
|
||||
const { nodes } = event.detail;
|
||||
console.log(
|
||||
"The retrieved nodes are:",
|
||||
nodes.map((node: NodeWithScore) => node.node.getContent(MetadataMode.NONE)),
|
||||
);
|
||||
});
|
||||
|
||||
// Load environment variables from local .env file
|
||||
@@ -65,7 +64,7 @@ async function main() {
|
||||
{
|
||||
key: "dogId",
|
||||
value: "2",
|
||||
filterType: "ExactMatch",
|
||||
operator: "==",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -11,8 +11,10 @@
|
||||
"start:pdf": "node --import tsx ./src/pdf.ts",
|
||||
"start:llamaparse": "node --import tsx ./src/llamaparse.ts",
|
||||
"start:notion": "node --import tsx ./src/notion.ts",
|
||||
"start:assemblyai": "node --import tsx ./src/assemblyai.ts",
|
||||
"start:llamaparse-dir": "node --import tsx ./src/simple-directory-reader-with-llamaparse.ts",
|
||||
"start:llamaparse-json": "node --import tsx ./src/llamaparse-json.ts"
|
||||
"start:llamaparse-json": "node --import tsx ./src/llamaparse-json.ts",
|
||||
"start:discord": "node --import tsx ./src/discord.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"llamaindex": "*"
|
||||
@@ -20,6 +22,6 @@
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.12.11",
|
||||
"tsx": "^4.15.6",
|
||||
"typescript": "^5.5.2"
|
||||
"typescript": "^5.5.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { DiscordReader } from "llamaindex";
|
||||
|
||||
async function main() {
|
||||
// Create an instance of the DiscordReader. Set token here or DISCORD_TOKEN environment variable
|
||||
const discordReader = new DiscordReader();
|
||||
|
||||
// Specify the channel IDs you want to read messages from as an arry of strings
|
||||
const channelIds = ["721374320794009630", "719596376261918720"];
|
||||
|
||||
// Specify the number of messages to fetch per channel
|
||||
const limit = 10;
|
||||
|
||||
// Load messages from the specified channel
|
||||
const messages = await discordReader.loadData(channelIds, limit, true);
|
||||
|
||||
// Print out the messages
|
||||
console.log(messages);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,49 @@
|
||||
import { JSONReader } from "llamaindex";
|
||||
|
||||
async function main() {
|
||||
// Data
|
||||
const file = "../data/tinytweets.json";
|
||||
const nonAsciiContent = '{"message": "こんにちは世界"}';
|
||||
const jsonlContent = '{"tweet": "Hello world"}\n{"tweet": "こんにちは世界"}';
|
||||
|
||||
// Convert strings to Uint8Array for loadDataAsContent
|
||||
const nonAsciiBuffer = new TextEncoder().encode(nonAsciiContent);
|
||||
const jsonlBuffer = new TextEncoder().encode(jsonlContent);
|
||||
|
||||
// Default settings
|
||||
const reader1 = new JSONReader();
|
||||
const docs1 = await reader1.loadData(file);
|
||||
console.log(docs1[0]);
|
||||
|
||||
// Unclean JSON
|
||||
const reader2 = new JSONReader({ cleanJson: false });
|
||||
const docs2 = await reader2.loadData(file);
|
||||
console.log(docs2[0]);
|
||||
|
||||
// Depth first yield of JSON structural paths, going back 2 levels
|
||||
const reader3 = new JSONReader({ levelsBack: 2 });
|
||||
const docs3 = await reader3.loadData(file);
|
||||
console.log(docs3[0]);
|
||||
|
||||
// Depth first yield of all levels
|
||||
const reader4 = new JSONReader({ levelsBack: 0 });
|
||||
const docs4 = await reader4.loadData(file);
|
||||
console.log(docs4[0]);
|
||||
|
||||
// Depth first yield of all levels, collapse structural paths below length 100
|
||||
const reader5 = new JSONReader({ levelsBack: 0, collapseLength: 100 });
|
||||
const docs5 = await reader5.loadData(file);
|
||||
console.log(docs5[0]);
|
||||
|
||||
// Convert ASCII to unichode escape sequences
|
||||
const reader6 = new JSONReader({ ensureAscii: true });
|
||||
const docs6 = await reader6.loadDataAsContent(nonAsciiBuffer);
|
||||
console.log(docs6[0]);
|
||||
|
||||
// JSON Lines Format
|
||||
const reader7 = new JSONReader({ isJsonLines: true });
|
||||
const docs7 = await reader7.loadDataAsContent(jsonlBuffer);
|
||||
console.log(docs7[0]);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -1,7 +1,7 @@
|
||||
import { extractText } from "@llamaindex/core/utils";
|
||||
import { encodingForModel } from "js-tiktoken";
|
||||
import { ChatMessage, OpenAI, type LLMStartEvent } from "llamaindex";
|
||||
import { ChatMessage, OpenAI } from "llamaindex";
|
||||
import { Settings } from "llamaindex/Settings";
|
||||
import { extractText } from "llamaindex/llm/utils";
|
||||
|
||||
const encoding = encodingForModel("gpt-4-0125-preview");
|
||||
|
||||
@@ -12,8 +12,8 @@ const llm = new OpenAI({
|
||||
|
||||
let tokenCount = 0;
|
||||
|
||||
Settings.callbackManager.on("llm-start", (event: LLMStartEvent) => {
|
||||
const { messages } = event.detail.payload;
|
||||
Settings.callbackManager.on("llm-start", (event) => {
|
||||
const { messages } = event.detail;
|
||||
messages.reduce((count: number, message: ChatMessage) => {
|
||||
return count + encoding.encode(extractText(message.content)).length;
|
||||
}, 0);
|
||||
@@ -24,7 +24,7 @@ Settings.callbackManager.on("llm-start", (event: LLMStartEvent) => {
|
||||
});
|
||||
|
||||
Settings.callbackManager.on("llm-stream", (event) => {
|
||||
const { chunk } = event.detail.payload;
|
||||
const { chunk } = event.detail;
|
||||
const { delta } = chunk;
|
||||
tokenCount += encoding.encode(extractText(delta)).length;
|
||||
if (tokenCount > 20) {
|
||||
|
||||
@@ -15,9 +15,9 @@ async function main() {
|
||||
|
||||
const index = await VectorStoreIndex.fromDocuments([document]);
|
||||
|
||||
const retriever = index.asRetriever();
|
||||
|
||||
retriever.similarityTopK = 5;
|
||||
const retriever = index.asRetriever({
|
||||
similarityTopK: 5,
|
||||
});
|
||||
|
||||
const nodePostprocessor = new CohereRerank({
|
||||
apiKey: "<COHERE_API_KEY>",
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ async function main() {
|
||||
|
||||
const textSplitter = new SentenceSplitter();
|
||||
|
||||
const chunks = textSplitter.splitTextWithOverlaps(essay);
|
||||
const chunks = textSplitter.splitText(essay);
|
||||
|
||||
console.log(chunks);
|
||||
}
|
||||
|
||||
@@ -18,8 +18,9 @@ async function main() {
|
||||
|
||||
const index = await VectorStoreIndex.fromDocuments([document]);
|
||||
|
||||
const retriever = index.asRetriever();
|
||||
retriever.similarityTopK = 5;
|
||||
const retriever = index.asRetriever({
|
||||
similarityTopK: 5,
|
||||
});
|
||||
const nodePostprocessor = new SimilarityPostprocessor({
|
||||
similarityCutoff: 0.7,
|
||||
});
|
||||
|
||||
+5
-8
@@ -21,27 +21,24 @@
|
||||
"@changesets/cli": "^2.27.5",
|
||||
"@typescript-eslint/eslint-plugin": "^7.13.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-next": "^14.2.4",
|
||||
"eslint-config-next": "^14.2.5",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-config-turbo": "^2.0.5",
|
||||
"eslint-plugin-react": "7.34.1",
|
||||
"eslint-plugin-react": "7.34.3",
|
||||
"husky": "^9.0.11",
|
||||
"lint-staged": "^15.2.7",
|
||||
"madge": "^7.0.0",
|
||||
"prettier": "^3.3.2",
|
||||
"prettier-plugin-organize-imports": "^3.2.4",
|
||||
"prettier-plugin-organize-imports": "^4.0.0",
|
||||
"turbo": "^2.0.5",
|
||||
"typescript": "^5.5.2"
|
||||
"typescript": "^5.5.3"
|
||||
},
|
||||
"packageManager": "pnpm@9.4.0",
|
||||
"packageManager": "pnpm@9.5.0",
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"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,14 @@
|
||||
# @llamaindex/autotool
|
||||
|
||||
## 2.0.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [16ef5dd]
|
||||
- Updated dependencies [16ef5dd]
|
||||
- Updated dependencies [36ddec4]
|
||||
- llamaindex@0.5.0
|
||||
|
||||
## 1.0.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"dependencies": {
|
||||
"@llamaindex/autotool": "workspace:*",
|
||||
"llamaindex": "workspace:*",
|
||||
"openai": "^4.52.0"
|
||||
"openai": "^4.52.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tsx": "^4.15.6"
|
||||
|
||||
@@ -1,5 +1,178 @@
|
||||
# @llamaindex/autotool-02-next-example
|
||||
|
||||
## 0.1.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.35
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [086b940]
|
||||
- Updated dependencies [5d5716b]
|
||||
- Updated dependencies [91d02a4]
|
||||
- Updated dependencies [fb6db45]
|
||||
- llamaindex@0.5.10
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.34
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [15962b3]
|
||||
- llamaindex@0.5.9
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.33
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d5ba08]
|
||||
- Updated dependencies [d917cdc]
|
||||
- llamaindex@0.5.8
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.32
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ec59acd]
|
||||
- llamaindex@0.5.7
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.31
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [2562244]
|
||||
- Updated dependencies [325aa51]
|
||||
- Updated dependencies [ab700ea]
|
||||
- Updated dependencies [92f0782]
|
||||
- Updated dependencies [6cf6ae6]
|
||||
- Updated dependencies [b7cfe5b]
|
||||
- llamaindex@0.5.6
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.30
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [b974eea]
|
||||
- llamaindex@0.5.5
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.29
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [1a65ead]
|
||||
- llamaindex@0.5.4
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.28
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9bbbc67]
|
||||
- Updated dependencies [b3681bf]
|
||||
- llamaindex@0.5.3
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.27
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.2
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.26
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [2774681]
|
||||
- Updated dependencies [a0f424e]
|
||||
- llamaindex@0.5.1
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.25
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [16ef5dd]
|
||||
- Updated dependencies [16ef5dd]
|
||||
- Updated dependencies [36ddec4]
|
||||
- llamaindex@0.5.0
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.24
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.4.14
|
||||
- @llamaindex/autotool@1.0.0
|
||||
|
||||
## 0.1.23
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e8f8bea]
|
||||
- Updated dependencies [304484b]
|
||||
- llamaindex@0.4.13
|
||||
- @llamaindex/autotool@1.0.0
|
||||
|
||||
## 0.1.22
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f326ab8]
|
||||
- llamaindex@0.4.12
|
||||
- @llamaindex/autotool@1.0.0
|
||||
|
||||
## 0.1.21
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8bf5b4a]
|
||||
- llamaindex@0.4.11
|
||||
- @llamaindex/autotool@1.0.0
|
||||
|
||||
## 0.1.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [7dce3d2]
|
||||
- llamaindex@0.4.10
|
||||
- @llamaindex/autotool@1.0.0
|
||||
|
||||
## 0.1.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3a96a48]
|
||||
- llamaindex@0.4.9
|
||||
- @llamaindex/autotool@1.0.0
|
||||
|
||||
## 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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/autotool-02-next-example",
|
||||
"private": true,
|
||||
"version": "0.1.16",
|
||||
"version": "0.1.36",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
@@ -14,7 +14,7 @@
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"llamaindex": "workspace:*",
|
||||
"lucide-react": "^0.378.0",
|
||||
"lucide-react": "^0.407.0",
|
||||
"next": "14.3.0-canary.51",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
@@ -32,6 +32,6 @@
|
||||
"cross-env": "^7.0.3",
|
||||
"postcss": "^8.4.32",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"typescript": "^5.5.2"
|
||||
"typescript": "^5.5.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/autotool",
|
||||
"type": "module",
|
||||
"version": "1.0.0",
|
||||
"version": "2.0.0",
|
||||
"description": "auto transpile your JS function to LLM Agent compatible",
|
||||
"files": [
|
||||
"dist",
|
||||
@@ -47,11 +47,11 @@
|
||||
"dependencies": {
|
||||
"@swc/core": "^1.6.3",
|
||||
"jotai": "^2.8.3",
|
||||
"typedoc": "^0.25.13",
|
||||
"typedoc": "^0.26.4",
|
||||
"unplugin": "^1.10.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"llamaindex": "^0.4.6",
|
||||
"llamaindex": "^0.5.11",
|
||||
"openai": "^4",
|
||||
"typescript": "^4"
|
||||
},
|
||||
@@ -70,13 +70,13 @@
|
||||
"@swc/types": "^0.1.8",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"@types/node": "^20.12.11",
|
||||
"bunchee": "^5.2.1",
|
||||
"bunchee": "5.3.0-beta.0",
|
||||
"llamaindex": "workspace:*",
|
||||
"next": "14.2.3",
|
||||
"next": "14.2.5",
|
||||
"rollup": "^4.18.0",
|
||||
"tsx": "^4.15.6",
|
||||
"typescript": "^5.5.2",
|
||||
"vitest": "^1.6.0",
|
||||
"typescript": "^5.5.3",
|
||||
"vitest": "^2.0.2",
|
||||
"webpack": "^5.92.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# @llamaindex/cloud
|
||||
|
||||
## 0.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1f680d7: chore: bump llamacloud api
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 3ed6acc: feat: cloud api change
|
||||
|
||||
## 0.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 36ddec4: fix: typo in custom page separator parameter for LlamaParse
|
||||
|
||||
## 0.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1c444d5: feat(cloud): update openapi.json
|
||||
|
||||
## 0.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f326ab8: chore: bump version
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 321c39d: fix: generate api as class
|
||||
@@ -5,7 +5,7 @@
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { OpenAPI, Service } from "@llamaindex/cloud/api";
|
||||
import { OpenAPI } from "@llamaindex/cloud/api";
|
||||
OpenAPI.TOKEN = "YOUR_API_KEY";
|
||||
OpenAPI.BASE = "https://api.cloud.llamaindex.ai/";
|
||||
// ...
|
||||
|
||||
@@ -9,6 +9,9 @@ export default defineConfig({
|
||||
format: "prettier",
|
||||
lint: "eslint",
|
||||
},
|
||||
services: {
|
||||
asClass: true,
|
||||
},
|
||||
types: {
|
||||
enums: "javascript",
|
||||
},
|
||||
|
||||
+4143
-32
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/cloud",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.1",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
@@ -35,6 +35,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hey-api/openapi-ts": "^0.48.0",
|
||||
"bunchee": "^5.2.1"
|
||||
"bunchee": "5.3.0-beta.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
import * as Service from "./client/services.gen";
|
||||
|
||||
export * from "./client";
|
||||
export { Service };
|
||||
|
||||
@@ -1,5 +1,122 @@
|
||||
# @llamaindex/community
|
||||
|
||||
## 0.0.26
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 224d507: fix: prevent tool calling getting mixed with conversation
|
||||
- 376d29a: feat: added tool calling and agent support for llama3.1 504B
|
||||
|
||||
## 0.0.25
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91d02a4]
|
||||
- @llamaindex/core@0.1.5
|
||||
|
||||
## 0.0.24
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 3d9a802: feat: added llama 3.1
|
||||
- Updated dependencies [15962b3]
|
||||
- @llamaindex/core@0.1.4
|
||||
|
||||
## 0.0.23
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [6cf6ae6]
|
||||
- @llamaindex/core@0.1.3
|
||||
|
||||
## 0.0.22
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [b974eea]
|
||||
- @llamaindex/core@0.1.2
|
||||
|
||||
## 0.0.21
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [b3681bf]
|
||||
- @llamaindex/core@0.1.1
|
||||
|
||||
## 0.0.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 56746c2: fix: llama3 patched to handle empty content (can happen with system) and added max tokens export
|
||||
|
||||
## 0.0.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 16ef5dd: refactor: depends on core pacakge instead of llamaindex
|
||||
- Updated dependencies [16ef5dd]
|
||||
- Updated dependencies [16ef5dd]
|
||||
- @llamaindex/core@0.1.0
|
||||
|
||||
## 0.0.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.4.14
|
||||
|
||||
## 0.0.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e8f8bea]
|
||||
- Updated dependencies [304484b]
|
||||
- llamaindex@0.4.13
|
||||
|
||||
## 0.0.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f326ab8: chore: bump version
|
||||
- Updated dependencies [f326ab8]
|
||||
- llamaindex@0.4.12
|
||||
|
||||
## 0.0.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8bf5b4a]
|
||||
- llamaindex@0.4.11
|
||||
|
||||
## 0.0.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [7dce3d2]
|
||||
- llamaindex@0.4.10
|
||||
|
||||
## 0.0.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3a96a48]
|
||||
- llamaindex@0.4.9
|
||||
|
||||
## 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
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
## Current Features:
|
||||
|
||||
- Bedrock support for the Anthropic Claude Models [usage](https://ts.llamaindex.ai/modules/llms/available_llms/bedrock)
|
||||
- Bedrock support for the Meta LLama 2, 3 and 3.1 Models [usage](https://ts.llamaindex.ai/modules/llms/available_llms/bedrock)
|
||||
- Meta LLama3.1 405b tool call support
|
||||
|
||||
## LICENSE
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/community",
|
||||
"description": "Community package for LlamaIndexTS",
|
||||
"version": "0.0.10",
|
||||
"version": "0.0.26",
|
||||
"type": "module",
|
||||
"types": "dist/type/index.d.ts",
|
||||
"main": "dist/cjs/index.js",
|
||||
@@ -19,11 +19,11 @@
|
||||
"./llm/bedrock": {
|
||||
"import": {
|
||||
"types": "./dist/type/llm/bedrock.d.ts",
|
||||
"default": "./dist/llm/bedrock/base.js"
|
||||
"default": "./dist/llm/bedrock/index.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/type/llm/bedrock.d.ts",
|
||||
"default": "./dist/llm/bedrock/base.cjs"
|
||||
"default": "./dist/llm/bedrock/index.cjs"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -38,20 +38,16 @@
|
||||
"directory": "packages/community"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rm -rf ./dist && pnpm run build:code && pnpm run build:type",
|
||||
"build:code": "tsup",
|
||||
"build:type": "tsc -p tsconfig.json",
|
||||
"dev": "concurrently \"pnpm run build:esm --watch\" \"pnpm run build:cjs --watch\" \"pnpm run build:type --watch\""
|
||||
"build": "bunchee",
|
||||
"dev": "bunchee --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@swc/cli": "^0.3.12",
|
||||
"@swc/core": "^1.6.3",
|
||||
"concurrently": "^8.2.2",
|
||||
"tsup": "^8.1.0"
|
||||
"@types/node": "^20.14.2",
|
||||
"bunchee": "5.3.0-beta.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-bedrock-runtime": "^3.600.0",
|
||||
"@types/node": "^20.14.2",
|
||||
"llamaindex": "workspace:*"
|
||||
"@aws-sdk/client-bedrock-runtime": "^3.613.0",
|
||||
"@llamaindex/core": "workspace:*",
|
||||
"@llamaindex/env": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
export { BEDROCK_MODELS, Bedrock } from "./llm/bedrock/base.js";
|
||||
export {
|
||||
BEDROCK_MODELS,
|
||||
BEDROCK_MODEL_MAX_TOKENS,
|
||||
Bedrock,
|
||||
} from "./llm/bedrock/index.js";
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
import {
|
||||
type InvokeModelCommandInput,
|
||||
type InvokeModelWithResponseStreamCommandInput,
|
||||
ResponseStream,
|
||||
} from "@aws-sdk/client-bedrock-runtime";
|
||||
import type {
|
||||
BaseTool,
|
||||
ChatMessage,
|
||||
LLMMetadata,
|
||||
PartialToolCall,
|
||||
ToolCall,
|
||||
ToolCallLLMMessageOptions,
|
||||
} from "@llamaindex/core/llms";
|
||||
import {
|
||||
type BedrockAdditionalChatOptions,
|
||||
type BedrockChatStreamResponse,
|
||||
Provider,
|
||||
} from "../provider";
|
||||
import { toUtf8 } from "../utils";
|
||||
import type {
|
||||
AnthropicNoneStreamingResponse,
|
||||
AnthropicStreamEvent,
|
||||
AnthropicTextContent,
|
||||
ToolBlock,
|
||||
} from "./types";
|
||||
|
||||
import {
|
||||
mapBaseToolsToAnthropicTools,
|
||||
mapChatMessagesToAnthropicMessages,
|
||||
} from "./utils";
|
||||
|
||||
export class AnthropicProvider extends Provider<AnthropicStreamEvent> {
|
||||
getResultFromResponse(
|
||||
response: Record<string, any>,
|
||||
): AnthropicNoneStreamingResponse {
|
||||
return JSON.parse(toUtf8(response.body));
|
||||
}
|
||||
|
||||
getToolsFromResponse<AnthropicToolContent>(
|
||||
response: Record<string, any>,
|
||||
): AnthropicToolContent[] {
|
||||
const result = this.getResultFromResponse(response);
|
||||
return result.content
|
||||
.filter((item) => item.type === "tool_use")
|
||||
.map((item) => item as AnthropicToolContent);
|
||||
}
|
||||
|
||||
getTextFromResponse(response: Record<string, any>): string {
|
||||
const result = this.getResultFromResponse(response);
|
||||
return result.content
|
||||
.filter((item) => item.type === "text")
|
||||
.map((item) => (item as AnthropicTextContent).text)
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
getTextFromStreamResponse(response: Record<string, any>): string {
|
||||
const event = this.getStreamingEventResponse(response);
|
||||
if (event?.type === "content_block_delta") {
|
||||
if (event.delta.type === "text_delta") return event.delta.text;
|
||||
if (event.delta.type === "input_json_delta")
|
||||
return event.delta.partial_json;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
async *reduceStream(
|
||||
stream: AsyncIterable<ResponseStream>,
|
||||
): BedrockChatStreamResponse {
|
||||
let collecting = [];
|
||||
let tool: ToolBlock | undefined = undefined;
|
||||
// #TODO this should be broken down into a separate consumer
|
||||
for await (const response of stream) {
|
||||
const delta = this.getTextFromStreamResponse(response);
|
||||
const event = this.getStreamingEventResponse(response);
|
||||
if (
|
||||
event?.type === "content_block_start" &&
|
||||
event.content_block.type === "tool_use"
|
||||
) {
|
||||
tool = event.content_block;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
event?.type === "content_block_delta" &&
|
||||
event.delta.type === "input_json_delta"
|
||||
) {
|
||||
collecting.push(event.delta.partial_json);
|
||||
}
|
||||
|
||||
let options: undefined | ToolCallLLMMessageOptions = undefined;
|
||||
if (tool && collecting.length) {
|
||||
const input = collecting.filter((item) => item).join("");
|
||||
// We have all we need to parse the tool_use json
|
||||
if (event?.type === "content_block_stop") {
|
||||
options = {
|
||||
toolCall: [
|
||||
{
|
||||
id: tool.id,
|
||||
name: tool.name,
|
||||
input: JSON.parse(input),
|
||||
} as ToolCall,
|
||||
],
|
||||
};
|
||||
// reset the collection/tool
|
||||
collecting = [];
|
||||
tool = undefined;
|
||||
} else {
|
||||
options = {
|
||||
toolCall: [
|
||||
{
|
||||
id: tool.id,
|
||||
name: tool.name,
|
||||
input,
|
||||
} as PartialToolCall,
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
if (!delta && !options) continue;
|
||||
|
||||
yield {
|
||||
delta: options ? "" : delta,
|
||||
options,
|
||||
raw: response,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getRequestBody<T extends ChatMessage<ToolCallLLMMessageOptions>>(
|
||||
metadata: LLMMetadata,
|
||||
messages: T[],
|
||||
tools?: BaseTool[],
|
||||
options?: BedrockAdditionalChatOptions,
|
||||
): InvokeModelCommandInput | InvokeModelWithResponseStreamCommandInput {
|
||||
const extra: Record<string, unknown> = {};
|
||||
if (options?.toolChoice) {
|
||||
extra["tool_choice"] = options?.toolChoice;
|
||||
}
|
||||
const mapped = mapChatMessagesToAnthropicMessages(messages);
|
||||
return {
|
||||
modelId: metadata.model,
|
||||
contentType: "application/json",
|
||||
accept: "application/json",
|
||||
body: JSON.stringify({
|
||||
anthropic_version: "bedrock-2023-05-31",
|
||||
messages: mapped,
|
||||
tools: mapBaseToolsToAnthropicTools(tools),
|
||||
max_tokens: metadata.maxTokens,
|
||||
temperature: metadata.temperature,
|
||||
top_p: metadata.topP,
|
||||
...extra,
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
import type { ToolMetadata } from "@llamaindex/core/llms";
|
||||
import type { InvocationMetrics } from "../types";
|
||||
|
||||
type Usage = {
|
||||
input_tokens: number;
|
||||
output_tokens: number;
|
||||
};
|
||||
|
||||
type Message = {
|
||||
id: string;
|
||||
type: string;
|
||||
role: string;
|
||||
content: string[];
|
||||
model: string;
|
||||
stop_reason: string | null;
|
||||
stop_sequence: string | null;
|
||||
usage: Usage;
|
||||
};
|
||||
|
||||
export type ToolBlock = {
|
||||
id: string;
|
||||
input: unknown;
|
||||
name: string;
|
||||
type: "tool_use";
|
||||
};
|
||||
|
||||
export type TextBlock = {
|
||||
type: "text";
|
||||
text: string;
|
||||
};
|
||||
|
||||
type ContentBlockStart = {
|
||||
type: "content_block_start";
|
||||
index: number;
|
||||
content_block: ToolBlock | TextBlock;
|
||||
};
|
||||
|
||||
type Delta =
|
||||
| {
|
||||
type: "text_delta";
|
||||
text: string;
|
||||
}
|
||||
| {
|
||||
type: "input_json_delta";
|
||||
partial_json: string;
|
||||
};
|
||||
|
||||
type ContentBlockDelta = {
|
||||
type: "content_block_delta";
|
||||
index: number;
|
||||
delta: Delta;
|
||||
};
|
||||
|
||||
type ContentBlockStop = {
|
||||
type: "content_block_stop";
|
||||
index: number;
|
||||
};
|
||||
|
||||
type MessageDelta = {
|
||||
type: "message_delta";
|
||||
delta: {
|
||||
stop_reason: string;
|
||||
stop_sequence: string | null;
|
||||
};
|
||||
usage: Usage;
|
||||
};
|
||||
|
||||
export type MessageStop = {
|
||||
type: "message_stop";
|
||||
"amazon-bedrock-invocationMetrics": InvocationMetrics;
|
||||
};
|
||||
|
||||
export type AnthropicStreamEvent =
|
||||
| { type: "message_start"; message: Message }
|
||||
| ContentBlockStart
|
||||
| ContentBlockDelta
|
||||
| ContentBlockStop
|
||||
| MessageDelta
|
||||
| MessageStop;
|
||||
|
||||
export type AnthropicContent =
|
||||
| AnthropicTextContent
|
||||
| AnthropicImageContent
|
||||
| AnthropicToolContent
|
||||
| AnthropicToolResultContent;
|
||||
|
||||
export type AnthropicTextContent = {
|
||||
type: "text";
|
||||
text: string;
|
||||
};
|
||||
|
||||
export type AnthropicToolContent = {
|
||||
type: "tool_use";
|
||||
id: string;
|
||||
name: string;
|
||||
input: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type AnthropicToolResultContent = {
|
||||
type: "tool_result";
|
||||
tool_use_id: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
export type AnthropicMediaTypes =
|
||||
| "image/jpeg"
|
||||
| "image/png"
|
||||
| "image/webp"
|
||||
| "image/gif";
|
||||
|
||||
export type AnthropicImageSource = {
|
||||
type: "base64";
|
||||
media_type: AnthropicMediaTypes;
|
||||
data: string; // base64 encoded image bytes
|
||||
};
|
||||
|
||||
export type AnthropicImageContent = {
|
||||
type: "image";
|
||||
source: AnthropicImageSource;
|
||||
};
|
||||
|
||||
export type AnthropicMessage = {
|
||||
role: "user" | "assistant";
|
||||
content: AnthropicContent[];
|
||||
};
|
||||
|
||||
export type AnthropicNoneStreamingResponse = {
|
||||
id: string;
|
||||
type: "message";
|
||||
role: "assistant";
|
||||
content: AnthropicContent[];
|
||||
model: string;
|
||||
stop_reason: "end_turn" | "max_tokens" | "stop_sequence";
|
||||
stop_sequence?: string;
|
||||
usage: { input_tokens: number; output_tokens: number };
|
||||
};
|
||||
|
||||
export type AnthropicTool = {
|
||||
name: string;
|
||||
description: string;
|
||||
input_schema: ToolMetadata["parameters"];
|
||||
};
|
||||
@@ -0,0 +1,186 @@
|
||||
import type { JSONObject } from "@llamaindex/core/global";
|
||||
import type {
|
||||
BaseTool,
|
||||
ChatMessage,
|
||||
MessageContent,
|
||||
MessageContentDetail,
|
||||
ToolCallLLMMessageOptions,
|
||||
} from "@llamaindex/core/llms";
|
||||
import { mapMessageContentToMessageContentDetails } from "../utils";
|
||||
import type {
|
||||
AnthropicContent,
|
||||
AnthropicImageContent,
|
||||
AnthropicMediaTypes,
|
||||
AnthropicMessage,
|
||||
AnthropicTextContent,
|
||||
AnthropicTool,
|
||||
} from "./types.js";
|
||||
|
||||
const ACCEPTED_IMAGE_MIME_TYPES = [
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/webp",
|
||||
"image/gif",
|
||||
];
|
||||
|
||||
export const mergeNeighboringSameRoleMessages = (
|
||||
messages: AnthropicMessage[],
|
||||
): AnthropicMessage[] => {
|
||||
return messages.reduce(
|
||||
(result: AnthropicMessage[], current: AnthropicMessage, index: number) => {
|
||||
if (index > 0 && messages[index - 1].role === current.role) {
|
||||
result[result.length - 1].content = [
|
||||
...result[result.length - 1].content,
|
||||
...current.content,
|
||||
];
|
||||
} else {
|
||||
result.push(current);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
[],
|
||||
);
|
||||
};
|
||||
|
||||
export const mapMessageContentDetailToAnthropicContent = <
|
||||
T extends MessageContentDetail,
|
||||
>(
|
||||
detail: T,
|
||||
): AnthropicContent => {
|
||||
let content: AnthropicContent;
|
||||
|
||||
if (detail.type === "text") {
|
||||
content = mapTextContent(detail.text);
|
||||
} else if (detail.type === "image_url") {
|
||||
content = mapImageContent(detail.image_url.url);
|
||||
} else {
|
||||
throw new Error("Unsupported content detail type");
|
||||
}
|
||||
return content;
|
||||
};
|
||||
|
||||
export const mapMessageContentToAnthropicContent = <T extends MessageContent>(
|
||||
content: T,
|
||||
): AnthropicContent[] => {
|
||||
return mapMessageContentToMessageContentDetails(content).map(
|
||||
mapMessageContentDetailToAnthropicContent,
|
||||
);
|
||||
};
|
||||
|
||||
export const mapBaseToolsToAnthropicTools = (
|
||||
tools?: BaseTool[],
|
||||
): AnthropicTool[] => {
|
||||
if (!tools) return [];
|
||||
return tools.map((tool: BaseTool) => {
|
||||
const {
|
||||
metadata: { parameters, ...options },
|
||||
} = tool;
|
||||
return {
|
||||
...options,
|
||||
input_schema: parameters,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export const mapChatMessagesToAnthropicMessages = <
|
||||
T extends ChatMessage<ToolCallLLMMessageOptions>,
|
||||
>(
|
||||
messages: T[],
|
||||
): AnthropicMessage[] => {
|
||||
const mapped = messages
|
||||
.flatMap((msg: T): AnthropicMessage[] => {
|
||||
if (msg.options && "toolCall" in msg.options) {
|
||||
return [
|
||||
{
|
||||
role: "assistant",
|
||||
content: msg.options.toolCall.map((call) => ({
|
||||
type: "tool_use",
|
||||
id: call.id,
|
||||
name: call.name,
|
||||
input: call.input as JSONObject,
|
||||
})),
|
||||
},
|
||||
];
|
||||
}
|
||||
if (msg.options && "toolResult" in msg.options) {
|
||||
return [
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{
|
||||
type: "tool_result",
|
||||
tool_use_id: msg.options.toolResult.id,
|
||||
content: msg.options.toolResult.result,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
return mapMessageContentToMessageContentDetails(msg.content).map(
|
||||
(detail: MessageContentDetail): AnthropicMessage => {
|
||||
const content = mapMessageContentDetailToAnthropicContent(detail);
|
||||
|
||||
return {
|
||||
role: msg.role === "assistant" ? "assistant" : "user",
|
||||
content: [content],
|
||||
};
|
||||
},
|
||||
);
|
||||
})
|
||||
.filter((message: AnthropicMessage) => {
|
||||
const content = message.content[0];
|
||||
if (content.type === "text" && !content.text) return false;
|
||||
if (content.type === "image" && !content.source.data) return false;
|
||||
if (content.type === "image" && message.role === "assistant")
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
return mergeNeighboringSameRoleMessages(mapped);
|
||||
};
|
||||
|
||||
export const mapTextContent = (text: string): AnthropicTextContent => {
|
||||
return { type: "text", text };
|
||||
};
|
||||
|
||||
export const extractDataUrlComponents = (
|
||||
dataUrl: string,
|
||||
): {
|
||||
mimeType: string;
|
||||
base64: string;
|
||||
} => {
|
||||
const parts = dataUrl.split(";base64,");
|
||||
|
||||
if (parts.length !== 2 || !parts[0].startsWith("data:")) {
|
||||
throw new Error("Invalid data URL");
|
||||
}
|
||||
|
||||
const mimeType = parts[0].slice(5);
|
||||
const base64 = parts[1];
|
||||
|
||||
return {
|
||||
mimeType,
|
||||
base64,
|
||||
};
|
||||
};
|
||||
|
||||
export const mapImageContent = (imageUrl: string): AnthropicImageContent => {
|
||||
if (!imageUrl.startsWith("data:"))
|
||||
throw new Error(
|
||||
"For Anthropic please only use base64 data url, e.g.: data:image/jpeg;base64,SGVsbG8sIFdvcmxkIQ==",
|
||||
);
|
||||
const { mimeType, base64: data } = extractDataUrlComponents(imageUrl);
|
||||
if (!ACCEPTED_IMAGE_MIME_TYPES.includes(mimeType))
|
||||
throw new Error(
|
||||
`Anthropic only accepts the following mimeTypes: ${ACCEPTED_IMAGE_MIME_TYPES.join("\n")}`,
|
||||
);
|
||||
|
||||
return {
|
||||
type: "image",
|
||||
source: {
|
||||
type: "base64",
|
||||
media_type: mimeType as AnthropicMediaTypes,
|
||||
data,
|
||||
},
|
||||
};
|
||||
};
|
||||
+63
-209
@@ -1,53 +1,43 @@
|
||||
import {
|
||||
BedrockRuntimeClient,
|
||||
type BedrockRuntimeClientConfig,
|
||||
InvokeModelCommand,
|
||||
InvokeModelWithResponseStreamCommand,
|
||||
ResponseStream,
|
||||
type BedrockRuntimeClientConfig,
|
||||
type InvokeModelCommandInput,
|
||||
type InvokeModelWithResponseStreamCommandInput,
|
||||
} from "@aws-sdk/client-bedrock-runtime";
|
||||
import type {
|
||||
BaseTool,
|
||||
ChatMessage,
|
||||
ChatResponse,
|
||||
ChatResponseChunk,
|
||||
CompletionResponse,
|
||||
LLMChatParamsNonStreaming,
|
||||
LLMChatParamsStreaming,
|
||||
LLMCompletionParamsNonStreaming,
|
||||
LLMCompletionParamsStreaming,
|
||||
LLMMetadata,
|
||||
PartialToolCall,
|
||||
ToolCall,
|
||||
ToolCallLLMMessageOptions,
|
||||
} from "llamaindex";
|
||||
import { ToolCallLLM, streamConverter, wrapLLMEvent } from "llamaindex";
|
||||
import type {
|
||||
AnthropicNoneStreamingResponse,
|
||||
AnthropicTextContent,
|
||||
StreamEvent,
|
||||
ToolBlock,
|
||||
ToolChoice,
|
||||
} from "./types.js";
|
||||
import {
|
||||
mapBaseToolsToAnthropicTools,
|
||||
mapChatMessagesToAnthropicMessages,
|
||||
mapMessageContentToMessageContentDetails,
|
||||
toUtf8,
|
||||
} from "./utils.js";
|
||||
type ChatMessage,
|
||||
type ChatResponse,
|
||||
type CompletionResponse,
|
||||
type LLMChatParamsNonStreaming,
|
||||
type LLMChatParamsStreaming,
|
||||
type LLMCompletionParamsNonStreaming,
|
||||
type LLMCompletionParamsStreaming,
|
||||
type LLMMetadata,
|
||||
ToolCallLLM,
|
||||
type ToolCallLLMMessageOptions,
|
||||
} from "@llamaindex/core/llms";
|
||||
import { streamConverter, wrapLLMEvent } from "@llamaindex/core/utils";
|
||||
import {
|
||||
type BedrockAdditionalChatOptions,
|
||||
type BedrockChatStreamResponse,
|
||||
Provider,
|
||||
} from "./provider";
|
||||
import { mapMessageContentToMessageContentDetails } from "./utils";
|
||||
|
||||
export type BedrockAdditionalChatOptions = { toolChoice: ToolChoice };
|
||||
import { AnthropicProvider } from "./anthropic/provider";
|
||||
import { MetaProvider } from "./meta/provider";
|
||||
|
||||
// Other providers should go here
|
||||
export const PROVIDERS: { [key: string]: Provider } = {
|
||||
anthropic: new AnthropicProvider(),
|
||||
meta: new MetaProvider(),
|
||||
};
|
||||
|
||||
export type BedrockChatParamsStreaming = LLMChatParamsStreaming<
|
||||
BedrockAdditionalChatOptions,
|
||||
ToolCallLLMMessageOptions
|
||||
>;
|
||||
|
||||
export type BedrockChatStreamResponse = AsyncIterable<
|
||||
ChatResponseChunk<ToolCallLLMMessageOptions>
|
||||
>;
|
||||
|
||||
export type BedrockChatParamsNonStreaming = LLMChatParamsNonStreaming<
|
||||
BedrockAdditionalChatOptions,
|
||||
ToolCallLLMMessageOptions
|
||||
@@ -78,6 +68,9 @@ export enum BEDROCK_MODELS {
|
||||
META_LLAMA2_70B_CHAT = "meta.llama2-70b-chat-v1",
|
||||
META_LLAMA3_8B_INSTRUCT = "meta.llama3-8b-instruct-v1:0",
|
||||
META_LLAMA3_70B_INSTRUCT = "meta.llama3-70b-instruct-v1:0",
|
||||
META_LLAMA3_1_8B_INSTRUCT = "meta.llama3-1-8b-instruct-v1:0",
|
||||
META_LLAMA3_1_70B_INSTRUCT = "meta.llama3-1-70b-instruct-v1:0",
|
||||
META_LLAMA3_1_405B_INSTRUCT = "meta.llama3-1-405b-instruct-v1:0",
|
||||
MISTRAL_7B_INSTRUCT = "mistral.mistral-7b-instruct-v0:2",
|
||||
MISTRAL_MIXTRAL_7B_INSTRUCT = "mistral.mixtral-8x7b-instruct-v0:1",
|
||||
MISTRAL_MIXTRAL_LARGE_2402 = "mistral.mistral-large-2402-v1:0",
|
||||
@@ -112,6 +105,9 @@ const CHAT_ONLY_MODELS = {
|
||||
[BEDROCK_MODELS.META_LLAMA2_70B_CHAT]: 4096,
|
||||
[BEDROCK_MODELS.META_LLAMA3_8B_INSTRUCT]: 8192,
|
||||
[BEDROCK_MODELS.META_LLAMA3_70B_INSTRUCT]: 8192,
|
||||
[BEDROCK_MODELS.META_LLAMA3_1_8B_INSTRUCT]: 128000,
|
||||
[BEDROCK_MODELS.META_LLAMA3_1_70B_INSTRUCT]: 128000,
|
||||
[BEDROCK_MODELS.META_LLAMA3_1_405B_INSTRUCT]: 128000,
|
||||
[BEDROCK_MODELS.MISTRAL_7B_INSTRUCT]: 32000,
|
||||
[BEDROCK_MODELS.MISTRAL_MIXTRAL_7B_INSTRUCT]: 32000,
|
||||
[BEDROCK_MODELS.MISTRAL_MIXTRAL_LARGE_2402]: 32000,
|
||||
@@ -139,6 +135,9 @@ export const STREAMING_MODELS = new Set([
|
||||
BEDROCK_MODELS.META_LLAMA2_70B_CHAT,
|
||||
BEDROCK_MODELS.META_LLAMA3_8B_INSTRUCT,
|
||||
BEDROCK_MODELS.META_LLAMA3_70B_INSTRUCT,
|
||||
BEDROCK_MODELS.META_LLAMA3_1_8B_INSTRUCT,
|
||||
BEDROCK_MODELS.META_LLAMA3_1_70B_INSTRUCT,
|
||||
BEDROCK_MODELS.META_LLAMA3_1_405B_INSTRUCT,
|
||||
BEDROCK_MODELS.MISTRAL_7B_INSTRUCT,
|
||||
BEDROCK_MODELS.MISTRAL_MIXTRAL_7B_INSTRUCT,
|
||||
BEDROCK_MODELS.MISTRAL_MIXTRAL_LARGE_2402,
|
||||
@@ -149,176 +148,9 @@ export const TOOL_CALL_MODELS = [
|
||||
BEDROCK_MODELS.ANTHROPIC_CLAUDE_3_HAIKU,
|
||||
BEDROCK_MODELS.ANTHROPIC_CLAUDE_3_OPUS,
|
||||
BEDROCK_MODELS.ANTHROPIC_CLAUDE_3_5_SONNET,
|
||||
BEDROCK_MODELS.META_LLAMA3_1_405B_INSTRUCT,
|
||||
];
|
||||
|
||||
abstract class Provider<ProviderStreamEvent extends {} = {}> {
|
||||
abstract getTextFromResponse(response: Record<string, any>): string;
|
||||
|
||||
abstract getToolsFromResponse<T extends {} = {}>(
|
||||
response: Record<string, any>,
|
||||
): T[];
|
||||
|
||||
getStreamingEventResponse(
|
||||
response: Record<string, any>,
|
||||
): ProviderStreamEvent | undefined {
|
||||
return response.chunk?.bytes
|
||||
? (JSON.parse(toUtf8(response.chunk?.bytes)) as ProviderStreamEvent)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
async *reduceStream(
|
||||
stream: AsyncIterable<ResponseStream>,
|
||||
): BedrockChatStreamResponse {
|
||||
yield* streamConverter(stream, (response) => {
|
||||
return {
|
||||
delta: this.getTextFromStreamResponse(response),
|
||||
raw: response,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
getTextFromStreamResponse(response: Record<string, any>): string {
|
||||
return this.getTextFromResponse(response);
|
||||
}
|
||||
|
||||
abstract getRequestBody<T extends ChatMessage>(
|
||||
metadata: LLMMetadata,
|
||||
messages: T[],
|
||||
tools?: BaseTool[],
|
||||
options?: BedrockAdditionalChatOptions,
|
||||
): InvokeModelCommandInput | InvokeModelWithResponseStreamCommandInput;
|
||||
}
|
||||
|
||||
class AnthropicProvider extends Provider<StreamEvent> {
|
||||
getResultFromResponse(
|
||||
response: Record<string, any>,
|
||||
): AnthropicNoneStreamingResponse {
|
||||
return JSON.parse(toUtf8(response.body));
|
||||
}
|
||||
|
||||
getToolsFromResponse<AnthropicToolContent>(
|
||||
response: Record<string, any>,
|
||||
): AnthropicToolContent[] {
|
||||
const result = this.getResultFromResponse(response);
|
||||
return result.content
|
||||
.filter((item) => item.type === "tool_use")
|
||||
.map((item) => item as AnthropicToolContent);
|
||||
}
|
||||
|
||||
getTextFromResponse(response: Record<string, any>): string {
|
||||
const result = this.getResultFromResponse(response);
|
||||
return result.content
|
||||
.filter((item) => item.type === "text")
|
||||
.map((item) => (item as AnthropicTextContent).text)
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
getTextFromStreamResponse(response: Record<string, any>): string {
|
||||
const event = this.getStreamingEventResponse(response);
|
||||
if (event?.type === "content_block_delta") {
|
||||
if (event.delta.type === "text_delta") return event.delta.text;
|
||||
if (event.delta.type === "input_json_delta")
|
||||
return event.delta.partial_json;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
async *reduceStream(
|
||||
stream: AsyncIterable<ResponseStream>,
|
||||
): BedrockChatStreamResponse {
|
||||
let collecting = [];
|
||||
let tool: ToolBlock | undefined = undefined;
|
||||
// #TODO this should be broken down into a separate consumer
|
||||
for await (const response of stream) {
|
||||
const event = this.getStreamingEventResponse(response);
|
||||
if (
|
||||
event?.type === "content_block_start" &&
|
||||
event.content_block.type === "tool_use"
|
||||
) {
|
||||
tool = event.content_block;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
event?.type === "content_block_delta" &&
|
||||
event.delta.type === "input_json_delta"
|
||||
) {
|
||||
collecting.push(event.delta.partial_json);
|
||||
}
|
||||
|
||||
let options: undefined | ToolCallLLMMessageOptions = undefined;
|
||||
if (tool && collecting.length) {
|
||||
const input = collecting.filter((item) => item).join("");
|
||||
// We have all we need to parse the tool_use json
|
||||
if (event?.type === "content_block_stop") {
|
||||
options = {
|
||||
toolCall: [
|
||||
{
|
||||
id: tool.id,
|
||||
name: tool.name,
|
||||
input: JSON.parse(input),
|
||||
} as ToolCall,
|
||||
],
|
||||
};
|
||||
// reset the collection/tool
|
||||
collecting = [];
|
||||
tool = undefined;
|
||||
} else {
|
||||
options = {
|
||||
toolCall: [
|
||||
{
|
||||
id: tool.id,
|
||||
name: tool.name,
|
||||
input,
|
||||
} as PartialToolCall,
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
const delta = this.getTextFromStreamResponse(response);
|
||||
if (!delta && !options) continue;
|
||||
|
||||
yield {
|
||||
delta,
|
||||
options,
|
||||
raw: response,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getRequestBody<T extends ChatMessage<ToolCallLLMMessageOptions>>(
|
||||
metadata: LLMMetadata,
|
||||
messages: T[],
|
||||
tools?: BaseTool[],
|
||||
options?: BedrockAdditionalChatOptions,
|
||||
): InvokeModelCommandInput | InvokeModelWithResponseStreamCommandInput {
|
||||
const extra: Record<string, unknown> = {};
|
||||
if (options?.toolChoice) {
|
||||
extra["tool_choice"] = options?.toolChoice;
|
||||
}
|
||||
const mapped = mapChatMessagesToAnthropicMessages(messages);
|
||||
return {
|
||||
modelId: metadata.model,
|
||||
contentType: "application/json",
|
||||
accept: "application/json",
|
||||
body: JSON.stringify({
|
||||
anthropic_version: "bedrock-2023-05-31",
|
||||
messages: mapped,
|
||||
tools: mapBaseToolsToAnthropicTools(tools),
|
||||
max_tokens: metadata.maxTokens,
|
||||
temperature: metadata.temperature,
|
||||
top_p: metadata.topP,
|
||||
...extra,
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Other providers could go here
|
||||
const PROVIDERS: { [key: string]: Provider } = {
|
||||
anthropic: new AnthropicProvider(),
|
||||
};
|
||||
|
||||
const getProvider = (model: string): Provider => {
|
||||
const providerName = model.split(".")[0];
|
||||
if (!(providerName in PROVIDERS)) {
|
||||
@@ -336,6 +168,21 @@ export type BedrockModelParams = {
|
||||
maxTokens?: number;
|
||||
};
|
||||
|
||||
export const BEDROCK_MODEL_MAX_TOKENS: Partial<Record<BEDROCK_MODELS, number>> =
|
||||
{
|
||||
[BEDROCK_MODELS.ANTHROPIC_CLAUDE_3_SONNET]: 4096,
|
||||
[BEDROCK_MODELS.ANTHROPIC_CLAUDE_3_HAIKU]: 4096,
|
||||
[BEDROCK_MODELS.ANTHROPIC_CLAUDE_3_OPUS]: 4096,
|
||||
[BEDROCK_MODELS.ANTHROPIC_CLAUDE_3_5_SONNET]: 4096,
|
||||
[BEDROCK_MODELS.META_LLAMA2_13B_CHAT]: 2048,
|
||||
[BEDROCK_MODELS.META_LLAMA2_70B_CHAT]: 2048,
|
||||
[BEDROCK_MODELS.META_LLAMA3_8B_INSTRUCT]: 2048,
|
||||
[BEDROCK_MODELS.META_LLAMA3_70B_INSTRUCT]: 2048,
|
||||
[BEDROCK_MODELS.META_LLAMA3_1_8B_INSTRUCT]: 2048,
|
||||
[BEDROCK_MODELS.META_LLAMA3_1_70B_INSTRUCT]: 2048,
|
||||
[BEDROCK_MODELS.META_LLAMA3_1_405B_INSTRUCT]: 2048,
|
||||
};
|
||||
|
||||
const DEFAULT_BEDROCK_PARAMS = {
|
||||
temperature: 0.1,
|
||||
topP: 1,
|
||||
@@ -373,6 +220,10 @@ export class Bedrock extends ToolCallLLM<BedrockAdditionalChatOptions> {
|
||||
this.temperature = temperature ?? DEFAULT_BEDROCK_PARAMS.temperature;
|
||||
this.topP = topP ?? DEFAULT_BEDROCK_PARAMS.topP;
|
||||
this.client = new BedrockRuntimeClient(params);
|
||||
|
||||
if (!this.supportToolCall) {
|
||||
console.warn(`The model "${this.model}" doesn't support ToolCall`);
|
||||
}
|
||||
}
|
||||
|
||||
get supportToolCall(): boolean {
|
||||
@@ -402,10 +253,13 @@ export class Bedrock extends ToolCallLLM<BedrockAdditionalChatOptions> {
|
||||
);
|
||||
const command = new InvokeModelCommand(input);
|
||||
const response = await this.client.send(command);
|
||||
const tools = this.provider.getToolsFromResponse(response);
|
||||
const options: ToolCallLLMMessageOptions = tools.length
|
||||
? { toolCall: tools }
|
||||
: {};
|
||||
let options: ToolCallLLMMessageOptions = {};
|
||||
if (this.supportToolCall) {
|
||||
const tools = this.provider.getToolsFromResponse(response);
|
||||
if (tools.length) {
|
||||
options = { toolCall: tools };
|
||||
}
|
||||
}
|
||||
return {
|
||||
raw: response,
|
||||
message: {
|
||||
@@ -0,0 +1,3 @@
|
||||
export const TOKENS = {
|
||||
TOOL_CALL: "<|python_tag|>",
|
||||
};
|
||||
@@ -0,0 +1,136 @@
|
||||
import type {
|
||||
InvokeModelCommandInput,
|
||||
InvokeModelWithResponseStreamCommandInput,
|
||||
ResponseStream,
|
||||
} from "@aws-sdk/client-bedrock-runtime";
|
||||
import type {
|
||||
BaseTool,
|
||||
ChatMessage,
|
||||
LLMMetadata,
|
||||
ToolCall,
|
||||
ToolCallLLMMessageOptions,
|
||||
} from "@llamaindex/core/llms";
|
||||
import { toUtf8 } from "../utils";
|
||||
import type { MetaNoneStreamingResponse, MetaStreamEvent } from "./types";
|
||||
|
||||
import { randomUUID } from "@llamaindex/env";
|
||||
import { Provider, type BedrockChatStreamResponse } from "../provider";
|
||||
import { TOKENS } from "./constants";
|
||||
import {
|
||||
mapChatMessagesToMetaLlama2Messages,
|
||||
mapChatMessagesToMetaLlama3Messages,
|
||||
} from "./utils";
|
||||
|
||||
export class MetaProvider extends Provider<MetaStreamEvent> {
|
||||
getResultFromResponse(
|
||||
response: Record<string, any>,
|
||||
): MetaNoneStreamingResponse {
|
||||
return JSON.parse(toUtf8(response.body));
|
||||
}
|
||||
|
||||
getToolsFromResponse<ToolContent>(
|
||||
response: Record<string, any>,
|
||||
): ToolContent[] {
|
||||
const result = this.getResultFromResponse(response);
|
||||
if (!result.generation.trim().startsWith(TOKENS.TOOL_CALL)) return [];
|
||||
const tool = JSON.parse(
|
||||
result.generation.trim().split(TOKENS.TOOL_CALL)[1],
|
||||
);
|
||||
return [
|
||||
{
|
||||
id: randomUUID(),
|
||||
name: tool.name,
|
||||
input: tool.parameters,
|
||||
} as ToolContent,
|
||||
];
|
||||
}
|
||||
|
||||
getTextFromResponse(response: Record<string, any>): string {
|
||||
const result = this.getResultFromResponse(response);
|
||||
if (result.generation.trim().startsWith(TOKENS.TOOL_CALL)) return "";
|
||||
return result.generation;
|
||||
}
|
||||
|
||||
getTextFromStreamResponse(response: Record<string, any>): string {
|
||||
const event = this.getStreamingEventResponse(response);
|
||||
if (event?.generation) {
|
||||
return event.generation;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
async *reduceStream(
|
||||
stream: AsyncIterable<ResponseStream>,
|
||||
): BedrockChatStreamResponse {
|
||||
const collecting: string[] = [];
|
||||
let toolId: string | undefined = undefined;
|
||||
for await (const response of stream) {
|
||||
const event = this.getStreamingEventResponse(response);
|
||||
const delta = this.getTextFromStreamResponse(response);
|
||||
// odd quirk of llama3.1, start token is \n\n
|
||||
if (
|
||||
!event?.generation.trim() &&
|
||||
event?.generation_token_count === 1 &&
|
||||
event.prompt_token_count !== null
|
||||
)
|
||||
continue;
|
||||
|
||||
if (delta === TOKENS.TOOL_CALL) {
|
||||
toolId = randomUUID();
|
||||
continue;
|
||||
}
|
||||
|
||||
let options: undefined | ToolCallLLMMessageOptions = undefined;
|
||||
if (toolId && event?.stop_reason === "stop") {
|
||||
const tool = JSON.parse(collecting.join(""));
|
||||
options = {
|
||||
toolCall: [
|
||||
{
|
||||
id: toolId,
|
||||
name: tool.name,
|
||||
input: tool.parameters,
|
||||
} as ToolCall,
|
||||
],
|
||||
};
|
||||
} else if (toolId && !event?.stop_reason) {
|
||||
collecting.push(delta);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!delta && !options) continue;
|
||||
|
||||
yield {
|
||||
delta: options ? "" : delta,
|
||||
options,
|
||||
raw: response,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getRequestBody<T extends ChatMessage>(
|
||||
metadata: LLMMetadata,
|
||||
messages: T[],
|
||||
tools?: BaseTool[],
|
||||
): InvokeModelCommandInput | InvokeModelWithResponseStreamCommandInput {
|
||||
let prompt: string = "";
|
||||
if (metadata.model.startsWith("meta.llama3")) {
|
||||
prompt = mapChatMessagesToMetaLlama3Messages(messages, tools);
|
||||
} else if (metadata.model.startsWith("meta.llama2")) {
|
||||
prompt = mapChatMessagesToMetaLlama2Messages(messages);
|
||||
} else {
|
||||
throw new Error(`Meta model ${metadata.model} is not supported`);
|
||||
}
|
||||
|
||||
return {
|
||||
modelId: metadata.model,
|
||||
contentType: "application/json",
|
||||
accept: "application/json",
|
||||
body: JSON.stringify({
|
||||
prompt,
|
||||
max_gen_len: metadata.maxTokens,
|
||||
temperature: metadata.temperature,
|
||||
top_p: metadata.topP,
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import type { InvocationMetrics } from "../types";
|
||||
|
||||
export type MetaTextContent = string;
|
||||
|
||||
export type MetaMessage = {
|
||||
role: "user" | "assistant" | "system" | "ipython";
|
||||
content: MetaTextContent;
|
||||
};
|
||||
|
||||
type MetaResponse = {
|
||||
generation: string;
|
||||
prompt_token_count: number;
|
||||
generation_token_count: number;
|
||||
stop_reason: "stop" | "length";
|
||||
};
|
||||
|
||||
export type MetaStreamEvent = MetaResponse & {
|
||||
"amazon-bedrock-invocationMetrics": InvocationMetrics;
|
||||
};
|
||||
|
||||
export type MetaNoneStreamingResponse = MetaResponse;
|
||||
@@ -0,0 +1,198 @@
|
||||
import type {
|
||||
BaseTool,
|
||||
ChatMessage,
|
||||
MessageContentTextDetail,
|
||||
ToolCallLLMMessageOptions,
|
||||
} from "@llamaindex/core/llms";
|
||||
import type { MetaMessage } from "./types";
|
||||
|
||||
const getToolCallInstructionString = (tool: BaseTool): string => {
|
||||
return `Use the function '${tool.metadata.name}' to '${tool.metadata.description}'`;
|
||||
};
|
||||
|
||||
const getToolCallParametersString = (tool: BaseTool): string => {
|
||||
return JSON.stringify({
|
||||
name: tool.metadata.name,
|
||||
description: tool.metadata.description,
|
||||
parameters: tool.metadata.parameters
|
||||
? Object.entries(tool.metadata.parameters.properties).map(
|
||||
([name, definition]) => ({ [name]: definition }),
|
||||
)
|
||||
: {},
|
||||
});
|
||||
};
|
||||
|
||||
// ported from https://github.com/meta-llama/llama-agentic-system/blob/main/llama_agentic_system/system_prompt.py
|
||||
// NOTE: using json instead of the above xml style tool calling works more reliability
|
||||
export const getToolsPrompt = (tools?: BaseTool[]) => {
|
||||
if (!tools?.length) return "";
|
||||
|
||||
const customToolParams = tools.map((tool) => {
|
||||
return [
|
||||
getToolCallInstructionString(tool),
|
||||
getToolCallParametersString(tool),
|
||||
].join("\n\n");
|
||||
});
|
||||
|
||||
return `
|
||||
Environment: node
|
||||
|
||||
# Tool Instructions
|
||||
- Never use ipython, always use javascript in node
|
||||
|
||||
Cutting Knowledge Date: December 2023
|
||||
Today Date: ${new Date().toLocaleString("en-US", { year: "numeric", month: "long" })}
|
||||
|
||||
You have access to the following functions:
|
||||
|
||||
${customToolParams}
|
||||
|
||||
Think very carefully before calling functions.
|
||||
|
||||
If a you choose to call a function ONLY reply in the following json format:
|
||||
{
|
||||
"name": function_name,
|
||||
"parameters": parameters,
|
||||
}
|
||||
where
|
||||
|
||||
{
|
||||
"name": function_name,
|
||||
"parameters": parameters, => a JSON dict with the function argument name as key and function argument value as value.
|
||||
}
|
||||
|
||||
Here is an example,
|
||||
|
||||
{
|
||||
"name": "example_function_name",
|
||||
"parameters": {"example_name": "example_value"}
|
||||
}
|
||||
|
||||
Reminder:
|
||||
- Function calls MUST follow the specified format
|
||||
- Required parameters MUST be specified
|
||||
- Only call one function at a time
|
||||
- Put the entire function call reply on one line
|
||||
- Always add your sources when using search results to answer the user query
|
||||
`;
|
||||
};
|
||||
|
||||
export const mapChatRoleToMetaRole = (
|
||||
role: ChatMessage["role"],
|
||||
): MetaMessage["role"] => {
|
||||
if (role === "assistant") return "assistant";
|
||||
if (role === "user") return "user";
|
||||
return "system";
|
||||
};
|
||||
|
||||
export const mapChatMessagesToMetaMessages = <
|
||||
T extends ChatMessage<ToolCallLLMMessageOptions>,
|
||||
>(
|
||||
messages: T[],
|
||||
): MetaMessage[] => {
|
||||
return messages.flatMap((msg) => {
|
||||
if (msg.options && "toolCall" in msg.options) {
|
||||
return msg.options.toolCall.map((call) => ({
|
||||
role: "assistant",
|
||||
content: JSON.stringify({
|
||||
id: call.id,
|
||||
name: call.name,
|
||||
parameters: call.input,
|
||||
}),
|
||||
}));
|
||||
}
|
||||
|
||||
if (msg.options && "toolResult" in msg.options) {
|
||||
return {
|
||||
role: "ipython",
|
||||
content: JSON.stringify(msg.options.toolResult),
|
||||
};
|
||||
}
|
||||
|
||||
let content: string = "";
|
||||
if (typeof msg.content === "string") {
|
||||
content = msg.content;
|
||||
} else if (msg.content.length) {
|
||||
content = (msg.content[0] as MessageContentTextDetail).text;
|
||||
}
|
||||
return {
|
||||
role: mapChatRoleToMetaRole(msg.role),
|
||||
content,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Documentation at https://llama.meta.com/docs/model-cards-and-prompt-formats/meta-llama-3
|
||||
*/
|
||||
export const mapChatMessagesToMetaLlama3Messages = <T extends ChatMessage>(
|
||||
messages: T[],
|
||||
tools?: BaseTool[],
|
||||
): string => {
|
||||
const parts: string[] = [];
|
||||
if (tools?.length) {
|
||||
parts.push(
|
||||
"<|begin_of_text|>",
|
||||
"<|start_header_id|>system<|end_header_id|>",
|
||||
getToolsPrompt(tools),
|
||||
"<|eot_id|>",
|
||||
);
|
||||
}
|
||||
|
||||
const mapped = mapChatMessagesToMetaMessages(messages).map((message) => {
|
||||
return [
|
||||
"<|start_header_id|>",
|
||||
message.role,
|
||||
"<|end_header_id|>",
|
||||
message.content,
|
||||
"<|eot_id|>",
|
||||
].join("\n");
|
||||
});
|
||||
|
||||
parts.push(
|
||||
"<|begin_of_text|>",
|
||||
...mapped,
|
||||
"<|start_header_id|>assistant<|end_header_id|>",
|
||||
);
|
||||
return parts.join("\n");
|
||||
};
|
||||
|
||||
/**
|
||||
* Documentation at https://llama.meta.com/docs/model-cards-and-prompt-formats/meta-llama-2
|
||||
*/
|
||||
export const mapChatMessagesToMetaLlama2Messages = <T extends ChatMessage>(
|
||||
messages: T[],
|
||||
): string => {
|
||||
const mapped = mapChatMessagesToMetaMessages(messages);
|
||||
let output = "<s>";
|
||||
let insideInst = false;
|
||||
let needsStartAgain = false;
|
||||
for (const message of mapped) {
|
||||
if (needsStartAgain) {
|
||||
output += "<s>";
|
||||
needsStartAgain = false;
|
||||
}
|
||||
const text = message.content;
|
||||
if (message.role === "system") {
|
||||
if (!insideInst) {
|
||||
output += "[INST] ";
|
||||
insideInst = true;
|
||||
}
|
||||
output += `<<SYS>>\n${text}\n<</SYS>>\n`;
|
||||
} else if (message.role === "user") {
|
||||
output += text;
|
||||
if (insideInst) {
|
||||
output += " [/INST]";
|
||||
insideInst = false;
|
||||
}
|
||||
} else if (message.role === "assistant") {
|
||||
if (insideInst) {
|
||||
output += " [/INST]";
|
||||
insideInst = false;
|
||||
}
|
||||
output += ` ${text} </s>\n`;
|
||||
needsStartAgain = true;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
type InvokeModelCommandInput,
|
||||
type InvokeModelWithResponseStreamCommandInput,
|
||||
ResponseStream,
|
||||
} from "@aws-sdk/client-bedrock-runtime";
|
||||
import {
|
||||
type BaseTool,
|
||||
type ChatMessage,
|
||||
type ChatResponseChunk,
|
||||
type LLMMetadata,
|
||||
type ToolCallLLMMessageOptions,
|
||||
} from "@llamaindex/core/llms";
|
||||
import { streamConverter } from "@llamaindex/core/utils";
|
||||
import type { ToolChoice } from "./types";
|
||||
import { toUtf8 } from "./utils";
|
||||
|
||||
export type BedrockAdditionalChatOptions = { toolChoice: ToolChoice };
|
||||
|
||||
export type BedrockChatStreamResponse = AsyncIterable<
|
||||
ChatResponseChunk<ToolCallLLMMessageOptions>
|
||||
>;
|
||||
|
||||
export abstract class Provider<ProviderStreamEvent extends {} = {}> {
|
||||
abstract getTextFromResponse(response: Record<string, any>): string;
|
||||
|
||||
// Return tool calls from none streaming calls
|
||||
abstract getToolsFromResponse<T extends {} = {}>(
|
||||
response: Record<string, any>,
|
||||
): T[];
|
||||
|
||||
getStreamingEventResponse(
|
||||
response: Record<string, any>,
|
||||
): ProviderStreamEvent | undefined {
|
||||
return response.chunk?.bytes
|
||||
? (JSON.parse(toUtf8(response.chunk?.bytes)) as ProviderStreamEvent)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
async *reduceStream(
|
||||
stream: AsyncIterable<ResponseStream>,
|
||||
): BedrockChatStreamResponse {
|
||||
yield* streamConverter(stream, (response) => {
|
||||
return {
|
||||
delta: this.getTextFromStreamResponse(response),
|
||||
raw: response,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
getTextFromStreamResponse(response: Record<string, any>): string {
|
||||
return this.getTextFromResponse(response);
|
||||
}
|
||||
|
||||
abstract getRequestBody<T extends ChatMessage>(
|
||||
metadata: LLMMetadata,
|
||||
messages: T[],
|
||||
tools?: BaseTool[],
|
||||
options?: BedrockAdditionalChatOptions,
|
||||
): InvokeModelCommandInput | InvokeModelWithResponseStreamCommandInput;
|
||||
}
|
||||
@@ -1,145 +1,11 @@
|
||||
type Usage = {
|
||||
input_tokens: number;
|
||||
output_tokens: number;
|
||||
};
|
||||
|
||||
type Message = {
|
||||
id: string;
|
||||
type: string;
|
||||
role: string;
|
||||
content: string[];
|
||||
model: string;
|
||||
stop_reason: string | null;
|
||||
stop_sequence: string | null;
|
||||
usage: Usage;
|
||||
};
|
||||
|
||||
export type ToolBlock = {
|
||||
id: string;
|
||||
input: unknown;
|
||||
name: string;
|
||||
type: "tool_use";
|
||||
};
|
||||
|
||||
export type TextBlock = {
|
||||
type: "text";
|
||||
text: string;
|
||||
};
|
||||
|
||||
type ContentBlockStart = {
|
||||
type: "content_block_start";
|
||||
index: number;
|
||||
content_block: ToolBlock | TextBlock;
|
||||
};
|
||||
|
||||
type Delta =
|
||||
| {
|
||||
type: "text_delta";
|
||||
text: string;
|
||||
}
|
||||
| {
|
||||
type: "input_json_delta";
|
||||
partial_json: string;
|
||||
};
|
||||
|
||||
type ContentBlockDelta = {
|
||||
type: "content_block_delta";
|
||||
index: number;
|
||||
delta: Delta;
|
||||
};
|
||||
|
||||
type ContentBlockStop = {
|
||||
type: "content_block_stop";
|
||||
index: number;
|
||||
};
|
||||
|
||||
type MessageDelta = {
|
||||
type: "message_delta";
|
||||
delta: {
|
||||
stop_reason: string;
|
||||
stop_sequence: string | null;
|
||||
};
|
||||
usage: Usage;
|
||||
};
|
||||
|
||||
type InvocationMetrics = {
|
||||
export type InvocationMetrics = {
|
||||
inputTokenCount: number;
|
||||
outputTokenCount: number;
|
||||
invocationLatency: number;
|
||||
firstByteLatency: number;
|
||||
};
|
||||
|
||||
type MessageStop = {
|
||||
type: "message_stop";
|
||||
"amazon-bedrock-invocationMetrics": InvocationMetrics;
|
||||
};
|
||||
|
||||
export type ToolChoice =
|
||||
| { type: "any" }
|
||||
| { type: "auto" }
|
||||
| { type: "tool"; name: string };
|
||||
|
||||
export type StreamEvent =
|
||||
| { type: "message_start"; message: Message }
|
||||
| ContentBlockStart
|
||||
| ContentBlockDelta
|
||||
| ContentBlockStop
|
||||
| MessageDelta
|
||||
| MessageStop;
|
||||
|
||||
export type AnthropicContent =
|
||||
| AnthropicTextContent
|
||||
| AnthropicImageContent
|
||||
| AnthropicToolContent
|
||||
| AnthropicToolResultContent;
|
||||
|
||||
export type AnthropicTextContent = {
|
||||
type: "text";
|
||||
text: string;
|
||||
};
|
||||
|
||||
export type AnthropicToolContent = {
|
||||
type: "tool_use";
|
||||
id: string;
|
||||
name: string;
|
||||
input: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type AnthropicToolResultContent = {
|
||||
type: "tool_result";
|
||||
tool_use_id: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
export type AnthropicMediaTypes =
|
||||
| "image/jpeg"
|
||||
| "image/png"
|
||||
| "image/webp"
|
||||
| "image/gif";
|
||||
|
||||
export type AnthropicImageSource = {
|
||||
type: "base64";
|
||||
media_type: AnthropicMediaTypes;
|
||||
data: string; // base64 encoded image bytes
|
||||
};
|
||||
|
||||
export type AnthropicImageContent = {
|
||||
type: "image";
|
||||
source: AnthropicImageSource;
|
||||
};
|
||||
|
||||
export type AnthropicMessage = {
|
||||
role: "user" | "assistant";
|
||||
content: AnthropicContent[];
|
||||
};
|
||||
|
||||
export type AnthropicNoneStreamingResponse = {
|
||||
id: string;
|
||||
type: "message";
|
||||
role: "assistant";
|
||||
content: AnthropicContent[];
|
||||
model: string;
|
||||
stop_reason: "end_turn" | "max_tokens" | "stop_sequence";
|
||||
stop_sequence?: string;
|
||||
usage: { input_tokens: number; output_tokens: number };
|
||||
};
|
||||
|
||||
@@ -1,26 +1,7 @@
|
||||
import type {
|
||||
BaseTool,
|
||||
ChatMessage,
|
||||
JSONObject,
|
||||
MessageContent,
|
||||
MessageContentDetail,
|
||||
ToolCallLLMMessageOptions,
|
||||
ToolMetadata,
|
||||
} from "llamaindex";
|
||||
import type {
|
||||
AnthropicContent,
|
||||
AnthropicImageContent,
|
||||
AnthropicMediaTypes,
|
||||
AnthropicMessage,
|
||||
AnthropicTextContent,
|
||||
} from "./types.js";
|
||||
|
||||
const ACCEPTED_IMAGE_MIME_TYPES = [
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/webp",
|
||||
"image/gif",
|
||||
];
|
||||
} from "@llamaindex/core/llms";
|
||||
|
||||
export const mapMessageContentToMessageContentDetails = (
|
||||
content: MessageContent,
|
||||
@@ -28,171 +9,5 @@ export const mapMessageContentToMessageContentDetails = (
|
||||
return Array.isArray(content) ? content : [{ type: "text", text: content }];
|
||||
};
|
||||
|
||||
export const mergeNeighboringSameRoleMessages = (
|
||||
messages: AnthropicMessage[],
|
||||
): AnthropicMessage[] => {
|
||||
return messages.reduce(
|
||||
(result: AnthropicMessage[], current: AnthropicMessage, index: number) => {
|
||||
if (index > 0 && messages[index - 1].role === current.role) {
|
||||
result[result.length - 1].content = [
|
||||
...result[result.length - 1].content,
|
||||
...current.content,
|
||||
];
|
||||
} else {
|
||||
result.push(current);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
[],
|
||||
);
|
||||
};
|
||||
|
||||
export const mapMessageContentDetailToAnthropicContent = <
|
||||
T extends MessageContentDetail,
|
||||
>(
|
||||
detail: T,
|
||||
): AnthropicContent => {
|
||||
let content: AnthropicContent;
|
||||
|
||||
if (detail.type === "text") {
|
||||
content = mapTextContent(detail.text);
|
||||
} else if (detail.type === "image_url") {
|
||||
content = mapImageContent(detail.image_url.url);
|
||||
} else {
|
||||
throw new Error("Unsupported content detail type");
|
||||
}
|
||||
return content;
|
||||
};
|
||||
|
||||
export const mapMessageContentToAnthropicContent = <T extends MessageContent>(
|
||||
content: T,
|
||||
): AnthropicContent[] => {
|
||||
return mapMessageContentToMessageContentDetails(content).map(
|
||||
mapMessageContentDetailToAnthropicContent,
|
||||
);
|
||||
};
|
||||
|
||||
type AnthropicTool = {
|
||||
name: string;
|
||||
description: string;
|
||||
input_schema: ToolMetadata["parameters"];
|
||||
};
|
||||
|
||||
export const mapBaseToolsToAnthropicTools = (
|
||||
tools?: BaseTool[],
|
||||
): AnthropicTool[] => {
|
||||
if (!tools) return [];
|
||||
return tools.map((tool: BaseTool) => {
|
||||
const {
|
||||
metadata: { parameters, ...options },
|
||||
} = tool;
|
||||
return {
|
||||
...options,
|
||||
input_schema: parameters,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export const mapChatMessagesToAnthropicMessages = <
|
||||
T extends ChatMessage<ToolCallLLMMessageOptions>,
|
||||
>(
|
||||
messages: T[],
|
||||
): AnthropicMessage[] => {
|
||||
const mapped = messages
|
||||
.flatMap((msg: T): AnthropicMessage[] => {
|
||||
if (msg.options && "toolCall" in msg.options) {
|
||||
return [
|
||||
{
|
||||
role: "assistant",
|
||||
content: msg.options.toolCall.map((call) => ({
|
||||
type: "tool_use",
|
||||
id: call.id,
|
||||
name: call.name,
|
||||
input: call.input as JSONObject,
|
||||
})),
|
||||
},
|
||||
];
|
||||
}
|
||||
if (msg.options && "toolResult" in msg.options) {
|
||||
return [
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{
|
||||
type: "tool_result",
|
||||
tool_use_id: msg.options.toolResult.id,
|
||||
content: msg.options.toolResult.result,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
return mapMessageContentToMessageContentDetails(msg.content).map(
|
||||
(detail: MessageContentDetail): AnthropicMessage => {
|
||||
const content = mapMessageContentDetailToAnthropicContent(detail);
|
||||
|
||||
return {
|
||||
role: msg.role === "assistant" ? "assistant" : "user",
|
||||
content: [content],
|
||||
};
|
||||
},
|
||||
);
|
||||
})
|
||||
.filter((message: AnthropicMessage) => {
|
||||
const content = message.content[0];
|
||||
if (content.type === "text" && !content.text) return false;
|
||||
if (content.type === "image" && !content.source.data) return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
return mergeNeighboringSameRoleMessages(mapped);
|
||||
};
|
||||
|
||||
export const mapTextContent = (text: string): AnthropicTextContent => {
|
||||
return { type: "text", text };
|
||||
};
|
||||
|
||||
export const extractDataUrlComponents = (
|
||||
dataUrl: string,
|
||||
): {
|
||||
mimeType: string;
|
||||
base64: string;
|
||||
} => {
|
||||
const parts = dataUrl.split(";base64,");
|
||||
|
||||
if (parts.length !== 2 || !parts[0].startsWith("data:")) {
|
||||
throw new Error("Invalid data URL");
|
||||
}
|
||||
|
||||
const mimeType = parts[0].slice(5);
|
||||
const base64 = parts[1];
|
||||
|
||||
return {
|
||||
mimeType,
|
||||
base64,
|
||||
};
|
||||
};
|
||||
|
||||
export const mapImageContent = (imageUrl: string): AnthropicImageContent => {
|
||||
if (!imageUrl.startsWith("data:"))
|
||||
throw new Error(
|
||||
"For Anthropic please only use base64 data url, e.g.: data:image/jpeg;base64,SGVsbG8sIFdvcmxkIQ==",
|
||||
);
|
||||
const { mimeType, base64: data } = extractDataUrlComponents(imageUrl);
|
||||
if (!ACCEPTED_IMAGE_MIME_TYPES.includes(mimeType))
|
||||
throw new Error(
|
||||
`Anthropic only accepts the following mimeTypes: ${ACCEPTED_IMAGE_MIME_TYPES.join("\n")}`,
|
||||
);
|
||||
|
||||
return {
|
||||
type: "image",
|
||||
source: {
|
||||
type: "base64",
|
||||
media_type: mimeType as AnthropicMediaTypes,
|
||||
data,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const toUtf8 = (input: Uint8Array): string =>
|
||||
new TextDecoder("utf-8").decode(input);
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/script/type",
|
||||
"tsBuildInfoFile": "./dist/script/.tsbuildinfo",
|
||||
"emitDeclarationOnly": true
|
||||
},
|
||||
"include": ["./tsup.config.ts"]
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import { defineConfig } from "tsup";
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
entry: ["src/index.ts", "src/llm/bedrock/base.ts"],
|
||||
format: ["cjs", "esm"],
|
||||
sourcemap: true,
|
||||
},
|
||||
]);
|
||||
@@ -0,0 +1,67 @@
|
||||
# @llamaindex/core
|
||||
|
||||
## 0.1.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 91d02a4: feat: support transform component callable
|
||||
|
||||
## 0.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 15962b3: feat: node parser refactor
|
||||
|
||||
Align the text splitter logic with Python; it has almost the same logic as Python; Zod checks for input and better error messages and event system.
|
||||
|
||||
This change will not be considered a breaking change since it doesn't have a significant output difference from the last version,
|
||||
but some edge cases will change, like the page separator and parameter for the constructor.
|
||||
|
||||
## 0.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 6cf6ae6: feat: abstract query type
|
||||
|
||||
## 0.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- b974eea: Add support for Metadata filters
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- b3681bf: fix: DataCloneError when using FunctionTool
|
||||
|
||||
## 0.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 16ef5dd: refactor: simplify callback manager
|
||||
|
||||
Change `event.detail.payload` to `event.detail`
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 16ef5dd: refactor: move callback manager & llm to core module
|
||||
|
||||
For people who import `llamaindex/llms/base` or `llamaindex/llms/utils`,
|
||||
use `@llamaindex/core/llms` and `@llamaindex/core/utils` instead.
|
||||
|
||||
## 0.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f326ab8: chore: bump version
|
||||
- Updated dependencies [f326ab8]
|
||||
- @llamaindex/env@0.1.8
|
||||
|
||||
## 0.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f10b41d: fix: release files
|
||||
- Updated dependencies [41fe871]
|
||||
- @llamaindex/env@0.1.7
|
||||
@@ -1,9 +1,51 @@
|
||||
{
|
||||
"name": "@llamaindex/core",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"version": "0.1.5",
|
||||
"description": "LlamaIndex Core Module",
|
||||
"exports": {
|
||||
"./node-parser": {
|
||||
"require": {
|
||||
"types": "./dist/node-parser/index.d.cts",
|
||||
"default": "./dist/node-parser/index.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/node-parser/index.d.ts",
|
||||
"default": "./dist/node-parser/index.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./dist/node-parser/index.d.ts",
|
||||
"default": "./dist/node-parser/index.js"
|
||||
}
|
||||
},
|
||||
"./query-engine": {
|
||||
"require": {
|
||||
"types": "./dist/query-engine/index.d.cts",
|
||||
"default": "./dist/query-engine/index.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/query-engine/index.d.ts",
|
||||
"default": "./dist/query-engine/index.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./dist/query-engine/index.d.ts",
|
||||
"default": "./dist/query-engine/index.js"
|
||||
}
|
||||
},
|
||||
"./llms": {
|
||||
"require": {
|
||||
"types": "./dist/llms/index.d.cts",
|
||||
"default": "./dist/llms/index.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/llms/index.d.ts",
|
||||
"default": "./dist/llms/index.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./dist/llms/index.d.ts",
|
||||
"default": "./dist/llms/index.js"
|
||||
}
|
||||
},
|
||||
"./decorator": {
|
||||
"require": {
|
||||
"types": "./dist/decorator/index.d.cts",
|
||||
@@ -18,6 +60,20 @@
|
||||
"default": "./dist/decorator/index.js"
|
||||
}
|
||||
},
|
||||
"./embeddings": {
|
||||
"require": {
|
||||
"types": "./dist/embeddings/index.d.cts",
|
||||
"default": "./dist/embeddings/index.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/embeddings/index.d.ts",
|
||||
"default": "./dist/embeddings/index.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./dist/embeddings/index.d.ts",
|
||||
"default": "./dist/embeddings/index.js"
|
||||
}
|
||||
},
|
||||
"./global": {
|
||||
"require": {
|
||||
"types": "./dist/global/index.d.cts",
|
||||
@@ -45,8 +101,25 @@
|
||||
"types": "./dist/schema/index.d.ts",
|
||||
"default": "./dist/schema/index.js"
|
||||
}
|
||||
},
|
||||
"./utils": {
|
||||
"require": {
|
||||
"types": "./dist/utils/index.d.cts",
|
||||
"default": "./dist/utils/index.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/utils/index.d.ts",
|
||||
"default": "./dist/utils/index.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./dist/utils/index.d.ts",
|
||||
"default": "./dist/utils/index.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "bunchee --watch",
|
||||
"build": "bunchee"
|
||||
@@ -57,7 +130,9 @@
|
||||
"url": "https://github.com/himself65/LlamaIndexTS.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bunchee": "^5.2.1"
|
||||
"ajv": "^8.16.0",
|
||||
"bunchee": "5.3.0-beta.0",
|
||||
"natural": "^7.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@llamaindex/env": "workspace:*",
|
||||
|
||||
+32
-27
@@ -1,9 +1,7 @@
|
||||
import type { BaseNode } from "@llamaindex/core/schema";
|
||||
import { MetadataMode } from "@llamaindex/core/schema";
|
||||
import { type Tokenizers } from "@llamaindex/env";
|
||||
import type { TransformComponent } from "../ingestion/types.js";
|
||||
import type { MessageContentDetail } from "../llm/types.js";
|
||||
import { extractSingleText } from "../llm/utils.js";
|
||||
import type { MessageContentDetail } from "../llms";
|
||||
import { BaseNode, MetadataMode, TransformComponent } from "../schema";
|
||||
import { extractSingleText } from "../utils";
|
||||
import { truncateMaxTokens } from "./tokenizer.js";
|
||||
import { SimilarityType, similarity } from "./utils.js";
|
||||
|
||||
@@ -17,10 +15,33 @@ export type EmbeddingInfo = {
|
||||
tokenizer?: Tokenizers;
|
||||
};
|
||||
|
||||
export abstract class BaseEmbedding implements TransformComponent {
|
||||
export type BaseEmbeddingOptions = {
|
||||
logProgress?: boolean;
|
||||
};
|
||||
|
||||
export abstract class BaseEmbedding extends TransformComponent {
|
||||
embedBatchSize = DEFAULT_EMBED_BATCH_SIZE;
|
||||
embedInfo?: EmbeddingInfo;
|
||||
|
||||
constructor() {
|
||||
super(
|
||||
async (
|
||||
nodes: BaseNode[],
|
||||
options?: BaseEmbeddingOptions,
|
||||
): Promise<BaseNode[]> => {
|
||||
const texts = nodes.map((node) => node.getContent(MetadataMode.EMBED));
|
||||
|
||||
const embeddings = await this.getTextEmbeddingsBatch(texts, options);
|
||||
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
nodes[i].embedding = embeddings[i];
|
||||
}
|
||||
|
||||
return nodes;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
similarity(
|
||||
embedding1: number[],
|
||||
embedding2: number[],
|
||||
@@ -45,7 +66,7 @@ export abstract class BaseEmbedding implements TransformComponent {
|
||||
* Optionally override this method to retrieve multiple embeddings in a single request
|
||||
* @param texts
|
||||
*/
|
||||
async getTextEmbeddings(texts: string[]): Promise<Array<number[]>> {
|
||||
getTextEmbeddings = async (texts: string[]): Promise<Array<number[]>> => {
|
||||
const embeddings: number[][] = [];
|
||||
|
||||
for (const text of texts) {
|
||||
@@ -54,7 +75,7 @@ export abstract class BaseEmbedding implements TransformComponent {
|
||||
}
|
||||
|
||||
return embeddings;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get embeddings for a batch of texts
|
||||
@@ -63,30 +84,16 @@ export abstract class BaseEmbedding implements TransformComponent {
|
||||
*/
|
||||
async getTextEmbeddingsBatch(
|
||||
texts: string[],
|
||||
options?: {
|
||||
logProgress?: boolean;
|
||||
},
|
||||
options?: BaseEmbeddingOptions,
|
||||
): Promise<Array<number[]>> {
|
||||
return await batchEmbeddings(
|
||||
texts,
|
||||
this.getTextEmbeddings.bind(this),
|
||||
this.getTextEmbeddings,
|
||||
this.embedBatchSize,
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
async transform(nodes: BaseNode[], _options?: any): Promise<BaseNode[]> {
|
||||
const texts = nodes.map((node) => node.getContent(MetadataMode.EMBED));
|
||||
|
||||
const embeddings = await this.getTextEmbeddingsBatch(texts, _options);
|
||||
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
nodes[i].embedding = embeddings[i];
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
truncateMaxTokens(input: string[]): string[] {
|
||||
return input.map((s) => {
|
||||
// truncate to max tokens
|
||||
@@ -104,9 +111,7 @@ export async function batchEmbeddings<T>(
|
||||
values: T[],
|
||||
embedFunc: EmbedFunc<T>,
|
||||
chunkSize: number,
|
||||
options?: {
|
||||
logProgress?: boolean;
|
||||
},
|
||||
options?: BaseEmbeddingOptions,
|
||||
): Promise<Array<number[]>> {
|
||||
const resultEmbeddings: Array<number[]> = [];
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export { BaseEmbedding, batchEmbeddings } from "./base";
|
||||
export type { BaseEmbeddingOptions, EmbeddingInfo } from "./base";
|
||||
export { truncateMaxTokens } from "./tokenizer";
|
||||
export { DEFAULT_SIMILARITY_TOP_K, SimilarityType, similarity } from "./utils";
|
||||
@@ -0,0 +1,64 @@
|
||||
export const DEFAULT_SIMILARITY_TOP_K = 2;
|
||||
|
||||
/**
|
||||
* Similarity type
|
||||
* Default is cosine similarity. Dot product and negative Euclidean distance are also supported.
|
||||
*/
|
||||
export enum SimilarityType {
|
||||
DEFAULT = "cosine",
|
||||
DOT_PRODUCT = "dot_product",
|
||||
EUCLIDEAN = "euclidean",
|
||||
}
|
||||
|
||||
/**
|
||||
* The similarity between two embeddings.
|
||||
* @param embedding1
|
||||
* @param embedding2
|
||||
* @param mode
|
||||
* @returns similarity score with higher numbers meaning the two embeddings are more similar
|
||||
*/
|
||||
|
||||
export function similarity(
|
||||
embedding1: number[],
|
||||
embedding2: number[],
|
||||
mode: SimilarityType = SimilarityType.DEFAULT,
|
||||
): number {
|
||||
if (embedding1.length !== embedding2.length) {
|
||||
throw new Error("Embedding length mismatch");
|
||||
}
|
||||
|
||||
// NOTE I've taken enough Kahan to know that we should probably leave the
|
||||
// numeric programming to numeric programmers. The naive approach here
|
||||
// will probably cause some avoidable loss of floating point precision
|
||||
// ml-distance is worth watching although they currently also use the naive
|
||||
// formulas
|
||||
function norm(x: number[]): number {
|
||||
let result = 0;
|
||||
for (let i = 0; i < x.length; i++) {
|
||||
result += x[i] * x[i];
|
||||
}
|
||||
return Math.sqrt(result);
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case SimilarityType.EUCLIDEAN: {
|
||||
const difference = embedding1.map((x, i) => x - embedding2[i]);
|
||||
return -norm(difference);
|
||||
}
|
||||
case SimilarityType.DOT_PRODUCT: {
|
||||
let result = 0;
|
||||
for (let i = 0; i < embedding1.length; i++) {
|
||||
result += embedding1[i] * embedding2[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case SimilarityType.DEFAULT: {
|
||||
return (
|
||||
similarity(embedding1, embedding2, SimilarityType.DOT_PRODUCT) /
|
||||
(norm(embedding1) * norm(embedding2))
|
||||
);
|
||||
}
|
||||
default:
|
||||
throw new Error("Not implemented yet");
|
||||
}
|
||||
}
|
||||
@@ -1 +1,11 @@
|
||||
export { Settings } from "./settings";
|
||||
export { CallbackManager } from "./settings/callback-manager";
|
||||
export type {
|
||||
LLMEndEvent,
|
||||
LLMStartEvent,
|
||||
LLMStreamEvent,
|
||||
LLMToolCallEvent,
|
||||
LLMToolResultEvent,
|
||||
LlamaIndexEventMaps,
|
||||
} from "./settings/callback-manager";
|
||||
export type { JSONArray, JSONObject, JSONValue } from "./type";
|
||||
|
||||
@@ -1,10 +1,31 @@
|
||||
import type { Tokenizer } from "@llamaindex/env";
|
||||
import {
|
||||
type CallbackManager,
|
||||
getCallbackManager,
|
||||
setCallbackManager,
|
||||
withCallbackManager,
|
||||
} from "./settings/callback-manager";
|
||||
import {
|
||||
getChunkSize,
|
||||
setChunkSize,
|
||||
withChunkSize,
|
||||
} from "./settings/chunk-size";
|
||||
import {
|
||||
getTokenizer,
|
||||
setTokenizer,
|
||||
withTokenizer,
|
||||
} from "./settings/tokenizer";
|
||||
|
||||
export const Settings = {
|
||||
get tokenizer() {
|
||||
return getTokenizer();
|
||||
},
|
||||
set tokenizer(tokenizer) {
|
||||
setTokenizer(tokenizer);
|
||||
},
|
||||
withTokenizer<Result>(tokenizer: Tokenizer, fn: () => Result): Result {
|
||||
return withTokenizer(tokenizer, fn);
|
||||
},
|
||||
get chunkSize(): number | undefined {
|
||||
return getChunkSize();
|
||||
},
|
||||
@@ -14,4 +35,19 @@ export const Settings = {
|
||||
withChunkSize<Result>(chunkSize: number, fn: () => Result): Result {
|
||||
return withChunkSize(chunkSize, fn);
|
||||
},
|
||||
|
||||
get callbackManager(): CallbackManager {
|
||||
return getCallbackManager();
|
||||
},
|
||||
|
||||
set callbackManager(callbackManager: CallbackManager) {
|
||||
setCallbackManager(callbackManager);
|
||||
},
|
||||
|
||||
withCallbackManager<Result>(
|
||||
callbackManager: CallbackManager,
|
||||
fn: () => Result,
|
||||
): Result {
|
||||
return withCallbackManager(callbackManager, fn);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
import { AsyncLocalStorage, CustomEvent } from "@llamaindex/env";
|
||||
import type {
|
||||
ChatMessage,
|
||||
ChatResponse,
|
||||
ChatResponseChunk,
|
||||
ToolCall,
|
||||
ToolOutput,
|
||||
} from "../../llms";
|
||||
import { TextNode } from "../../schema";
|
||||
import { EventCaller, getEventCaller } from "../../utils/event-caller";
|
||||
import type { UUID } from "../type";
|
||||
|
||||
export type LLMStartEvent = {
|
||||
id: UUID;
|
||||
messages: ChatMessage[];
|
||||
};
|
||||
|
||||
export type LLMToolCallEvent = {
|
||||
toolCall: ToolCall;
|
||||
};
|
||||
|
||||
export type LLMToolResultEvent = {
|
||||
toolCall: ToolCall;
|
||||
toolResult: ToolOutput;
|
||||
};
|
||||
|
||||
export type LLMEndEvent = {
|
||||
id: UUID;
|
||||
response: ChatResponse;
|
||||
};
|
||||
|
||||
export type LLMStreamEvent = {
|
||||
id: UUID;
|
||||
chunk: ChatResponseChunk;
|
||||
};
|
||||
|
||||
export type ChunkingStartEvent = {
|
||||
text: string[];
|
||||
};
|
||||
|
||||
export type ChunkingEndEvent = {
|
||||
chunks: string[];
|
||||
};
|
||||
|
||||
export type NodeParsingStartEvent = {
|
||||
documents: TextNode[];
|
||||
};
|
||||
|
||||
export type NodeParsingEndEvent = {
|
||||
nodes: TextNode[];
|
||||
};
|
||||
|
||||
export interface LlamaIndexEventMaps {
|
||||
"llm-start": LLMStartEvent;
|
||||
"llm-end": LLMEndEvent;
|
||||
"llm-tool-call": LLMToolCallEvent;
|
||||
"llm-tool-result": LLMToolResultEvent;
|
||||
"llm-stream": LLMStreamEvent;
|
||||
"chunking-start": ChunkingStartEvent;
|
||||
"chunking-end": ChunkingEndEvent;
|
||||
"node-parsing-start": NodeParsingStartEvent;
|
||||
"node-parsing-end": NodeParsingEndEvent;
|
||||
}
|
||||
|
||||
export class LlamaIndexCustomEvent<T = any> extends CustomEvent<T> {
|
||||
reason: EventCaller | null = null;
|
||||
private constructor(
|
||||
event: string,
|
||||
options?: CustomEventInit & {
|
||||
reason?: EventCaller | null;
|
||||
},
|
||||
) {
|
||||
super(event, options);
|
||||
this.reason = options?.reason ?? null;
|
||||
}
|
||||
|
||||
static fromEvent<Type extends keyof LlamaIndexEventMaps>(
|
||||
type: Type,
|
||||
detail: LlamaIndexEventMaps[Type],
|
||||
) {
|
||||
return new LlamaIndexCustomEvent(type, {
|
||||
detail: detail,
|
||||
reason: getEventCaller(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
type EventHandler<Event> = (event: LlamaIndexCustomEvent<Event>) => void;
|
||||
|
||||
export class CallbackManager {
|
||||
#handlers = new Map<keyof LlamaIndexEventMaps, EventHandler<any>[]>();
|
||||
|
||||
on<K extends keyof LlamaIndexEventMaps>(
|
||||
event: K,
|
||||
handler: EventHandler<LlamaIndexEventMaps[K]>,
|
||||
) {
|
||||
if (!this.#handlers.has(event)) {
|
||||
this.#handlers.set(event, []);
|
||||
}
|
||||
this.#handlers.get(event)!.push(handler);
|
||||
return this;
|
||||
}
|
||||
|
||||
off<K extends keyof LlamaIndexEventMaps>(
|
||||
event: K,
|
||||
handler: EventHandler<LlamaIndexEventMaps[K]>,
|
||||
) {
|
||||
if (!this.#handlers.has(event)) {
|
||||
return this;
|
||||
}
|
||||
const cbs = this.#handlers.get(event)!;
|
||||
const index = cbs.indexOf(handler);
|
||||
if (index > -1) {
|
||||
cbs.splice(index, 1);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
dispatchEvent<K extends keyof LlamaIndexEventMaps>(
|
||||
event: K,
|
||||
detail: LlamaIndexEventMaps[K],
|
||||
) {
|
||||
const cbs = this.#handlers.get(event);
|
||||
if (!cbs) {
|
||||
return;
|
||||
}
|
||||
queueMicrotask(() => {
|
||||
cbs.forEach((handler) =>
|
||||
handler(LlamaIndexCustomEvent.fromEvent(event, { ...detail })),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const globalCallbackManager = new CallbackManager();
|
||||
|
||||
const callbackManagerAsyncLocalStorage =
|
||||
new AsyncLocalStorage<CallbackManager>();
|
||||
|
||||
let currentCallbackManager: CallbackManager = globalCallbackManager;
|
||||
|
||||
export function getCallbackManager(): CallbackManager {
|
||||
return callbackManagerAsyncLocalStorage.getStore() ?? currentCallbackManager;
|
||||
}
|
||||
|
||||
export function setCallbackManager(callbackManager: CallbackManager) {
|
||||
currentCallbackManager = callbackManager;
|
||||
}
|
||||
|
||||
export function withCallbackManager<Result>(
|
||||
callbackManager: CallbackManager,
|
||||
fn: () => Result,
|
||||
): Result {
|
||||
return callbackManagerAsyncLocalStorage.run(callbackManager, fn);
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import { AsyncLocalStorage } from "@llamaindex/env";
|
||||
|
||||
const chunkSizeAsyncLocalStorage = new AsyncLocalStorage<number | undefined>();
|
||||
let globalChunkSize: number | null = null;
|
||||
let globalChunkSize: number = 1024;
|
||||
|
||||
export function getChunkSize(): number | undefined {
|
||||
export function getChunkSize(): number {
|
||||
return globalChunkSize ?? chunkSizeAsyncLocalStorage.getStore();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { AsyncLocalStorage, type Tokenizer, tokenizers } from "@llamaindex/env";
|
||||
|
||||
const chunkSizeAsyncLocalStorage = new AsyncLocalStorage<Tokenizer>();
|
||||
let globalTokenizer: Tokenizer = tokenizers.tokenizer();
|
||||
|
||||
export function getTokenizer(): Tokenizer {
|
||||
return globalTokenizer ?? chunkSizeAsyncLocalStorage.getStore();
|
||||
}
|
||||
|
||||
export function setTokenizer(tokenizer: Tokenizer | undefined) {
|
||||
if (tokenizer !== undefined) {
|
||||
globalTokenizer = tokenizer;
|
||||
}
|
||||
}
|
||||
|
||||
export function withTokenizer<Result>(
|
||||
tokenizer: Tokenizer,
|
||||
fn: () => Result,
|
||||
): Result {
|
||||
return chunkSizeAsyncLocalStorage.run(tokenizer, fn);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export type UUID = `${string}-${string}-${string}-${string}-${string}`;
|
||||
|
||||
export type JSONValue = string | number | boolean | JSONObject | JSONArray;
|
||||
|
||||
export type JSONObject = {
|
||||
[key: string]: JSONValue;
|
||||
};
|
||||
|
||||
export type JSONArray = Array<JSONValue>;
|
||||
@@ -1 +0,0 @@
|
||||
export * from "./schema";
|
||||
@@ -1,3 +1,5 @@
|
||||
import { streamConverter } from "../utils";
|
||||
import { extractText } from "../utils/llms";
|
||||
import type {
|
||||
ChatResponse,
|
||||
ChatResponseChunk,
|
||||
@@ -9,8 +11,7 @@ import type {
|
||||
LLMCompletionParamsStreaming,
|
||||
LLMMetadata,
|
||||
ToolCallLLMMessageOptions,
|
||||
} from "./types.js";
|
||||
import { extractText, streamConverter } from "./utils.js";
|
||||
} from "./type";
|
||||
|
||||
export abstract class BaseLLM<
|
||||
AdditionalChatOptions extends object = object,
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user