mirror of
https://github.com/run-llama/LlamaIndexTS.git
synced 2026-07-04 03:40:26 -04:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f99a237093 | |||
| fcbf18344c | |||
| bf8cbeb6c5 | |||
| e27e7dd054 | |||
| 8b66cf4341 | |||
| 6f4549bdea | |||
| c654398f75 | |||
| 0664a99945 | |||
| 58abc5731b | |||
| 7498b1e0f1 | |||
| 07a275fea5 | |||
| 1b6263e08d | |||
| 089f1d49c0 | |||
| 01c184c608 | |||
| 1752463ee6 | |||
| c825a2f743 | |||
| ba058dc8d4 | |||
| 04b2f8e062 | |||
| 62b874e14f | |||
| 9c9e9b4e03 | |||
| e3c307ab55 | |||
| b1b2baa969 | |||
| 0452af91cc | |||
| da5cfc42e5 | |||
| eb89223386 | |||
| 93dc3a31b3 | |||
| 345300f110 | |||
| f322c5d202 | |||
| 376d29a78f | |||
| 224d507ab5 | |||
| 1f680d731d | |||
| f0a1cc51b4 | |||
| fee3280799 | |||
| 54925bf1ae | |||
| 91d02a4fc0 | |||
| 086b94038e | |||
| 5d5716b339 | |||
| fb6db454d4 | |||
| e4d4e0d024 | |||
| 17724d961e |
+6
-1
@@ -31,7 +31,12 @@ module.exports = {
|
||||
"@typescript-eslint/ban-types": "off",
|
||||
"no-array-constructor": "off",
|
||||
"@typescript-eslint/no-array-constructor": "off",
|
||||
"@typescript-eslint/no-base-to-string": "off",
|
||||
"@typescript-eslint/no-base-to-string": [
|
||||
"error",
|
||||
{
|
||||
ignoredTypeNames: ["Error", "RegExp", "URL", "URLSearchParams"],
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-duplicate-enum-values": "off",
|
||||
"@typescript-eslint/no-duplicate-type-constituents": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
|
||||
+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
|
||||
|
||||
@@ -164,7 +164,7 @@ Check out our NextJS playground at https://llama-playground.vercel.app/. The sou
|
||||
|
||||
- [Node](/packages/llamaindex/src/Node.ts): The basic data building block. Most commonly, these are parts of the document split into manageable pieces that are small enough to be fed into an embedding model and LLM.
|
||||
|
||||
- [Embedding](/packages/llamaindex/src/embeddings/OpenAIEmbedding.ts): Embeddings are sets of floating point numbers which represent the data in a Node. By comparing the similarity of embeddings, we can derive an understanding of the similarity of two pieces of data. One use case is to compare the embedding of a question with the embeddings of our Nodes to see which Nodes may contain the data needed to answer that quesiton. Because the default service context is OpenAI, the default embedding is `OpenAIEmbedding`. If using different models, say through Ollama, use this [Embedding](/packages/llamaindex/src/embeddings/OllamaEmbedding.ts) (see all [here](/packages/llamaindex/src/embeddings)).
|
||||
- [Embedding](/packages/llamaindex/src/embeddings/OpenAIEmbedding.ts): Embeddings are sets of floating point numbers which represent the data in a Node. By comparing the similarity of embeddings, we can derive an understanding of the similarity of two pieces of data. One use case is to compare the embedding of a question with the embeddings of our Nodes to see which Nodes may contain the data needed to answer that question. Because the default service context is OpenAI, the default embedding is `OpenAIEmbedding`. If using different models, say through Ollama, use this [Embedding](/packages/llamaindex/src/embeddings/OllamaEmbedding.ts) (see all [here](/packages/llamaindex/src/embeddings)).
|
||||
|
||||
- [Indices](/packages/llamaindex/src/indices/): Indices store the Nodes and the embeddings of those nodes. QueryEngines retrieve Nodes from these Indices using embedding similarity.
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"llamaindex": minor
|
||||
"docs": minor
|
||||
---
|
||||
|
||||
Add deepseek llm class
|
||||
@@ -1,5 +1,82 @@
|
||||
# docs
|
||||
|
||||
## 0.0.60
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [fcbf183]
|
||||
- llamaindex@0.5.19
|
||||
|
||||
## 0.0.59
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8b66cf4]
|
||||
- llamaindex@0.5.18
|
||||
|
||||
## 0.0.58
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c654398]
|
||||
- llamaindex@0.5.17
|
||||
|
||||
## 0.0.57
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [58abc57]
|
||||
- llamaindex@0.5.16
|
||||
|
||||
## 0.0.56
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [01c184c]
|
||||
- Updated dependencies [07a275f]
|
||||
- llamaindex@0.5.15
|
||||
|
||||
## 0.0.55
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c825a2f]
|
||||
- llamaindex@0.5.14
|
||||
|
||||
## 0.0.54
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.13
|
||||
|
||||
## 0.0.53
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [345300f]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- llamaindex@0.5.12
|
||||
|
||||
## 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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Copy the URL in your browser and select the server you want your bot to join.
|
||||
#### DiscordReader()
|
||||
|
||||
- `discordToken?`: The Discord bot token.
|
||||
- `makeRequest?`: Optionally provide a custom request function for edge environments, e.g. `fetch`. See discord.js for more info.
|
||||
- `requestHandler?`: Optionally provide a custom request function for edge environments, e.g. `fetch`. See discord.js for more info.
|
||||
|
||||
#### DiscordReader.loadData
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -41,11 +41,14 @@ They can be divided into two groups.
|
||||
- `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 LLMs/embeddings performances in most cases.
|
||||
- `pageSeparator?` Optional. The page separator to use. Defaults is `\\n---\\n`.
|
||||
- `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`.
|
||||
- `splitByPage` Wether to split the results, creating one document per page. Uses the set `pageSeparator` or `\n---\n` as fallback. Default is true.
|
||||
- `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`.
|
||||
|
||||
@@ -31,7 +31,7 @@ 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
|
||||
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==`
|
||||
@@ -67,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/)
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docs",
|
||||
"version": "0.0.50",
|
||||
"version": "0.0.60",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
|
||||
@@ -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);
|
||||
@@ -0,0 +1,31 @@
|
||||
# Weaviate Vector Store
|
||||
|
||||
Here are two sample scripts which work with loading and querying data from a Weaviate Vector Store.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- An Weaviate Vector Database
|
||||
- Hosted https://weaviate.io/
|
||||
- Self Hosted https://weaviate.io/developers/weaviate/installation/docker-compose#starter-docker-compose-file
|
||||
- An OpenAI API Key
|
||||
|
||||
## Setup
|
||||
|
||||
1. Set your env variables:
|
||||
|
||||
- `WEAVIATE_CLUSTER_URL`: Address of your Weaviate Vector Store (like localhost:8080)
|
||||
- `WEAVIATE_API_KEY`: Your Weaviate API key
|
||||
- `OPENAI_API_KEY`: Your OpenAI key
|
||||
|
||||
2. `cd` Into the `examples` directory
|
||||
3. run `npm i`
|
||||
|
||||
## Load the data
|
||||
|
||||
This sample loads the same dataset of movie reviews as sample dataset
|
||||
|
||||
run `npx tsx weaviate/load`
|
||||
|
||||
## Use RAG to Query the data
|
||||
|
||||
run `npx tsx weaviate/query`
|
||||
@@ -0,0 +1,23 @@
|
||||
import {
|
||||
PapaCSVReader,
|
||||
storageContextFromDefaults,
|
||||
VectorStoreIndex,
|
||||
WeaviateVectorStore,
|
||||
} from "llamaindex";
|
||||
|
||||
const indexName = "MovieReviews";
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const reader = new PapaCSVReader(false);
|
||||
const docs = await reader.loadData("./data/movie_reviews.csv");
|
||||
const vectorStore = new WeaviateVectorStore({ indexName });
|
||||
const storageContext = await storageContextFromDefaults({ vectorStore });
|
||||
await VectorStoreIndex.fromDocuments(docs, { storageContext });
|
||||
console.log("Successfully loaded data into Weaviate");
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
void main();
|
||||
@@ -0,0 +1,46 @@
|
||||
import { VectorStoreIndex, WeaviateVectorStore } from "llamaindex";
|
||||
|
||||
const indexName = "MovieReviews";
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const query = "Get all movie titles.";
|
||||
const vectorStore = new WeaviateVectorStore({ indexName });
|
||||
const index = await VectorStoreIndex.fromVectorStore(vectorStore);
|
||||
const retriever = index.asRetriever({ similarityTopK: 20 });
|
||||
|
||||
const queryEngine = index.asQueryEngine({ retriever });
|
||||
const results = await queryEngine.query({ query });
|
||||
console.log(`Query from ${results.sourceNodes?.length} nodes`);
|
||||
console.log(results.response);
|
||||
|
||||
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_21",
|
||||
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();
|
||||
@@ -1,5 +1,13 @@
|
||||
# @llamaindex/autotool
|
||||
|
||||
## 2.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 58abc57: fix: align version
|
||||
- Updated dependencies [58abc57]
|
||||
- llamaindex@0.5.16
|
||||
|
||||
## 2.0.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,5 +1,89 @@
|
||||
# @llamaindex/autotool-02-next-example
|
||||
|
||||
## 0.1.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [fcbf183]
|
||||
- llamaindex@0.5.19
|
||||
- @llamaindex/autotool@2.0.1
|
||||
|
||||
## 0.1.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8b66cf4]
|
||||
- llamaindex@0.5.18
|
||||
- @llamaindex/autotool@2.0.1
|
||||
|
||||
## 0.1.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c654398]
|
||||
- llamaindex@0.5.17
|
||||
- @llamaindex/autotool@2.0.1
|
||||
|
||||
## 0.1.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [58abc57]
|
||||
- @llamaindex/autotool@2.0.1
|
||||
- llamaindex@0.5.16
|
||||
|
||||
## 0.1.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [01c184c]
|
||||
- Updated dependencies [07a275f]
|
||||
- llamaindex@0.5.15
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c825a2f]
|
||||
- llamaindex@0.5.14
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.38
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.13
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.37
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [345300f]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- llamaindex@0.5.12
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/autotool-02-next-example",
|
||||
"private": true,
|
||||
"version": "0.1.34",
|
||||
"version": "0.1.44",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/autotool",
|
||||
"type": "module",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"description": "auto transpile your JS function to LLM Agent compatible",
|
||||
"files": [
|
||||
"dist",
|
||||
@@ -51,7 +51,7 @@
|
||||
"unplugin": "^1.10.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"llamaindex": "^0.5.9",
|
||||
"llamaindex": "^0.5.19",
|
||||
"openai": "^4",
|
||||
"typescript": "^4"
|
||||
},
|
||||
@@ -70,7 +70,7 @@
|
||||
"@swc/types": "^0.1.8",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"@types/node": "^20.12.11",
|
||||
"bunchee": "5.3.0-beta.0",
|
||||
"bunchee": "5.3.1",
|
||||
"llamaindex": "workspace:*",
|
||||
"next": "14.2.5",
|
||||
"rollup": "^4.18.0",
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @llamaindex/cloud
|
||||
|
||||
## 0.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 58abc57: fix: align version
|
||||
|
||||
## 0.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1f680d7: chore: bump llamacloud api
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
+835
-117
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "@llamaindex/cloud",
|
||||
"version": "0.2.0",
|
||||
"version": "0.2.2",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"generate": "pnpm dlx @hey-api/openapi-ts",
|
||||
"generate": "pnpm dlx @hey-api/openapi-ts@0.49.0",
|
||||
"build": "pnpm run generate && bunchee"
|
||||
},
|
||||
"files": [
|
||||
@@ -35,6 +35,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hey-api/openapi-ts": "^0.48.0",
|
||||
"bunchee": "5.3.0-beta.0"
|
||||
"bunchee": "5.3.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,49 @@
|
||||
# @llamaindex/community
|
||||
|
||||
## 0.0.30
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e27e7dd]
|
||||
- @llamaindex/core@0.1.9
|
||||
|
||||
## 0.0.29
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 58abc57: fix: align version
|
||||
- Updated dependencies [58abc57]
|
||||
- @llamaindex/core@0.1.8
|
||||
- @llamaindex/env@0.1.9
|
||||
|
||||
## 0.0.28
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [04b2f8e]
|
||||
- @llamaindex/core@0.1.7
|
||||
|
||||
## 0.0.27
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [0452af9]
|
||||
- @llamaindex/core@0.1.6
|
||||
|
||||
## 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
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
- 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.24",
|
||||
"version": "0.0.30",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -43,10 +43,11 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.14.2",
|
||||
"bunchee": "5.3.0-beta.0"
|
||||
"bunchee": "5.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-bedrock-runtime": "^3.613.0",
|
||||
"@llamaindex/core": "workspace:*"
|
||||
"@llamaindex/core": "workspace:*",
|
||||
"@llamaindex/env": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@ export {
|
||||
BEDROCK_MODELS,
|
||||
BEDROCK_MODEL_MAX_TOKENS,
|
||||
Bedrock,
|
||||
} from "./llm/bedrock/base.js";
|
||||
} from "./llm/bedrock/index.js";
|
||||
|
||||
+6
-5
@@ -16,17 +16,18 @@ import {
|
||||
type BedrockChatStreamResponse,
|
||||
Provider,
|
||||
} from "../provider";
|
||||
import { toUtf8 } from "../utils";
|
||||
import type {
|
||||
AnthropicNoneStreamingResponse,
|
||||
AnthropicStreamEvent,
|
||||
AnthropicTextContent,
|
||||
ToolBlock,
|
||||
} from "../types";
|
||||
} from "./types";
|
||||
|
||||
import {
|
||||
mapBaseToolsToAnthropicTools,
|
||||
mapChatMessagesToAnthropicMessages,
|
||||
toUtf8,
|
||||
} from "../utils";
|
||||
} from "./utils";
|
||||
|
||||
export class AnthropicProvider extends Provider<AnthropicStreamEvent> {
|
||||
getResultFromResponse(
|
||||
@@ -69,6 +70,7 @@ export class AnthropicProvider extends Provider<AnthropicStreamEvent> {
|
||||
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" &&
|
||||
@@ -114,11 +116,10 @@ export class AnthropicProvider extends Provider<AnthropicStreamEvent> {
|
||||
};
|
||||
}
|
||||
}
|
||||
const delta = this.getTextFromStreamResponse(response);
|
||||
if (!delta && !options) continue;
|
||||
|
||||
yield {
|
||||
delta,
|
||||
delta: options ? "" : delta,
|
||||
options,
|
||||
raw: response,
|
||||
};
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
};
|
||||
+11
-2
@@ -22,8 +22,16 @@ import {
|
||||
type BedrockChatStreamResponse,
|
||||
Provider,
|
||||
} from "./provider";
|
||||
import { PROVIDERS } from "./providers";
|
||||
import { mapMessageContentToMessageContentDetails } from "./utils.js";
|
||||
import { mapMessageContentToMessageContentDetails } from "./utils";
|
||||
|
||||
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,
|
||||
@@ -140,6 +148,7 @@ 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,
|
||||
];
|
||||
|
||||
const getProvider = (model: string): Provider => {
|
||||
@@ -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;
|
||||
};
|
||||
@@ -23,6 +23,7 @@ export type BedrockChatStreamResponse = AsyncIterable<
|
||||
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[];
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Provider } from "../provider";
|
||||
import { AnthropicProvider } from "./anthropic";
|
||||
import { MetaProvider } from "./meta";
|
||||
|
||||
// Other providers should go here
|
||||
export const PROVIDERS: { [key: string]: Provider } = {
|
||||
anthropic: new AnthropicProvider(),
|
||||
meta: new MetaProvider(),
|
||||
};
|
||||
@@ -1,69 +0,0 @@
|
||||
import type {
|
||||
InvokeModelCommandInput,
|
||||
InvokeModelWithResponseStreamCommandInput,
|
||||
} from "@aws-sdk/client-bedrock-runtime";
|
||||
import type { ChatMessage, LLMMetadata } from "@llamaindex/core/llms";
|
||||
import type { MetaNoneStreamingResponse, MetaStreamEvent } from "../types";
|
||||
import {
|
||||
mapChatMessagesToMetaLlama2Messages,
|
||||
mapChatMessagesToMetaLlama3Messages,
|
||||
toUtf8,
|
||||
} from "../utils";
|
||||
|
||||
import { Provider } from "../provider";
|
||||
|
||||
export class MetaProvider extends Provider<MetaStreamEvent> {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
getResultFromResponse(
|
||||
response: Record<string, any>,
|
||||
): MetaNoneStreamingResponse {
|
||||
return JSON.parse(toUtf8(response.body));
|
||||
}
|
||||
|
||||
getToolsFromResponse(_response: Record<string, any>): never {
|
||||
throw new Error("Not supported by this provider.");
|
||||
}
|
||||
|
||||
getTextFromResponse(response: Record<string, any>): string {
|
||||
const result = this.getResultFromResponse(response);
|
||||
return result.generation;
|
||||
}
|
||||
|
||||
getTextFromStreamResponse(response: Record<string, any>): string {
|
||||
const event = this.getStreamingEventResponse(response);
|
||||
if (event?.generation) {
|
||||
return event.generation;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
getRequestBody<T extends ChatMessage>(
|
||||
metadata: LLMMetadata,
|
||||
messages: T[],
|
||||
): InvokeModelCommandInput | InvokeModelWithResponseStreamCommandInput {
|
||||
let promptFunction: (messages: ChatMessage[]) => string;
|
||||
|
||||
if (metadata.model.startsWith("meta.llama3")) {
|
||||
promptFunction = mapChatMessagesToMetaLlama3Messages;
|
||||
} else if (metadata.model.startsWith("meta.llama2")) {
|
||||
promptFunction = mapChatMessagesToMetaLlama2Messages;
|
||||
} 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: promptFunction(messages),
|
||||
max_gen_len: metadata.maxTokens,
|
||||
temperature: metadata.temperature,
|
||||
top_p: metadata.topP,
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,165 +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 AnthropicStreamEvent =
|
||||
| { type: "message_start"; message: Message }
|
||||
| ContentBlockStart
|
||||
| ContentBlockDelta
|
||||
| ContentBlockStop
|
||||
| MessageDelta
|
||||
| MessageStop;
|
||||
|
||||
export type AnthropicContent =
|
||||
| AnthropicTextContent
|
||||
| AnthropicImageContent
|
||||
| AnthropicToolContent
|
||||
| AnthropicToolResultContent;
|
||||
|
||||
export type MetaTextContent = string;
|
||||
|
||||
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 MetaMessage = {
|
||||
role: "user" | "assistant" | "system";
|
||||
content: MetaTextContent;
|
||||
};
|
||||
|
||||
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 };
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
@@ -1,28 +1,7 @@
|
||||
import type { JSONObject } from "@llamaindex/core/global";
|
||||
import type {
|
||||
BaseTool,
|
||||
ChatMessage,
|
||||
MessageContent,
|
||||
MessageContentDetail,
|
||||
MessageContentTextDetail,
|
||||
ToolCallLLMMessageOptions,
|
||||
ToolMetadata,
|
||||
} from "@llamaindex/core/llms";
|
||||
import type {
|
||||
AnthropicContent,
|
||||
AnthropicImageContent,
|
||||
AnthropicMediaTypes,
|
||||
AnthropicMessage,
|
||||
AnthropicTextContent,
|
||||
MetaMessage,
|
||||
} from "./types.js";
|
||||
|
||||
const ACCEPTED_IMAGE_MIME_TYPES = [
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/webp",
|
||||
"image/gif",
|
||||
];
|
||||
|
||||
export const mapMessageContentToMessageContentDetails = (
|
||||
content: MessageContent,
|
||||
@@ -30,250 +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 mapChatMessagesToMetaMessages = <T extends ChatMessage>(
|
||||
messages: T[],
|
||||
): MetaMessage[] => {
|
||||
return messages.map((msg) => {
|
||||
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:
|
||||
msg.role === "assistant"
|
||||
? "assistant"
|
||||
: msg.role === "user"
|
||||
? "user"
|
||||
: "system",
|
||||
content,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Documentation at https://llama.meta.com/docs/model-cards-and-prompt-formats/meta-llama-3
|
||||
*/
|
||||
export const mapChatMessagesToMetaLlama3Messages = <T extends ChatMessage>(
|
||||
messages: T[],
|
||||
): string => {
|
||||
const mapped = mapChatMessagesToMetaMessages(messages).map((message) => {
|
||||
const text = message.content;
|
||||
return `<|start_header_id|>${message.role}<|end_header_id|>\n${text}\n<|eot_id|>\n`;
|
||||
});
|
||||
return (
|
||||
"<|begin_of_text|>" +
|
||||
mapped.join("\n") +
|
||||
"\n<|start_header_id|>assistant<|end_header_id|>\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;
|
||||
};
|
||||
|
||||
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,5 +1,37 @@
|
||||
# @llamaindex/core
|
||||
|
||||
## 0.1.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- e27e7dd: chore: bump `natural` to 8.0.1
|
||||
|
||||
## 0.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 58abc57: fix: align version
|
||||
- Updated dependencies [58abc57]
|
||||
- @llamaindex/env@0.1.9
|
||||
|
||||
## 0.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 04b2f8e: Fix issue with metadata included after sentence splitter
|
||||
|
||||
## 0.1.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 0452af9: fix: handling errors in splitBySentenceTokenizer
|
||||
|
||||
## 0.1.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 91d02a4: feat: support transform component callable
|
||||
|
||||
## 0.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/core",
|
||||
"type": "module",
|
||||
"version": "0.1.4",
|
||||
"version": "0.1.9",
|
||||
"description": "LlamaIndex Core Module",
|
||||
"exports": {
|
||||
"./node-parser": {
|
||||
@@ -131,8 +131,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"ajv": "^8.16.0",
|
||||
"bunchee": "5.3.0-beta.0",
|
||||
"natural": "^7.1.0"
|
||||
"bunchee": "5.3.1",
|
||||
"natural": "^8.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@llamaindex/env": "workspace:*",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { type Tokenizers } from "@llamaindex/env";
|
||||
import type { MessageContentDetail } from "../llms";
|
||||
import type { TransformComponent } from "../schema";
|
||||
import { BaseNode, MetadataMode } from "../schema";
|
||||
import { BaseNode, MetadataMode, TransformComponent } from "../schema";
|
||||
import { extractSingleText } from "../utils";
|
||||
import { truncateMaxTokens } from "./tokenizer.js";
|
||||
import { SimilarityType, similarity } from "./utils.js";
|
||||
@@ -20,10 +19,29 @@ export type BaseEmbeddingOptions = {
|
||||
logProgress?: boolean;
|
||||
};
|
||||
|
||||
export abstract class BaseEmbedding implements TransformComponent {
|
||||
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[],
|
||||
@@ -76,21 +94,6 @@ export abstract class BaseEmbedding implements TransformComponent {
|
||||
);
|
||||
}
|
||||
|
||||
async transform(
|
||||
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;
|
||||
}
|
||||
|
||||
truncateMaxTokens(input: string[]): string[] {
|
||||
return input.map((s) => {
|
||||
// truncate to max tokens
|
||||
|
||||
@@ -5,13 +5,19 @@ import {
|
||||
MetadataMode,
|
||||
NodeRelationship,
|
||||
TextNode,
|
||||
type TransformComponent,
|
||||
TransformComponent,
|
||||
} from "../schema";
|
||||
|
||||
export abstract class NodeParser implements TransformComponent {
|
||||
export abstract class NodeParser extends TransformComponent {
|
||||
includeMetadata: boolean = true;
|
||||
includePrevNextRel: boolean = true;
|
||||
|
||||
constructor() {
|
||||
super(async (nodes: BaseNode[]): Promise<BaseNode[]> => {
|
||||
return this.getNodesFromDocuments(nodes as TextNode[]);
|
||||
});
|
||||
}
|
||||
|
||||
protected postProcessParsedNodes(
|
||||
nodes: TextNode[],
|
||||
parentDocMap: Map<string, TextNode>,
|
||||
@@ -90,10 +96,6 @@ export abstract class NodeParser implements TransformComponent {
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
async transform(nodes: BaseNode[], options?: {}): Promise<BaseNode[]> {
|
||||
return this.getNodesFromDocuments(nodes as TextNode[]);
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class TextSplitter extends NodeParser {
|
||||
@@ -138,7 +140,7 @@ export abstract class MetadataAwareTextSplitter extends TextSplitter {
|
||||
return nodes.reduce<TextNode[]>((allNodes, node) => {
|
||||
const metadataStr = this.getMetadataString(node);
|
||||
const splits = this.splitTextMetadataAware(
|
||||
node.getContent(MetadataMode.ALL),
|
||||
node.getContent(MetadataMode.NONE),
|
||||
metadataStr,
|
||||
);
|
||||
return allNodes.concat(buildNodeFromSplits(splits, node));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+1
@@ -1,4 +1,5 @@
|
||||
declare class SentenceTokenizer {
|
||||
constructor(abbreviations?: string[]);
|
||||
tokenize(text: string): string[];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __commonJS = (cb, mod) =>
|
||||
function __require() {
|
||||
return (
|
||||
mod ||
|
||||
(0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod),
|
||||
mod.exports
|
||||
);
|
||||
};
|
||||
|
||||
// lib/natural/tokenizers/tokenizer.js
|
||||
var require_tokenizer = __commonJS({
|
||||
"lib/natural/tokenizers/tokenizer.js"(exports, module) {
|
||||
"use strict";
|
||||
var Tokenizer = class {
|
||||
trim(array) {
|
||||
while (array[array.length - 1] === "") {
|
||||
array.pop();
|
||||
}
|
||||
while (array[0] === "") {
|
||||
array.shift();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
};
|
||||
module.exports = Tokenizer;
|
||||
},
|
||||
});
|
||||
|
||||
// lib/natural/tokenizers/sentence_tokenizer.js
|
||||
var require_sentence_tokenizer = __commonJS({
|
||||
"lib/natural/tokenizers/sentence_tokenizer.js"(exports, module) {
|
||||
var Tokenizer = require_tokenizer();
|
||||
var NUM = "NUMBER";
|
||||
var DELIM = "DELIM";
|
||||
var URI = "URI";
|
||||
var ABBREV = "ABBREV";
|
||||
var DEBUG = false;
|
||||
function generateUniqueCode(base, index) {
|
||||
return `{{${base}_${index}}}`;
|
||||
}
|
||||
function escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
}
|
||||
var SentenceTokenizer = class extends Tokenizer {
|
||||
constructor(abbreviations) {
|
||||
super();
|
||||
if (abbreviations) {
|
||||
this.abbreviations = abbreviations;
|
||||
} else {
|
||||
this.abbreviations = [];
|
||||
}
|
||||
this.replacementMap = null;
|
||||
this.replacementCounter = 0;
|
||||
}
|
||||
replaceUrisWithPlaceholders(text) {
|
||||
const urlPattern =
|
||||
/(https?:\/\/\S+|www\.\S+|ftp:\/\/\S+|(mailto:)?[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|file:\/\/\S+)/gi;
|
||||
const modifiedText = text.replace(urlPattern, (match) => {
|
||||
const placeholder = generateUniqueCode(
|
||||
URI,
|
||||
this.replacementCounter++,
|
||||
);
|
||||
this.replacementMap.set(placeholder, match);
|
||||
return placeholder;
|
||||
});
|
||||
return modifiedText;
|
||||
}
|
||||
replaceAbbreviations(text) {
|
||||
if (this.abbreviations.length === 0) {
|
||||
return text;
|
||||
}
|
||||
const pattern = new RegExp(
|
||||
`(${this.abbreviations.map((abbrev) => escapeRegExp(abbrev)).join("|")})`,
|
||||
"gi",
|
||||
);
|
||||
const replacedText = text.replace(pattern, (match) => {
|
||||
const code = generateUniqueCode(ABBREV, this.replacementCounter++);
|
||||
this.replacementMap.set(code, match);
|
||||
return code;
|
||||
});
|
||||
return replacedText;
|
||||
}
|
||||
replaceDelimitersWithPlaceholders(text) {
|
||||
const delimiterPattern = /([.?!… ]*)([.?!…])(["'”’)}\]]?)/g;
|
||||
const modifiedText = text.replace(
|
||||
delimiterPattern,
|
||||
(match, p1, p2, p3) => {
|
||||
const placeholder = generateUniqueCode(
|
||||
DELIM,
|
||||
this.replacementCounter++,
|
||||
);
|
||||
this.delimiterMap.set(placeholder, p1 + p2 + p3);
|
||||
return placeholder;
|
||||
},
|
||||
);
|
||||
return modifiedText;
|
||||
}
|
||||
splitOnPlaceholders(text, placeholders) {
|
||||
if (this.delimiterMap.size === 0) {
|
||||
return [text];
|
||||
}
|
||||
const keys = Array.from(this.delimiterMap.keys());
|
||||
const pattern = new RegExp(`(${keys.map(escapeRegExp).join("|")})`);
|
||||
const parts = text.split(pattern);
|
||||
const sentences = [];
|
||||
for (let i = 0; i < parts.length; i += 2) {
|
||||
const sentence = parts[i];
|
||||
const placeholder = parts[i + 1] || "";
|
||||
sentences.push(sentence + placeholder);
|
||||
}
|
||||
return sentences;
|
||||
}
|
||||
replaceNumbersWithCode(text) {
|
||||
const numberPattern = /\b\d{1,3}(?:,\d{3})*(?:\.\d+)?\b/g;
|
||||
const replacedText = text.replace(numberPattern, (match) => {
|
||||
const code = generateUniqueCode(NUM, this.replacementCounter++);
|
||||
this.replacementMap.set(code, match);
|
||||
return code;
|
||||
});
|
||||
return replacedText;
|
||||
}
|
||||
revertReplacements(text) {
|
||||
let originalText = text;
|
||||
for (const [
|
||||
placeholder,
|
||||
replacement,
|
||||
] of this.replacementMap.entries()) {
|
||||
const pattern = new RegExp(escapeRegExp(placeholder), "g");
|
||||
originalText = originalText.replace(pattern, replacement);
|
||||
}
|
||||
return originalText;
|
||||
}
|
||||
revertDelimiters(text) {
|
||||
let originalText = text;
|
||||
for (const [placeholder, replacement] of this.delimiterMap.entries()) {
|
||||
const pattern = new RegExp(escapeRegExp(placeholder), "g");
|
||||
originalText = originalText.replace(pattern, replacement);
|
||||
}
|
||||
return originalText;
|
||||
}
|
||||
tokenize(text) {
|
||||
this.replacementCounter = 0;
|
||||
this.replacementMap = /* @__PURE__ */ new Map();
|
||||
this.delimiterMap = /* @__PURE__ */ new Map();
|
||||
DEBUG &&
|
||||
console.log(
|
||||
"---Start of sentence tokenization-----------------------",
|
||||
);
|
||||
DEBUG && console.log("Original input: >>>" + text + "<<<");
|
||||
const result1 = this.replaceAbbreviations(text);
|
||||
DEBUG &&
|
||||
console.log(
|
||||
"Phase 1: replacing abbreviations: " + JSON.stringify(result1),
|
||||
);
|
||||
const result2 = this.replaceUrisWithPlaceholders(result1);
|
||||
DEBUG &&
|
||||
console.log("Phase 2: replacing URIs: " + JSON.stringify(result2));
|
||||
const result3 = this.replaceNumbersWithCode(result2);
|
||||
DEBUG &&
|
||||
console.log(
|
||||
"Phase 3: replacing numbers with placeholders: " +
|
||||
JSON.stringify(result3),
|
||||
);
|
||||
const result4 = this.replaceDelimitersWithPlaceholders(result3);
|
||||
DEBUG &&
|
||||
console.log(
|
||||
"Phase 4: replacing delimiters with placeholders: " +
|
||||
JSON.stringify(result4),
|
||||
);
|
||||
const sentences = this.splitOnPlaceholders(result4);
|
||||
DEBUG &&
|
||||
console.log(
|
||||
"Phase 5: splitting into sentences on placeholders: " +
|
||||
JSON.stringify(sentences),
|
||||
);
|
||||
const newSentences = sentences.map((s) => {
|
||||
const s1 = this.revertReplacements(s);
|
||||
return this.revertDelimiters(s1);
|
||||
});
|
||||
DEBUG &&
|
||||
console.log(
|
||||
"Phase 6: replacing back abbreviations, URIs, numbers and delimiters: " +
|
||||
JSON.stringify(newSentences),
|
||||
);
|
||||
const trimmedSentences = this.trim(newSentences);
|
||||
DEBUG &&
|
||||
console.log(
|
||||
"Phase 7: trimming array of empty sentences: " +
|
||||
JSON.stringify(trimmedSentences),
|
||||
);
|
||||
const trimmedSentences2 = trimmedSentences.map((sent) => sent.trim());
|
||||
DEBUG &&
|
||||
console.log(
|
||||
"Phase 8: trimming sentences from surrounding whitespace: " +
|
||||
JSON.stringify(trimmedSentences2),
|
||||
);
|
||||
DEBUG &&
|
||||
console.log(
|
||||
"---End of sentence tokenization--------------------------",
|
||||
);
|
||||
DEBUG &&
|
||||
console.log(
|
||||
"---Replacement map---------------------------------------",
|
||||
);
|
||||
DEBUG && console.log([...this.replacementMap.entries()]);
|
||||
DEBUG &&
|
||||
console.log(
|
||||
"---Delimiter map-----------------------------------------",
|
||||
);
|
||||
DEBUG && console.log([...this.delimiterMap.entries()]);
|
||||
DEBUG &&
|
||||
console.log(
|
||||
"---------------------------------------------------------",
|
||||
);
|
||||
return trimmedSentences2;
|
||||
}
|
||||
};
|
||||
module.exports = SentenceTokenizer;
|
||||
},
|
||||
});
|
||||
export default require_sentence_tokenizer();
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { TextSplitter } from "./base";
|
||||
import SentenceTokenizerNew from "./sentence-tokenizer-parser.js";
|
||||
import SentenceTokenizer from "./sentence_tokenizer";
|
||||
|
||||
export type TextSplitterFn = (text: string) => string[];
|
||||
|
||||
@@ -31,15 +31,25 @@ export const splitByChar = (): TextSplitterFn => {
|
||||
return (text: string) => text.split("");
|
||||
};
|
||||
|
||||
let sentenceTokenizer: SentenceTokenizerNew | null = null;
|
||||
let sentenceTokenizer: SentenceTokenizer | null = null;
|
||||
|
||||
export const splitBySentenceTokenizer = (): TextSplitterFn => {
|
||||
if (!sentenceTokenizer) {
|
||||
sentenceTokenizer = new SentenceTokenizerNew();
|
||||
sentenceTokenizer = new SentenceTokenizer([
|
||||
"i.e.",
|
||||
"etc.",
|
||||
"vs.",
|
||||
"Inc.",
|
||||
"A.S.A.P.",
|
||||
]);
|
||||
}
|
||||
const tokenizer = sentenceTokenizer;
|
||||
return (text: string) => {
|
||||
return tokenizer.tokenize(text);
|
||||
try {
|
||||
return tokenizer.tokenize(text);
|
||||
} catch {
|
||||
return [text];
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export * from "./node";
|
||||
export type { TransformComponent } from "./type";
|
||||
export { FileReader, TransformComponent, type BaseReader } from "./type";
|
||||
export { EngineResponse } from "./type/engine–response";
|
||||
export * from "./zod";
|
||||
|
||||
@@ -1,8 +1,64 @@
|
||||
import type { BaseNode } from "./node";
|
||||
import { fs, path, randomUUID } from "@llamaindex/env";
|
||||
import type { BaseNode, Document } from "./node";
|
||||
|
||||
export interface TransformComponent {
|
||||
transform<Options extends Record<string, unknown>>(
|
||||
interface TransformComponentSignature {
|
||||
<Options extends Record<string, unknown>>(
|
||||
nodes: BaseNode[],
|
||||
options?: Options,
|
||||
): Promise<BaseNode[]>;
|
||||
}
|
||||
|
||||
export interface TransformComponent extends TransformComponentSignature {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export class TransformComponent {
|
||||
constructor(transformFn: TransformComponentSignature) {
|
||||
Object.defineProperties(
|
||||
transformFn,
|
||||
Object.getOwnPropertyDescriptors(this.constructor.prototype),
|
||||
);
|
||||
const transform = function transform(
|
||||
...args: Parameters<TransformComponentSignature>
|
||||
) {
|
||||
return transformFn(...args);
|
||||
};
|
||||
Reflect.setPrototypeOf(transform, new.target.prototype);
|
||||
transform.id = randomUUID();
|
||||
return transform;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A reader takes imports data into Document objects.
|
||||
*/
|
||||
export interface BaseReader {
|
||||
loadData(...args: unknown[]): Promise<Document[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A FileReader takes file paths and imports data into Document objects.
|
||||
*/
|
||||
export abstract class FileReader implements BaseReader {
|
||||
abstract loadDataAsContent(
|
||||
fileContent: Uint8Array,
|
||||
fileName?: string,
|
||||
): Promise<Document[]>;
|
||||
|
||||
async loadData(filePath: string): Promise<Document[]> {
|
||||
const fileContent = await fs.readFile(filePath);
|
||||
const fileName = path.basename(filePath);
|
||||
const docs = await this.loadDataAsContent(fileContent, fileName);
|
||||
docs.forEach(FileReader.addMetaData(filePath));
|
||||
return docs;
|
||||
}
|
||||
|
||||
static addMetaData(filePath: string) {
|
||||
return (doc: Document, index: number) => {
|
||||
// generate id as loadDataAsContent is only responsible for the content
|
||||
doc.id_ = `${filePath}_${index + 1}`;
|
||||
doc.metadata["file_path"] = path.resolve(filePath);
|
||||
doc.metadata["file_name"] = path.basename(filePath);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { SentenceSplitter } from "@llamaindex/core/node-parser";
|
||||
import {
|
||||
SentenceSplitter,
|
||||
splitBySentenceTokenizer,
|
||||
} from "@llamaindex/core/node-parser";
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
describe("SentenceSplitter", () => {
|
||||
describe("sentence splitter", () => {
|
||||
test("initializes", () => {
|
||||
const sentenceSplitter = new SentenceSplitter();
|
||||
expect(sentenceSplitter).toBeDefined();
|
||||
@@ -105,4 +108,11 @@ describe("SentenceSplitter", () => {
|
||||
"因为他照了人类,连我都在内。",
|
||||
]);
|
||||
});
|
||||
|
||||
test("issue 1087 - edge case when input with brackets", () => {
|
||||
const text =
|
||||
"A card must be of uniform thickness and made of unfolded and uncreased paper or cardstock of approximately the quality and weight of a stamped card (i.e., a card available from USPS).";
|
||||
const split = splitBySentenceTokenizer();
|
||||
expect(split(text)).toEqual([text]);
|
||||
});
|
||||
});
|
||||
|
||||
Vendored
+6
@@ -1,5 +1,11 @@
|
||||
# @llamaindex/env
|
||||
|
||||
## 0.1.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 58abc57: fix: align version
|
||||
|
||||
## 0.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/env",
|
||||
"description": "environment wrapper, supports all JS environment including node, deno, bun, edge runtime, and cloudflare worker",
|
||||
"version": "0.1.8",
|
||||
"version": "0.1.9",
|
||||
"type": "module",
|
||||
"types": "dist/type/index.d.ts",
|
||||
"main": "dist/cjs/index.js",
|
||||
|
||||
@@ -1,5 +1,80 @@
|
||||
# @llamaindex/experimental
|
||||
|
||||
## 0.0.69
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [fcbf183]
|
||||
- llamaindex@0.5.19
|
||||
|
||||
## 0.0.68
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8b66cf4]
|
||||
- llamaindex@0.5.18
|
||||
|
||||
## 0.0.67
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c654398]
|
||||
- llamaindex@0.5.17
|
||||
|
||||
## 0.0.66
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 58abc57: fix: align version
|
||||
- Updated dependencies [58abc57]
|
||||
- llamaindex@0.5.16
|
||||
|
||||
## 0.0.65
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [01c184c]
|
||||
- Updated dependencies [07a275f]
|
||||
- llamaindex@0.5.15
|
||||
|
||||
## 0.0.64
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c825a2f]
|
||||
- llamaindex@0.5.14
|
||||
|
||||
## 0.0.63
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.13
|
||||
|
||||
## 0.0.62
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [345300f]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- llamaindex@0.5.12
|
||||
|
||||
## 0.0.61
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.0.60
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [086b940]
|
||||
- Updated dependencies [5d5716b]
|
||||
- Updated dependencies [91d02a4]
|
||||
- Updated dependencies [fb6db45]
|
||||
- llamaindex@0.5.10
|
||||
|
||||
## 0.0.59
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/experimental",
|
||||
"description": "Experimental package for LlamaIndexTS",
|
||||
"version": "0.0.59",
|
||||
"version": "0.0.69",
|
||||
"type": "module",
|
||||
"types": "dist/type/index.d.ts",
|
||||
"main": "dist/cjs/index.js",
|
||||
|
||||
@@ -162,18 +162,18 @@ export class JSONQueryEngine implements QueryEngine {
|
||||
|
||||
const schema = this.getSchemaContext();
|
||||
|
||||
const jsonPathResponseStr = await this.serviceContext.llm.complete({
|
||||
const { text: jsonPathResponse } = await this.serviceContext.llm.complete({
|
||||
prompt: this.jsonPathPrompt({ query, schema }),
|
||||
});
|
||||
|
||||
if (this.verbose) {
|
||||
console.log(
|
||||
`> JSONPath Instructions:\n\`\`\`\n${jsonPathResponseStr}\n\`\`\`\n`,
|
||||
`> JSONPath Instructions:\n\`\`\`\n${jsonPathResponse}\n\`\`\`\n`,
|
||||
);
|
||||
}
|
||||
|
||||
const jsonPathOutput = await this.outputProcessor({
|
||||
llmOutput: jsonPathResponseStr.text,
|
||||
llmOutput: jsonPathResponse,
|
||||
jsonValue: this.jsonValue,
|
||||
});
|
||||
|
||||
@@ -188,7 +188,7 @@ export class JSONQueryEngine implements QueryEngine {
|
||||
prompt: this.responseSynthesisPrompt({
|
||||
query,
|
||||
jsonSchema: schema,
|
||||
jsonPath: jsonPathResponseStr.text,
|
||||
jsonPath: jsonPathResponse,
|
||||
jsonPathValue: JSON.stringify(jsonPathOutput),
|
||||
}),
|
||||
});
|
||||
@@ -199,7 +199,7 @@ export class JSONQueryEngine implements QueryEngine {
|
||||
}
|
||||
|
||||
const responseMetadata = {
|
||||
jsonPathResponseStr,
|
||||
jsonPathResponse,
|
||||
};
|
||||
|
||||
const response = EngineResponse.fromResponse(responseStr, false);
|
||||
|
||||
@@ -1,5 +1,83 @@
|
||||
# llamaindex
|
||||
|
||||
## 0.5.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fcbf183: implement llamacloud file service
|
||||
|
||||
## 0.5.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8b66cf4: feat: support organization id in llamacloud index
|
||||
- Updated dependencies [e27e7dd]
|
||||
- @llamaindex/core@0.1.9
|
||||
|
||||
## 0.5.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- c654398: Implement Weaviate Vector Store in TS
|
||||
|
||||
## 0.5.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 58abc57: fix: align version
|
||||
- Updated dependencies [58abc57]
|
||||
- @llamaindex/cloud@0.2.2
|
||||
- @llamaindex/core@0.1.8
|
||||
- @llamaindex/env@0.1.9
|
||||
|
||||
## 0.5.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 01c184c: Add is_empty operator for filtering vector store
|
||||
- 07a275f: chore: bump openai
|
||||
|
||||
## 0.5.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- c825a2f: Add gpt-4o-mini to Azure. Add 2024-06-01 API version for Azure
|
||||
|
||||
## 0.5.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [04b2f8e]
|
||||
- @llamaindex/core@0.1.7
|
||||
|
||||
## 0.5.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 345300f: feat: add splitByPage mode to LlamaParseReader
|
||||
- da5cfc4: Add metadatafilter options to retriever constructors
|
||||
- da5cfc4: Fix system prompt not used in ContextChatEngine
|
||||
- Updated dependencies [0452af9]
|
||||
- @llamaindex/core@0.1.6
|
||||
|
||||
## 0.5.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [1f680d7]
|
||||
- @llamaindex/cloud@0.2.1
|
||||
|
||||
## 0.5.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 086b940: feat: add DeepSeek LLM
|
||||
- 5d5716b: feat: add a reader for JSON data
|
||||
- 91d02a4: feat: support transform component callable
|
||||
- fb6db45: feat: add pageSeparator params to LlamaParseReader
|
||||
- Updated dependencies [91d02a4]
|
||||
- @llamaindex/core@0.1.5
|
||||
|
||||
## 0.5.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,5 +1,79 @@
|
||||
# @llamaindex/cloudflare-worker-agent-test
|
||||
|
||||
## 0.0.53
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [fcbf183]
|
||||
- llamaindex@0.5.19
|
||||
|
||||
## 0.0.52
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8b66cf4]
|
||||
- llamaindex@0.5.18
|
||||
|
||||
## 0.0.51
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c654398]
|
||||
- llamaindex@0.5.17
|
||||
|
||||
## 0.0.50
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [58abc57]
|
||||
- llamaindex@0.5.16
|
||||
|
||||
## 0.0.49
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [01c184c]
|
||||
- Updated dependencies [07a275f]
|
||||
- llamaindex@0.5.15
|
||||
|
||||
## 0.0.48
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c825a2f]
|
||||
- llamaindex@0.5.14
|
||||
|
||||
## 0.0.47
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.13
|
||||
|
||||
## 0.0.46
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [345300f]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- llamaindex@0.5.12
|
||||
|
||||
## 0.0.45
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.0.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [086b940]
|
||||
- Updated dependencies [5d5716b]
|
||||
- Updated dependencies [91d02a4]
|
||||
- Updated dependencies [fb6db45]
|
||||
- llamaindex@0.5.10
|
||||
|
||||
## 0.0.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/cloudflare-worker-agent-test",
|
||||
"version": "0.0.43",
|
||||
"version": "0.0.53",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,79 @@
|
||||
# @llamaindex/next-agent-test
|
||||
|
||||
## 0.1.53
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [fcbf183]
|
||||
- llamaindex@0.5.19
|
||||
|
||||
## 0.1.52
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8b66cf4]
|
||||
- llamaindex@0.5.18
|
||||
|
||||
## 0.1.51
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c654398]
|
||||
- llamaindex@0.5.17
|
||||
|
||||
## 0.1.50
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [58abc57]
|
||||
- llamaindex@0.5.16
|
||||
|
||||
## 0.1.49
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [01c184c]
|
||||
- Updated dependencies [07a275f]
|
||||
- llamaindex@0.5.15
|
||||
|
||||
## 0.1.48
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c825a2f]
|
||||
- llamaindex@0.5.14
|
||||
|
||||
## 0.1.47
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.13
|
||||
|
||||
## 0.1.46
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [345300f]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- llamaindex@0.5.12
|
||||
|
||||
## 0.1.45
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.1.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [086b940]
|
||||
- Updated dependencies [5d5716b]
|
||||
- Updated dependencies [91d02a4]
|
||||
- Updated dependencies [fb6db45]
|
||||
- llamaindex@0.5.10
|
||||
|
||||
## 0.1.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/next-agent-test",
|
||||
"version": "0.1.43",
|
||||
"version": "0.1.53",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -1,5 +1,79 @@
|
||||
# test-edge-runtime
|
||||
|
||||
## 0.1.52
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [fcbf183]
|
||||
- llamaindex@0.5.19
|
||||
|
||||
## 0.1.51
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8b66cf4]
|
||||
- llamaindex@0.5.18
|
||||
|
||||
## 0.1.50
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c654398]
|
||||
- llamaindex@0.5.17
|
||||
|
||||
## 0.1.49
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [58abc57]
|
||||
- llamaindex@0.5.16
|
||||
|
||||
## 0.1.48
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [01c184c]
|
||||
- Updated dependencies [07a275f]
|
||||
- llamaindex@0.5.15
|
||||
|
||||
## 0.1.47
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c825a2f]
|
||||
- llamaindex@0.5.14
|
||||
|
||||
## 0.1.46
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.13
|
||||
|
||||
## 0.1.45
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [345300f]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- llamaindex@0.5.12
|
||||
|
||||
## 0.1.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.1.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [086b940]
|
||||
- Updated dependencies [5d5716b]
|
||||
- Updated dependencies [91d02a4]
|
||||
- Updated dependencies [fb6db45]
|
||||
- llamaindex@0.5.10
|
||||
|
||||
## 0.1.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/nextjs-edge-runtime-test",
|
||||
"version": "0.1.42",
|
||||
"version": "0.1.52",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -1,5 +1,79 @@
|
||||
# @llamaindex/next-node-runtime
|
||||
|
||||
## 0.0.34
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [fcbf183]
|
||||
- llamaindex@0.5.19
|
||||
|
||||
## 0.0.33
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8b66cf4]
|
||||
- llamaindex@0.5.18
|
||||
|
||||
## 0.0.32
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c654398]
|
||||
- llamaindex@0.5.17
|
||||
|
||||
## 0.0.31
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [58abc57]
|
||||
- llamaindex@0.5.16
|
||||
|
||||
## 0.0.30
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [01c184c]
|
||||
- Updated dependencies [07a275f]
|
||||
- llamaindex@0.5.15
|
||||
|
||||
## 0.0.29
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c825a2f]
|
||||
- llamaindex@0.5.14
|
||||
|
||||
## 0.0.28
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.13
|
||||
|
||||
## 0.0.27
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [345300f]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- llamaindex@0.5.12
|
||||
|
||||
## 0.0.26
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.0.25
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [086b940]
|
||||
- Updated dependencies [5d5716b]
|
||||
- Updated dependencies [91d02a4]
|
||||
- Updated dependencies [fb6db45]
|
||||
- llamaindex@0.5.10
|
||||
|
||||
## 0.0.24
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/next-node-runtime-test",
|
||||
"version": "0.0.24",
|
||||
"version": "0.0.34",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -1,5 +1,79 @@
|
||||
# @llamaindex/waku-query-engine-test
|
||||
|
||||
## 0.0.53
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [fcbf183]
|
||||
- llamaindex@0.5.19
|
||||
|
||||
## 0.0.52
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8b66cf4]
|
||||
- llamaindex@0.5.18
|
||||
|
||||
## 0.0.51
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c654398]
|
||||
- llamaindex@0.5.17
|
||||
|
||||
## 0.0.50
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [58abc57]
|
||||
- llamaindex@0.5.16
|
||||
|
||||
## 0.0.49
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [01c184c]
|
||||
- Updated dependencies [07a275f]
|
||||
- llamaindex@0.5.15
|
||||
|
||||
## 0.0.48
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c825a2f]
|
||||
- llamaindex@0.5.14
|
||||
|
||||
## 0.0.47
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.13
|
||||
|
||||
## 0.0.46
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [345300f]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- Updated dependencies [da5cfc4]
|
||||
- llamaindex@0.5.12
|
||||
|
||||
## 0.0.45
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.0.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [086b940]
|
||||
- Updated dependencies [5d5716b]
|
||||
- Updated dependencies [91d02a4]
|
||||
- Updated dependencies [fb6db45]
|
||||
- llamaindex@0.5.10
|
||||
|
||||
## 0.0.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/waku-query-engine-test",
|
||||
"version": "0.0.43",
|
||||
"version": "0.0.53",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1,15 +1,26 @@
|
||||
import { TransformComponent } from "@llamaindex/core/schema";
|
||||
import {
|
||||
BaseEmbedding,
|
||||
BaseNode,
|
||||
SimilarityType,
|
||||
type BaseEmbedding,
|
||||
type EmbeddingInfo,
|
||||
type MessageContentDetail,
|
||||
} from "llamaindex";
|
||||
|
||||
export class OpenAIEmbedding implements BaseEmbedding {
|
||||
export class OpenAIEmbedding
|
||||
extends TransformComponent
|
||||
implements BaseEmbedding
|
||||
{
|
||||
embedInfo?: EmbeddingInfo | undefined;
|
||||
embedBatchSize = 512;
|
||||
|
||||
constructor() {
|
||||
super(async (nodes: BaseNode[], _options?: any): Promise<BaseNode[]> => {
|
||||
nodes.forEach((node) => (node.embedding = [0]));
|
||||
return nodes;
|
||||
});
|
||||
}
|
||||
|
||||
async getQueryEmbedding(query: MessageContentDetail) {
|
||||
return [0];
|
||||
}
|
||||
@@ -34,11 +45,6 @@ export class OpenAIEmbedding implements BaseEmbedding {
|
||||
return 1;
|
||||
}
|
||||
|
||||
async transform(nodes: BaseNode[], _options?: any): Promise<BaseNode[]> {
|
||||
nodes.forEach((node) => (node.embedding = [0]));
|
||||
return nodes;
|
||||
}
|
||||
|
||||
truncateMaxTokens(input: string[]): string[] {
|
||||
return input;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "llamaindex",
|
||||
"version": "0.5.9",
|
||||
"version": "0.5.19",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"keywords": [
|
||||
@@ -55,7 +55,7 @@
|
||||
"md-utils-ts": "^2.0.0",
|
||||
"mongodb": "^6.7.0",
|
||||
"notion-md-crawler": "^1.0.0",
|
||||
"openai": "^4.52.5",
|
||||
"openai": "^4.55.3",
|
||||
"papaparse": "^5.4.1",
|
||||
"pathe": "^1.1.2",
|
||||
"pg": "^8.12.0",
|
||||
@@ -65,6 +65,7 @@
|
||||
"string-strip-html": "^13.4.8",
|
||||
"tiktoken": "^1.0.15",
|
||||
"unpdf": "^0.11.0",
|
||||
"weaviate-client": "^3.1.4",
|
||||
"wikipedia": "^2.1.2",
|
||||
"wink-nlp": "^2.3.0",
|
||||
"zod": "^3.23.8"
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import {
|
||||
FilesService,
|
||||
PipelinesService,
|
||||
ProjectsService,
|
||||
} from "@llamaindex/cloud/api";
|
||||
import { initService } from "./utils.js";
|
||||
|
||||
export class LLamaCloudFileService {
|
||||
/**
|
||||
* Get list of projects, each project contains a list of pipelines
|
||||
*/
|
||||
public static async getAllProjectsWithPipelines() {
|
||||
initService();
|
||||
try {
|
||||
const projects = await ProjectsService.listProjectsApiV1ProjectsGet();
|
||||
const pipelines =
|
||||
await PipelinesService.searchPipelinesApiV1PipelinesGet();
|
||||
return projects.map((project) => ({
|
||||
...project,
|
||||
pipelines: pipelines.filter((p) => p.project_id === project.id),
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error("Error listing projects and pipelines:", error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a file to a pipeline in LlamaCloud
|
||||
*/
|
||||
public static async addFileToPipeline(
|
||||
projectId: string,
|
||||
pipelineId: string,
|
||||
uploadFile: File | Blob,
|
||||
customMetadata: Record<string, any> = {},
|
||||
) {
|
||||
initService();
|
||||
const file = await FilesService.uploadFileApiV1FilesPost({
|
||||
projectId,
|
||||
formData: {
|
||||
upload_file: uploadFile,
|
||||
},
|
||||
});
|
||||
const files = [
|
||||
{
|
||||
file_id: file.id,
|
||||
custom_metadata: { file_id: file.id, ...customMetadata },
|
||||
},
|
||||
];
|
||||
await PipelinesService.addFilesToPipelineApiV1PipelinesPipelineIdFilesPut({
|
||||
pipelineId,
|
||||
requestBody: files,
|
||||
});
|
||||
|
||||
// Wait 2s for the file to be processed
|
||||
const maxAttempts = 20;
|
||||
let attempt = 0;
|
||||
while (attempt < maxAttempts) {
|
||||
const result =
|
||||
await PipelinesService.getPipelineFileStatusApiV1PipelinesPipelineIdFilesFileIdStatusGet(
|
||||
{
|
||||
pipelineId,
|
||||
fileId: file.id,
|
||||
},
|
||||
);
|
||||
if (result.status === "ERROR") {
|
||||
throw new Error(`File processing failed: ${JSON.stringify(result)}`);
|
||||
}
|
||||
if (result.status === "SUCCESS") {
|
||||
// File is ingested - return the file id
|
||||
return file.id;
|
||||
}
|
||||
attempt += 1;
|
||||
await new Promise((resolve) => setTimeout(resolve, 100)); // Sleep for 100ms
|
||||
}
|
||||
throw new Error(
|
||||
`File processing did not complete after ${maxAttempts} attempts.`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get download URL for a file in LlamaCloud
|
||||
*/
|
||||
public static async getFileUrl(pipelineId: string, filename: string) {
|
||||
initService();
|
||||
const allPipelineFiles =
|
||||
await PipelinesService.listPipelineFilesApiV1PipelinesPipelineIdFilesGet({
|
||||
pipelineId,
|
||||
});
|
||||
const file = allPipelineFiles.find((file) => file.name === filename);
|
||||
if (!file?.file_id) return null;
|
||||
const fileContent =
|
||||
await FilesService.readFileContentApiV1FilesIdContentGet({
|
||||
id: file.file_id,
|
||||
projectId: file.project_id,
|
||||
});
|
||||
return fileContent.url;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import type { CloudRetrieveParams } from "./LlamaCloudRetriever.js";
|
||||
import { LlamaCloudRetriever } from "./LlamaCloudRetriever.js";
|
||||
import { getPipelineCreate } from "./config.js";
|
||||
import type { CloudConstructorParams } from "./constants.js";
|
||||
import { getAppBaseUrl, initService } from "./utils.js";
|
||||
import { getAppBaseUrl, getProjectId, initService } from "./utils.js";
|
||||
|
||||
import { PipelinesService, ProjectsService } from "@llamaindex/cloud/api";
|
||||
import { SentenceSplitter } from "@llamaindex/core/node-parser";
|
||||
@@ -132,18 +132,28 @@ export class LlamaCloudIndex {
|
||||
await this.waitForPipelineIngestion(verbose, raiseOnError);
|
||||
}
|
||||
|
||||
private async getPipelineId(
|
||||
name: string,
|
||||
projectName: string,
|
||||
public async getPipelineId(
|
||||
name?: string,
|
||||
projectName?: string,
|
||||
): Promise<string> {
|
||||
const pipelines = await PipelinesService.searchPipelinesApiV1PipelinesGet({
|
||||
projectName,
|
||||
pipelineName: name,
|
||||
projectId: await this.getProjectId(projectName),
|
||||
pipelineName: name ?? this.params.name,
|
||||
});
|
||||
|
||||
return pipelines[0].id;
|
||||
}
|
||||
|
||||
public async getProjectId(
|
||||
projectName?: string,
|
||||
organizationId?: string,
|
||||
): Promise<string> {
|
||||
return await getProjectId(
|
||||
projectName ?? this.params.projectName,
|
||||
organizationId ?? this.params.organizationId,
|
||||
);
|
||||
}
|
||||
|
||||
static async fromDocuments(
|
||||
params: {
|
||||
documents: Document[];
|
||||
@@ -168,6 +178,7 @@ export class LlamaCloudIndex {
|
||||
});
|
||||
|
||||
const project = await ProjectsService.upsertProjectApiV1ProjectsPut({
|
||||
organizationId: params.organizationId,
|
||||
requestBody: {
|
||||
name: params.projectName ?? "default",
|
||||
},
|
||||
|
||||
@@ -11,16 +11,17 @@ import { extractText, wrapEventCaller } from "@llamaindex/core/utils";
|
||||
import type { BaseRetriever, RetrieveParams } from "../Retriever.js";
|
||||
import type { ClientParams, CloudConstructorParams } from "./constants.js";
|
||||
import { DEFAULT_PROJECT_NAME } from "./constants.js";
|
||||
import { initService } from "./utils.js";
|
||||
import { getProjectId, initService } from "./utils.js";
|
||||
|
||||
export type CloudRetrieveParams = Omit<
|
||||
RetrievalParams,
|
||||
"query" | "searchFilters" | "className" | "denseSimilarityTopK"
|
||||
> & { similarityTopK?: number };
|
||||
"query" | "search_filters" | "dense_similarity_top_k"
|
||||
> & { similarityTopK?: number; filters?: MetadataFilters };
|
||||
|
||||
export class LlamaCloudRetriever implements BaseRetriever {
|
||||
clientParams: ClientParams;
|
||||
retrieveParams: CloudRetrieveParams;
|
||||
organizationId?: string;
|
||||
projectName: string = DEFAULT_PROJECT_NAME;
|
||||
pipelineName: string;
|
||||
|
||||
@@ -49,6 +50,9 @@ export class LlamaCloudRetriever implements BaseRetriever {
|
||||
if (params.projectName) {
|
||||
this.projectName = params.projectName;
|
||||
}
|
||||
if (params.organizationId) {
|
||||
this.organizationId = params.organizationId;
|
||||
}
|
||||
}
|
||||
|
||||
@wrapEventCaller
|
||||
@@ -57,7 +61,7 @@ export class LlamaCloudRetriever implements BaseRetriever {
|
||||
preFilters,
|
||||
}: RetrieveParams): Promise<NodeWithScore[]> {
|
||||
const pipelines = await PipelinesService.searchPipelinesApiV1PipelinesGet({
|
||||
projectName: this.projectName,
|
||||
projectId: await getProjectId(this.projectName, this.organizationId),
|
||||
pipelineName: this.pipelineName,
|
||||
});
|
||||
|
||||
@@ -84,7 +88,9 @@ export class LlamaCloudRetriever implements BaseRetriever {
|
||||
requestBody: {
|
||||
...this.retrieveParams,
|
||||
query: extractText(query),
|
||||
search_filters: preFilters as MetadataFilters,
|
||||
search_filters:
|
||||
this.retrieveParams.filters ?? (preFilters as MetadataFilters),
|
||||
dense_similarity_top_k: this.retrieveParams.similarityTopK,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -8,5 +8,6 @@ export type ClientParams = { apiKey?: string; baseUrl?: string };
|
||||
export type CloudConstructorParams = {
|
||||
name: string;
|
||||
projectName: string;
|
||||
organizationId?: string;
|
||||
serviceContext?: ServiceContext;
|
||||
} & ClientParams;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export type { CloudConstructorParams } from "./constants.js";
|
||||
export { LLamaCloudFileService } from "./LLamaCloudFileService.js";
|
||||
export { LlamaCloudIndex } from "./LlamaCloudIndex.js";
|
||||
export {
|
||||
LlamaCloudRetriever,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { OpenAPI } from "@llamaindex/cloud/api";
|
||||
import { OpenAPI, ProjectsService } from "@llamaindex/cloud/api";
|
||||
import { getEnv } from "@llamaindex/env";
|
||||
import type { ClientParams } from "./constants.js";
|
||||
import { DEFAULT_BASE_URL } from "./constants.js";
|
||||
@@ -20,3 +20,31 @@ export function initService({ apiKey, baseUrl }: ClientParams = {}) {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function getProjectId(
|
||||
projectName: string,
|
||||
organizationId?: string,
|
||||
): Promise<string> {
|
||||
const projects = await ProjectsService.listProjectsApiV1ProjectsGet({
|
||||
projectName: projectName,
|
||||
organizationId: organizationId,
|
||||
});
|
||||
|
||||
if (projects.length === 0) {
|
||||
throw new Error(
|
||||
`Unknown project name ${projectName}. Please confirm a managed project with this name exists.`,
|
||||
);
|
||||
} else if (projects.length > 1) {
|
||||
throw new Error(
|
||||
`Multiple projects found with name ${projectName}. Please specify organization_id.`,
|
||||
);
|
||||
}
|
||||
|
||||
const project = projects[0];
|
||||
|
||||
if (!project.id) {
|
||||
throw new Error(`No project found with name ${projectName}`);
|
||||
}
|
||||
|
||||
return project.id;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ export class JinaAIEmbedding extends MultiModalEmbedding {
|
||||
private async getImageInput(
|
||||
image: ImageType,
|
||||
): Promise<{ bytes: string } | { url: string }> {
|
||||
if (isLocal(image)) {
|
||||
if (isLocal(image) || image instanceof Blob) {
|
||||
const base64 = await imageToDataUrl(image);
|
||||
const bytes = base64.split(",")[1];
|
||||
return { bytes };
|
||||
|
||||
@@ -126,7 +126,7 @@ export class ContextChatEngine extends PromptMixin implements ChatEngine {
|
||||
if (!this.systemPrompt) return message;
|
||||
return {
|
||||
...message,
|
||||
content: this.systemPrompt.trim() + "\n" + message.content,
|
||||
content: this.systemPrompt.trim() + "\n" + extractText(message.content),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ export class RouterQueryEngine extends PromptMixin implements QueryEngine {
|
||||
const responses: EngineResponse[] = [];
|
||||
for (let i = 0; i < result.selections.length; i++) {
|
||||
const engineInd = result.selections[i];
|
||||
const logStr = `Selecting query engine ${engineInd}: ${result.selections[i]}.`;
|
||||
const logStr = `Selecting query engine ${engineInd.index}: ${result.selections[i].index}.`;
|
||||
|
||||
if (this.verbose) {
|
||||
console.log(logStr + "\n");
|
||||
|
||||
@@ -119,15 +119,15 @@ export class SubQuestionQueryEngine
|
||||
return null;
|
||||
}
|
||||
|
||||
const responseText = await queryEngine?.call?.({
|
||||
const responseValue = await queryEngine?.call?.({
|
||||
query: question,
|
||||
});
|
||||
|
||||
if (!responseText) {
|
||||
if (responseValue == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const nodeText = `Sub question: ${question}\nResponse: ${responseText}`;
|
||||
const nodeText = `Sub question: ${question}\nResponse: ${typeof responseValue === "string" ? responseValue : JSON.stringify(responseValue)}`;
|
||||
const node = new TextNode({ text: nodeText });
|
||||
return { node, score: 0 };
|
||||
} catch (error) {
|
||||
|
||||
@@ -78,7 +78,7 @@ export class RelevancyEvaluator extends PromptMixin implements BaseEvaluator {
|
||||
serviceContext: this.serviceContext,
|
||||
});
|
||||
|
||||
const queryResponse = `Question: ${query}\nResponse: ${response}`;
|
||||
const queryResponse = `Question: ${extractText(query)}\nResponse: ${response}`;
|
||||
|
||||
const queryEngine = index.asQueryEngine();
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import type { BaseNode, TransformComponent } from "@llamaindex/core/schema";
|
||||
import { MetadataMode, TextNode } from "@llamaindex/core/schema";
|
||||
import {
|
||||
BaseNode,
|
||||
MetadataMode,
|
||||
TextNode,
|
||||
TransformComponent,
|
||||
} from "@llamaindex/core/schema";
|
||||
import { defaultNodeTextTemplate } from "./prompts.js";
|
||||
|
||||
/*
|
||||
* Abstract class for all extractors.
|
||||
*/
|
||||
export abstract class BaseExtractor implements TransformComponent {
|
||||
export abstract class BaseExtractor extends TransformComponent {
|
||||
isTextNodeOnly: boolean = true;
|
||||
showProgress: boolean = true;
|
||||
metadataMode: MetadataMode = MetadataMode.ALL;
|
||||
@@ -13,16 +17,18 @@ export abstract class BaseExtractor implements TransformComponent {
|
||||
inPlace: boolean = true;
|
||||
numWorkers: number = 4;
|
||||
|
||||
abstract extract(nodes: BaseNode[]): Promise<Record<string, any>[]>;
|
||||
|
||||
async transform(nodes: BaseNode[], options?: any): Promise<BaseNode[]> {
|
||||
return this.processNodes(
|
||||
nodes,
|
||||
options?.excludedEmbedMetadataKeys,
|
||||
options?.excludedLlmMetadataKeys,
|
||||
);
|
||||
constructor() {
|
||||
super(async (nodes: BaseNode[], options?: any): Promise<BaseNode[]> => {
|
||||
return this.processNodes(
|
||||
nodes,
|
||||
options?.excludedEmbedMetadataKeys,
|
||||
options?.excludedLlmMetadataKeys,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
abstract extract(nodes: BaseNode[]): Promise<Record<string, any>[]>;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param nodes Nodes to extract metadata from.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { AgentEndEvent, AgentStartEvent } from "./agent/types.js";
|
||||
import type { RetrievalEndEvent, RetrievalStartEvent } from "./llm/types.js";
|
||||
|
||||
export * from "@llamaindex/core/schema";
|
||||
|
||||
declare module "@llamaindex/core/global" {
|
||||
export interface LlamaIndexEventMaps {
|
||||
"retrieve-start": RetrievalStartEvent;
|
||||
|
||||
@@ -172,7 +172,7 @@ export class VectorStoreIndex extends BaseIndex<IndexDict> {
|
||||
const embedModel =
|
||||
this.embedModel ?? this.vectorStores[type as ModalityType]?.embedModel;
|
||||
if (embedModel && nodes) {
|
||||
await embedModel.transform(nodes, {
|
||||
await embedModel(nodes, {
|
||||
logProgress: options?.logProgress,
|
||||
});
|
||||
}
|
||||
@@ -386,6 +386,7 @@ export type VectorIndexRetrieverOptions = {
|
||||
index: VectorStoreIndex;
|
||||
similarityTopK?: number;
|
||||
topK?: TopKMap;
|
||||
filters?: MetadataFilters;
|
||||
};
|
||||
|
||||
export class VectorIndexRetriever implements BaseRetriever {
|
||||
@@ -393,14 +394,21 @@ export class VectorIndexRetriever implements BaseRetriever {
|
||||
topK: TopKMap;
|
||||
|
||||
serviceContext?: ServiceContext;
|
||||
filters?: MetadataFilters;
|
||||
|
||||
constructor({ index, similarityTopK, topK }: VectorIndexRetrieverOptions) {
|
||||
constructor({
|
||||
index,
|
||||
similarityTopK,
|
||||
topK,
|
||||
filters,
|
||||
}: VectorIndexRetrieverOptions) {
|
||||
this.index = index;
|
||||
this.serviceContext = this.index.serviceContext;
|
||||
this.topK = topK ?? {
|
||||
[ModalityType.TEXT]: similarityTopK ?? DEFAULT_SIMILARITY_TOP_K,
|
||||
[ModalityType.IMAGE]: DEFAULT_SIMILARITY_TOP_K,
|
||||
};
|
||||
this.filters = filters;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -443,7 +451,7 @@ export class VectorIndexRetriever implements BaseRetriever {
|
||||
query: MessageContent,
|
||||
type: ModalityType,
|
||||
vectorStore: VectorStore,
|
||||
preFilters?: MetadataFilters,
|
||||
filters?: MetadataFilters,
|
||||
): Promise<NodeWithScore[]> {
|
||||
// convert string message to multi-modal format
|
||||
if (typeof query === "string") {
|
||||
@@ -460,7 +468,7 @@ export class VectorIndexRetriever implements BaseRetriever {
|
||||
queryEmbedding,
|
||||
mode: VectorStoreQueryMode.DEFAULT,
|
||||
similarityTopK: this.topK[type],
|
||||
filters: preFilters ?? undefined,
|
||||
filters: this.filters ?? filters ?? undefined,
|
||||
});
|
||||
nodes = nodes.concat(this.buildNodeListFromQueryResult(result));
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export function getTransformationHash(
|
||||
const transformString: string = transformToJSON(transform);
|
||||
|
||||
const hash = createSHA256();
|
||||
hash.update(nodesStr + transformString);
|
||||
hash.update(nodesStr + transformString + transform.id);
|
||||
return hash.digest();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { TransformComponent } from "@llamaindex/core/schema";
|
||||
import type { BaseReader, TransformComponent } from "@llamaindex/core/schema";
|
||||
import {
|
||||
ModalityType,
|
||||
splitNodesByType,
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
type Document,
|
||||
type Metadata,
|
||||
} from "@llamaindex/core/schema";
|
||||
import type { BaseReader } from "../readers/type.js";
|
||||
import type { BaseDocumentStore } from "../storage/docStore/types.js";
|
||||
import type {
|
||||
VectorStore,
|
||||
@@ -40,7 +39,7 @@ export async function runTransformations(
|
||||
nodes = [...nodesToRun];
|
||||
}
|
||||
if (docStoreStrategy) {
|
||||
nodes = await docStoreStrategy.transform(nodes);
|
||||
nodes = await docStoreStrategy(nodes);
|
||||
}
|
||||
for (const transform of transformations) {
|
||||
if (cache) {
|
||||
@@ -49,11 +48,11 @@ export async function runTransformations(
|
||||
if (cachedNodes) {
|
||||
nodes = cachedNodes;
|
||||
} else {
|
||||
nodes = await transform.transform(nodes, transformOptions);
|
||||
nodes = await transform(nodes, transformOptions);
|
||||
await cache.put(hash, nodes);
|
||||
}
|
||||
} else {
|
||||
nodes = await transform.transform(nodes, transformOptions);
|
||||
nodes = await transform(nodes, transformOptions);
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
@@ -107,6 +106,7 @@ export class IngestionPipeline {
|
||||
inputNodes.push(this.documents);
|
||||
}
|
||||
if (this.reader) {
|
||||
// fixme: empty parameter might cause error
|
||||
inputNodes.push(await this.reader.loadData());
|
||||
}
|
||||
return inputNodes.flat();
|
||||
|
||||
@@ -1,31 +1,30 @@
|
||||
import type { BaseNode, TransformComponent } from "@llamaindex/core/schema";
|
||||
import { BaseNode, TransformComponent } from "@llamaindex/core/schema";
|
||||
import type { BaseDocumentStore } from "../../storage/docStore/types.js";
|
||||
|
||||
/**
|
||||
* Handle doc store duplicates by checking all hashes.
|
||||
*/
|
||||
export class DuplicatesStrategy implements TransformComponent {
|
||||
export class DuplicatesStrategy extends TransformComponent {
|
||||
private docStore: BaseDocumentStore;
|
||||
|
||||
constructor(docStore: BaseDocumentStore) {
|
||||
super(async (nodes: BaseNode[]): Promise<BaseNode[]> => {
|
||||
const hashes = await this.docStore.getAllDocumentHashes();
|
||||
const currentHashes = new Set<string>();
|
||||
const nodesToRun: BaseNode[] = [];
|
||||
|
||||
for (const node of nodes) {
|
||||
if (!(node.hash in hashes) && !currentHashes.has(node.hash)) {
|
||||
await this.docStore.setDocumentHash(node.id_, node.hash);
|
||||
nodesToRun.push(node);
|
||||
currentHashes.add(node.hash);
|
||||
}
|
||||
}
|
||||
|
||||
await this.docStore.addDocuments(nodesToRun, true);
|
||||
|
||||
return nodesToRun;
|
||||
});
|
||||
this.docStore = docStore;
|
||||
}
|
||||
|
||||
async transform(nodes: BaseNode[]): Promise<BaseNode[]> {
|
||||
const hashes = await this.docStore.getAllDocumentHashes();
|
||||
const currentHashes = new Set<string>();
|
||||
const nodesToRun: BaseNode[] = [];
|
||||
|
||||
for (const node of nodes) {
|
||||
if (!(node.hash in hashes) && !currentHashes.has(node.hash)) {
|
||||
await this.docStore.setDocumentHash(node.id_, node.hash);
|
||||
nodesToRun.push(node);
|
||||
currentHashes.add(node.hash);
|
||||
}
|
||||
}
|
||||
|
||||
await this.docStore.addDocuments(nodesToRun, true);
|
||||
|
||||
return nodesToRun;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { BaseNode, TransformComponent } from "@llamaindex/core/schema";
|
||||
import { BaseNode, TransformComponent } from "@llamaindex/core/schema";
|
||||
import type { BaseDocumentStore } from "../../storage/docStore/types.js";
|
||||
import type { VectorStore } from "../../storage/vectorStore/types.js";
|
||||
import { classify } from "./classify.js";
|
||||
@@ -7,43 +7,42 @@ import { classify } from "./classify.js";
|
||||
* Handle docstore upserts by checking hashes and ids.
|
||||
* Identify missing docs and delete them from docstore and vector store
|
||||
*/
|
||||
export class UpsertsAndDeleteStrategy implements TransformComponent {
|
||||
export class UpsertsAndDeleteStrategy extends TransformComponent {
|
||||
protected docStore: BaseDocumentStore;
|
||||
protected vectorStores?: VectorStore[];
|
||||
|
||||
constructor(docStore: BaseDocumentStore, vectorStores?: VectorStore[]) {
|
||||
super(async (nodes: BaseNode[]): Promise<BaseNode[]> => {
|
||||
const { dedupedNodes, missingDocs, unusedDocs } = await classify(
|
||||
this.docStore,
|
||||
nodes,
|
||||
);
|
||||
|
||||
// remove unused docs
|
||||
for (const refDocId of unusedDocs) {
|
||||
await this.docStore.deleteRefDoc(refDocId, false);
|
||||
if (this.vectorStores) {
|
||||
for (const vectorStore of this.vectorStores) {
|
||||
await vectorStore.delete(refDocId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove missing docs
|
||||
for (const docId of missingDocs) {
|
||||
await this.docStore.deleteDocument(docId, true);
|
||||
if (this.vectorStores) {
|
||||
for (const vectorStore of this.vectorStores) {
|
||||
await vectorStore.delete(docId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await this.docStore.addDocuments(dedupedNodes, true);
|
||||
|
||||
return dedupedNodes;
|
||||
});
|
||||
this.docStore = docStore;
|
||||
this.vectorStores = vectorStores;
|
||||
}
|
||||
|
||||
async transform(nodes: BaseNode[]): Promise<BaseNode[]> {
|
||||
const { dedupedNodes, missingDocs, unusedDocs } = await classify(
|
||||
this.docStore,
|
||||
nodes,
|
||||
);
|
||||
|
||||
// remove unused docs
|
||||
for (const refDocId of unusedDocs) {
|
||||
await this.docStore.deleteRefDoc(refDocId, false);
|
||||
if (this.vectorStores) {
|
||||
for (const vectorStore of this.vectorStores) {
|
||||
await vectorStore.delete(refDocId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove missing docs
|
||||
for (const docId of missingDocs) {
|
||||
await this.docStore.deleteDocument(docId, true);
|
||||
if (this.vectorStores) {
|
||||
for (const vectorStore of this.vectorStores) {
|
||||
await vectorStore.delete(docId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await this.docStore.addDocuments(dedupedNodes, true);
|
||||
|
||||
return dedupedNodes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { BaseNode, TransformComponent } from "@llamaindex/core/schema";
|
||||
import { BaseNode, TransformComponent } from "@llamaindex/core/schema";
|
||||
import type { BaseDocumentStore } from "../../storage/docStore/types.js";
|
||||
import type { VectorStore } from "../../storage/vectorStore/types.js";
|
||||
import { classify } from "./classify.js";
|
||||
@@ -6,28 +6,27 @@ import { classify } from "./classify.js";
|
||||
/**
|
||||
* Handles doc store upserts by checking hashes and ids.
|
||||
*/
|
||||
export class UpsertsStrategy implements TransformComponent {
|
||||
export class UpsertsStrategy extends TransformComponent {
|
||||
protected docStore: BaseDocumentStore;
|
||||
protected vectorStores?: VectorStore[];
|
||||
|
||||
constructor(docStore: BaseDocumentStore, vectorStores?: VectorStore[]) {
|
||||
super(async (nodes: BaseNode[]): Promise<BaseNode[]> => {
|
||||
const { dedupedNodes, unusedDocs } = await classify(this.docStore, nodes);
|
||||
// remove unused docs
|
||||
for (const refDocId of unusedDocs) {
|
||||
await this.docStore.deleteRefDoc(refDocId, false);
|
||||
if (this.vectorStores) {
|
||||
for (const vectorStore of this.vectorStores) {
|
||||
await vectorStore.delete(refDocId);
|
||||
}
|
||||
}
|
||||
}
|
||||
// add non-duplicate docs
|
||||
await this.docStore.addDocuments(dedupedNodes, true);
|
||||
return dedupedNodes;
|
||||
});
|
||||
this.docStore = docStore;
|
||||
this.vectorStores = vectorStores;
|
||||
}
|
||||
|
||||
async transform(nodes: BaseNode[]): Promise<BaseNode[]> {
|
||||
const { dedupedNodes, unusedDocs } = await classify(this.docStore, nodes);
|
||||
// remove unused docs
|
||||
for (const refDocId of unusedDocs) {
|
||||
await this.docStore.deleteRefDoc(refDocId, false);
|
||||
if (this.vectorStores) {
|
||||
for (const vectorStore of this.vectorStores) {
|
||||
await vectorStore.delete(refDocId);
|
||||
}
|
||||
}
|
||||
}
|
||||
// add non-duplicate docs
|
||||
await this.docStore.addDocuments(dedupedNodes, true);
|
||||
return dedupedNodes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { TransformComponent } from "@llamaindex/core/schema";
|
||||
import { TransformComponent } from "@llamaindex/core/schema";
|
||||
import type { BaseDocumentStore } from "../../storage/docStore/types.js";
|
||||
import type { VectorStore } from "../../storage/vectorStore/types.js";
|
||||
import { DuplicatesStrategy } from "./DuplicatesStrategy.js";
|
||||
@@ -19,9 +19,9 @@ export enum DocStoreStrategy {
|
||||
NONE = "none", // no-op strategy
|
||||
}
|
||||
|
||||
class NoOpStrategy implements TransformComponent {
|
||||
async transform(nodes: any[]): Promise<any[]> {
|
||||
return nodes;
|
||||
class NoOpStrategy extends TransformComponent {
|
||||
constructor() {
|
||||
super(async (nodes) => nodes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ const ALL_AZURE_OPENAI_CHAT_MODELS = {
|
||||
openAIModel: "gpt-3.5-turbo-16k",
|
||||
},
|
||||
"gpt-4o": { contextWindow: 128000, openAIModel: "gpt-4o" },
|
||||
"gpt-4o-mini": { contextWindow: 128000, openAIModel: "gpt-4o-mini" },
|
||||
"gpt-4": { contextWindow: 8192, openAIModel: "gpt-4" },
|
||||
"gpt-4-32k": { contextWindow: 32768, openAIModel: "gpt-4-32k" },
|
||||
"gpt-4-turbo": {
|
||||
@@ -40,6 +41,10 @@ const ALL_AZURE_OPENAI_CHAT_MODELS = {
|
||||
contextWindow: 128000,
|
||||
openAIModel: "gpt-4o-2024-05-13",
|
||||
},
|
||||
"gpt-4o-mini-2024-07-18": {
|
||||
contextWindow: 128000,
|
||||
openAIModel: "gpt-4o-mini-2024-07-18",
|
||||
},
|
||||
};
|
||||
|
||||
const ALL_AZURE_OPENAI_EMBEDDING_MODELS = {
|
||||
@@ -73,6 +78,7 @@ const ALL_AZURE_API_VERSIONS = [
|
||||
"2024-03-01-preview",
|
||||
"2024-04-01-preview",
|
||||
"2024-05-01-preview",
|
||||
"2024-06-01",
|
||||
];
|
||||
|
||||
const DEFAULT_API_VERSION = "2023-05-15";
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { getEnv } from "@llamaindex/env";
|
||||
import { OpenAI } from "./openai.js";
|
||||
|
||||
export const DEEPSEEK_MODELS = {
|
||||
"deepseek-coder": { contextWindow: 128000 },
|
||||
"deepseek-chat": { contextWindow: 128000 },
|
||||
};
|
||||
|
||||
type DeepSeekModelName = keyof typeof DEEPSEEK_MODELS;
|
||||
const DEFAULT_MODEL: DeepSeekModelName = "deepseek-coder";
|
||||
|
||||
export class DeepSeekLLM extends OpenAI {
|
||||
constructor(init?: Partial<OpenAI> & { model?: DeepSeekModelName }) {
|
||||
const {
|
||||
apiKey = getEnv("DEEPSEEK_API_KEY"),
|
||||
additionalSessionOptions = {},
|
||||
model = DEFAULT_MODEL,
|
||||
...rest
|
||||
} = init ?? {};
|
||||
|
||||
if (!apiKey) {
|
||||
throw new Error("Set DeepSeek Key in DEEPSEEK_API_KEY env variable");
|
||||
}
|
||||
|
||||
additionalSessionOptions.baseURL =
|
||||
additionalSessionOptions.baseURL ?? "https://api.deepseek.com/v1";
|
||||
|
||||
super({
|
||||
apiKey,
|
||||
additionalSessionOptions,
|
||||
model,
|
||||
...rest,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -34,5 +34,6 @@ export {
|
||||
ReplicateSession,
|
||||
} from "./replicate_ai.js";
|
||||
|
||||
export { DeepSeekLLM } from "./deepseek.js";
|
||||
export { TogetherLLM } from "./together.js";
|
||||
export * from "./types.js";
|
||||
|
||||
@@ -6,6 +6,7 @@ import type {
|
||||
ClientOptions as OpenAIClientOptions,
|
||||
} from "openai";
|
||||
import { AzureOpenAI, OpenAI as OrigOpenAI } from "openai";
|
||||
import type { ChatModel } from "openai/resources/chat/chat";
|
||||
|
||||
import {
|
||||
type BaseTool,
|
||||
@@ -108,16 +109,24 @@ export const GPT4_MODELS = {
|
||||
"gpt-4o-2024-05-13": { contextWindow: 128000 },
|
||||
"gpt-4o-mini": { contextWindow: 128000 },
|
||||
"gpt-4o-mini-2024-07-18": { contextWindow: 128000 },
|
||||
"gpt-4o-2024-08-06": { contextWindow: 128000 },
|
||||
"gpt-4o-2024-09-14": { contextWindow: 128000 },
|
||||
"gpt-4o-2024-10-14": { contextWindow: 128000 },
|
||||
"gpt-4-0613": { contextWindow: 128000 },
|
||||
"gpt-4-turbo-2024-04-09": { contextWindow: 128000 },
|
||||
"gpt-4-0314": { contextWindow: 128000 },
|
||||
"gpt-4-32k-0314": { contextWindow: 32768 },
|
||||
};
|
||||
|
||||
// NOTE we don't currently support gpt-3.5-turbo-instruct and don't plan to in the near future
|
||||
export const GPT35_MODELS = {
|
||||
"gpt-3.5-turbo": { contextWindow: 4096 },
|
||||
"gpt-3.5-turbo": { contextWindow: 16385 },
|
||||
"gpt-3.5-turbo-0613": { contextWindow: 4096 },
|
||||
"gpt-3.5-turbo-16k": { contextWindow: 16384 },
|
||||
"gpt-3.5-turbo-16k-0613": { contextWindow: 16384 },
|
||||
"gpt-3.5-turbo-1106": { contextWindow: 16384 },
|
||||
"gpt-3.5-turbo-0125": { contextWindow: 16384 },
|
||||
"gpt-3.5-turbo-16k": { contextWindow: 16385 },
|
||||
"gpt-3.5-turbo-16k-0613": { contextWindow: 16385 },
|
||||
"gpt-3.5-turbo-1106": { contextWindow: 16385 },
|
||||
"gpt-3.5-turbo-0125": { contextWindow: 16385 },
|
||||
"gpt-3.5-turbo-0301": { contextWindow: 16385 },
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -126,7 +135,7 @@ export const GPT35_MODELS = {
|
||||
export const ALL_AVAILABLE_OPENAI_MODELS = {
|
||||
...GPT4_MODELS,
|
||||
...GPT35_MODELS,
|
||||
};
|
||||
} satisfies Record<ChatModel, { contextWindow: number }>;
|
||||
|
||||
export function isFunctionCallingModel(llm: LLM): llm is OpenAI {
|
||||
let model: string;
|
||||
@@ -157,8 +166,10 @@ export type OpenAIAdditionalChatOptions = Omit<
|
||||
>;
|
||||
|
||||
export class OpenAI extends ToolCallLLM<OpenAIAdditionalChatOptions> {
|
||||
// Per completion OpenAI params
|
||||
model: keyof typeof ALL_AVAILABLE_OPENAI_MODELS | string;
|
||||
model:
|
||||
| ChatModel
|
||||
// string & {} is a hack to allow any string, but still give autocomplete
|
||||
| (string & {});
|
||||
temperature: number;
|
||||
topP: number;
|
||||
maxTokens?: number;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Document } from "@llamaindex/core/schema";
|
||||
import { type BaseReader, Document } from "@llamaindex/core/schema";
|
||||
import { getEnv } from "@llamaindex/env";
|
||||
import type {
|
||||
BaseServiceParams,
|
||||
@@ -8,7 +8,6 @@ import type {
|
||||
TranscriptSentence,
|
||||
} from "assemblyai";
|
||||
import { AssemblyAI } from "assemblyai";
|
||||
import type { BaseReader } from "./type.js";
|
||||
|
||||
type AssemblyAIOptions = Partial<BaseServiceParams>;
|
||||
const defaultOptions = {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Document } from "@llamaindex/core/schema";
|
||||
import { type BaseReader, Document, FileReader } from "@llamaindex/core/schema";
|
||||
import type { ParseConfig } from "papaparse";
|
||||
import Papa from "papaparse";
|
||||
import { FileReader } from "./type.js";
|
||||
|
||||
/**
|
||||
* papaparse-based csv parser
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { REST, type RESTOptions } from "@discordjs/rest";
|
||||
import { Document } from "@llamaindex/core/schema";
|
||||
import { Document, type BaseReader } from "@llamaindex/core/schema";
|
||||
import { getEnv } from "@llamaindex/env";
|
||||
import { Routes, type APIEmbed, type APIMessage } from "discord-api-types/v10";
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Routes, type APIEmbed, type APIMessage } from "discord-api-types/v10";
|
||||
* Represents a reader for Discord messages using @discordjs/rest
|
||||
* See https://github.com/discordjs/discord.js/tree/main/packages/rest
|
||||
*/
|
||||
export class DiscordReader {
|
||||
export class DiscordReader implements BaseReader {
|
||||
private client: REST;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Document } from "@llamaindex/core/schema";
|
||||
import { Document, FileReader } from "@llamaindex/core/schema";
|
||||
import mammoth from "mammoth";
|
||||
import { FileReader } from "./type.js";
|
||||
|
||||
export class DocxReader extends FileReader {
|
||||
/** DocxParser */
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { Document } from "@llamaindex/core/schema";
|
||||
import { FileReader } from "./type.js";
|
||||
|
||||
import { Document, FileReader } from "@llamaindex/core/schema";
|
||||
/**
|
||||
* Extract the significant text from an arbitrary HTML document.
|
||||
* The contents of any head, script, style, and xml tags are removed completely.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { Document } from "@llamaindex/core/schema";
|
||||
import { ImageDocument } from "@llamaindex/core/schema";
|
||||
import { FileReader } from "./type.js";
|
||||
import { FileReader, ImageDocument } from "@llamaindex/core/schema";
|
||||
|
||||
/**
|
||||
* Reads the content of an image file into a Document object (which stores the image file as a Blob).
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user