Compare commits

...

33 Commits

Author SHA1 Message Date
github-actions[bot] c517f35526 Release 0.3.11 (#835)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-16 16:35:57 -07:00
Alex Yang e072c45393 fix: remove non-standard API pipeline (#850) 2024-05-16 16:31:48 -07:00
Alex Yang 51241865f8 feat: improve BaseNode (#848) 2024-05-16 16:29:16 -07:00
Thuc Pham 10c83485d2 fix: allow custom task query for agents (#846) 2024-05-16 12:48:50 -07:00
Alex Yang 1e6a18ad2d build: fix jsr release 2024-05-15 18:03:22 -07:00
Alex Yang 9e133ac10d refactor: remove defaultFS from parameters (#841) 2024-05-15 17:37:51 -07:00
Alex Yang ba217eec2c chore: remove test.py (#842) 2024-05-15 16:47:39 -07:00
Alex Yang 64ef70b735 build: ignore example project 2024-05-15 16:10:08 -07:00
Alex Yang 6615aaa4ab chore: use pnpm format
Using `pnpm format:write` will cause two commits which is not expected
2024-05-15 13:11:53 -07:00
Parham Saidi 447105a6dc fix: Gemini text chat - prevent sending broken messageContent and history (#822) 2024-05-15 16:33:55 +07:00
Huu Le (Lee) 320be3fab6 chore: rollback chromadb version to 1.7.3 (#834)
Co-authored-by: Marcus Schiesser <mail@marcusschiesser.de>
2024-05-14 16:07:44 +07:00
Alex Yang bbd9f85a45 chore: bump openai (#833) 2024-05-13 12:53:12 -07:00
github-actions[bot] 5f29ba5e2c Release 0.3.10 (#832)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-13 10:53:59 -07:00
Alex Yang 4aba02eb82 feat: support gpt4-o (#831) 2024-05-13 10:51:10 -07:00
Alex Yang 75736ad01b build: release output files 2024-05-10 14:08:21 -07:00
Alex Yang 68a508fcd0 test: fix check host (#829) 2024-05-10 11:07:40 -07:00
github-actions[bot] 6281fc8c91 Release 0.3.9 (#828)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-09 11:16:08 -07:00
Alex Yang c3747d092a feat: add nextjs plugin for llamaindex (#824) 2024-05-09 02:29:11 -05:00
Marcus Schiesser 24a39aefb8 feat: send retrieve start and end events (#827) 2024-05-09 14:16:34 +07:00
Alex Yang 0b1299036d chore: bump version (#826) 2024-05-09 00:11:21 -05:00
Alex Yang 2c8d7941f0 ci: fix publish (#825) 2024-05-08 23:30:17 -05:00
Fabian Wimmer a1a72ab223 feat: LlamaParseReader: update Supported File Types to match python version (#823) 2024-05-09 09:51:01 +07:00
Alex Yang b99ab056d1 feat: init @llamaindex/autotool (#819) 2024-05-08 02:56:42 -05:00
github-actions[bot] 1a45b44307 Release 0.3.8 (#816)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-07 13:05:08 -05:00
JT-Dev-215 804c57519f fix: PGVector similarity score (#817) 2024-05-07 12:54:13 -05:00
Marcus Schiesser ce94780b95 feat: add page number to read PDFs (#815) 2024-05-07 10:45:55 +07:00
ezirmusitua 645fcf6c24 fix: use sha256 hash value as the Document.id_ in MarkdownReader (#768)
Co-authored-by: Alex Yang <himself65@outlook.com>
2024-05-07 10:07:39 +07:00
Marcus Schiesser e37fa5d9ca docs: add retriever tool example (#814) 2024-05-07 09:41:14 +07:00
github-actions[bot] 97e4ecd5b8 Release 0.3.7 (#812)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-05 22:11:54 -05:00
Alex Yang b6a660651b feat: allow to change ollama port (#811) 2024-05-05 19:08:00 -05:00
github-actions[bot] 456d3fb0b3 Release 0.3.6 (#810)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-05 18:40:58 -05:00
Alex Yang efa326a871 chore: update package.json and usage of lodash (#809) 2024-05-05 18:30:46 -05:00
Alex Yang 5765b637ce build: fix jsr release 2024-05-03 18:21:08 -05:00
145 changed files with 19159 additions and 4822 deletions
+4 -5
View File
@@ -69,15 +69,14 @@ jobs:
- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm run build --filter llamaindex
run: pnpm run build
- name: Use Build For Examples
run: pnpm link ../packages/core/
working-directory: ./examples
- name: Run Type Check
run: pnpm run type-check
- name: Run Circular Dependency Check
run: pnpm run circular-check
working-directory: ./packages/core
run: pnpm dlx turbo run circular-check
- uses: actions/upload-artifact@v3
if: failure()
with:
@@ -105,7 +104,7 @@ jobs:
- name: Install dependencies
run: pnpm install
- name: Build llamaindex
run: pnpm run build --filter llamaindex
run: pnpm run build
- name: Build ${{ matrix.packages }}
run: pnpm run build
working-directory: packages/core/e2e/examples/${{ matrix.packages }}
@@ -124,7 +123,7 @@ jobs:
- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm run build --filter llamaindex
run: pnpm run build
- name: Copy examples
run: rsync -rv --exclude=node_modules ./examples ${{ runner.temp }}
- name: Pack @llamaindex/env
+1 -1
View File
@@ -1,3 +1,3 @@
pnpm format:write
pnpm format
pnpm lint
npx lint-staged
+11
View File
@@ -78,6 +78,17 @@ node --import tsx ./main.ts
### Next.js
First, you will need to add a llamaindex plugin to your Next.js project.
```js
// next.config.js
const withLlamaIndex = require("llamaindex/next");
module.exports = withLlamaIndex({
// your next.js config
});
```
You can combine `ai` with `llamaindex` in Next.js with RSC (React Server Components).
```tsx
+46
View File
@@ -1,5 +1,51 @@
# docs
## 0.0.19
### Patch Changes
- Updated dependencies [e072c45]
- Updated dependencies [9e133ac]
- Updated dependencies [447105a]
- Updated dependencies [320be3f]
- llamaindex@0.3.11
## 0.0.18
### Patch Changes
- Updated dependencies [4aba02e]
- llamaindex@0.3.10
## 0.0.17
### Patch Changes
- Updated dependencies [c3747d0]
- llamaindex@0.3.9
## 0.0.16
### Patch Changes
- Updated dependencies [ce94780]
- llamaindex@0.3.8
## 0.0.15
### Patch Changes
- Updated dependencies [b6a6606]
- Updated dependencies [b6a6606]
- llamaindex@0.3.7
## 0.0.14
### Patch Changes
- Updated dependencies [efa326a]
- llamaindex@0.3.6
## 0.0.13
### Patch Changes
+14 -14
View File
@@ -1,6 +1,6 @@
{
"name": "docs",
"version": "0.0.13",
"version": "0.0.19",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
@@ -15,29 +15,29 @@
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "^3.2.1",
"@docusaurus/remark-plugin-npm2yarn": "^3.2.1",
"@docusaurus/core": "^3.3.2",
"@docusaurus/remark-plugin-npm2yarn": "^3.3.2",
"@llamaindex/examples": "workspace:*",
"@mdx-js/react": "^3.0.1",
"clsx": "^2.1.0",
"clsx": "^2.1.1",
"llamaindex": "workspace:*",
"postcss": "^8.4.38",
"prism-react-renderer": "^2.3.1",
"raw-loader": "^4.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.2.0",
"@docusaurus/preset-classic": "^3.2.1",
"@docusaurus/theme-classic": "^3.2.1",
"@docusaurus/types": "^3.2.1",
"@docusaurus/module-type-aliases": "3.3.2",
"@docusaurus/preset-classic": "^3.3.2",
"@docusaurus/theme-classic": "^3.3.2",
"@docusaurus/types": "^3.3.2",
"@tsconfig/docusaurus": "^2.0.3",
"@types/node": "^20.12.7",
"docusaurus-plugin-typedoc": "^0.22.0",
"@types/node": "^20.12.11",
"docusaurus-plugin-typedoc": "^1.0.1",
"typedoc": "^0.25.13",
"typedoc-plugin-markdown": "^3.17.1",
"typescript": "^5.4.4"
"typedoc-plugin-markdown": "^4.0.1",
"typescript": "^5.4.5"
},
"browserslist": {
"production": [
+3 -2
View File
@@ -29,15 +29,16 @@ async function main() {
// Create an OpenAIAgent with the function tools
const agent = new OpenAIAgent({
tools: [queryEngineTool],
verbose: true,
});
// Chat with the agent
const response = await agent.chat({
message: "What was his salary?",
message: "What was his first salary?",
});
// Print the response
console.log(String(response));
console.log(response.response);
}
void main().then(() => {
+65
View File
@@ -0,0 +1,65 @@
import {
FunctionTool,
MetadataMode,
NodeWithScore,
OpenAIAgent,
SimpleDirectoryReader,
VectorStoreIndex,
} from "llamaindex";
async function main() {
// Load the documents
const documents = await new SimpleDirectoryReader().loadData({
directoryPath: "node_modules/llamaindex/examples",
});
// Create a vector index from the documents
const vectorIndex = await VectorStoreIndex.fromDocuments(documents);
const retriever = vectorIndex.asRetriever({ similarityTopK: 3 });
const retrieverTool = FunctionTool.from(
async ({ query }: { query: string }) => {
const nodesWithScores = await retriever.retrieve({
query,
});
return nodesWithScores
.map((nodeWithScore: NodeWithScore) =>
nodeWithScore.node.getContent(MetadataMode.NONE),
)
.join("\n");
},
{
name: "get_abramov_info",
description: "Get information about the Abramov documents",
parameters: {
type: "object",
properties: {
query: {
type: "string",
description: "The query about Abramov",
},
},
required: ["query"],
},
},
);
// Create an OpenAIAgent with the function tools
const agent = new OpenAIAgent({
tools: [retrieverTool],
verbose: true,
});
// Chat with the agent
const response = await agent.chat({
message: "What was his first salary?",
});
// Print the response
console.log(response.response);
}
void main().then(() => {
console.log("Done");
});
+6 -1
View File
@@ -2,7 +2,12 @@ import { OllamaEmbedding } from "llamaindex";
import { Ollama } from "llamaindex/llm/ollama";
(async () => {
const llm = new Ollama({ model: "llama3" });
const llm = new Ollama({
model: "llama3",
config: {
host: "http://localhost:11434",
},
});
const embedModel = new OllamaEmbedding({ model: "nomic-embed-text" });
{
const response = await llm.chat({
+8 -8
View File
@@ -4,22 +4,22 @@
"version": "0.0.4",
"dependencies": {
"@aws-crypto/sha256-js": "^5.2.0",
"@datastax/astra-db-ts": "^1.0.1",
"@datastax/astra-db-ts": "^1.1.0",
"@notionhq/client": "^2.2.15",
"@pinecone-database/pinecone": "^1.1.3",
"@zilliz/milvus2-sdk-node": "^2.4.1",
"chromadb": "^1.8.1",
"commander": "^11.1.0",
"@pinecone-database/pinecone": "^2.2.0",
"@zilliz/milvus2-sdk-node": "^2.4.2",
"chromadb": "^1.7.3",
"commander": "^12.0.0",
"dotenv": "^16.4.5",
"js-tiktoken": "^1.0.11",
"llamaindex": "*",
"mongodb": "^6.5.0",
"mongodb": "^6.6.1",
"pathe": "^1.1.2"
},
"devDependencies": {
"@types/node": "^20.12.7",
"@types/node": "^20.12.11",
"ts-node": "^10.9.2",
"tsx": "^4.7.2",
"tsx": "^4.9.3",
"typescript": "^5.4.5"
},
"scripts": {
+2 -2
View File
@@ -17,8 +17,8 @@
"llamaindex": "*"
},
"devDependencies": {
"@types/node": "^20.12.7",
"tsx": "^4.7.2",
"@types/node": "^20.12.11",
"tsx": "^4.9.3",
"typescript": "^5.4.5"
}
}
View File
+9 -8
View File
@@ -2,8 +2,8 @@
"name": "@llamaindex/monorepo",
"private": true,
"scripts": {
"build": "turbo run build",
"build:release": "turbo run build lint test --filter=\"!docs\" --filter=\"!*-test\"",
"build": "turbo run build --filter=\"!docs\" --filter=\"!*-test\" --filter=\"!*-example\"",
"build:release": "turbo run build lint test --filter=\"!docs\" --filter=\"!*-test\" --filter=\"!*-example\"",
"dev": "turbo run dev",
"format": "prettier --ignore-unknown --cache --check .",
"format:write": "prettier --ignore-unknown --write .",
@@ -20,17 +20,18 @@
},
"devDependencies": {
"@changesets/cli": "^2.27.1",
"@typescript-eslint/eslint-plugin": "^7.7.0",
"@typescript-eslint/eslint-plugin": "^7.8.0",
"eslint": "^8.57.0",
"eslint-config-next": "^13.5.6",
"eslint-config-prettier": "^8.10.0",
"eslint-config-turbo": "^1.13.2",
"eslint-plugin-react": "7.28.0",
"eslint-config-next": "^14.2.3",
"eslint-config-prettier": "^9.1.0",
"eslint-config-turbo": "^1.13.3",
"eslint-plugin-react": "7.34.1",
"husky": "^9.0.11",
"lint-staged": "^15.2.2",
"madge": "^7.0.0",
"prettier": "^3.2.5",
"prettier-plugin-organize-imports": "^3.2.4",
"turbo": "^1.13.2",
"turbo": "^1.13.3",
"typescript": "^5.4.5"
},
"packageManager": "pnpm@9.0.5",
+83
View File
@@ -0,0 +1,83 @@
# @llamaindex/autotool
> Auto transpile your JS function to LLM Agent compatible
## Usage
First, Install the package
```shell
npm install @llamaindex/autotool
pnpm add @llamaindex/autotool
yarn add @llamaindex/autotool
```
Second, Add the plugin/loader to your configuration:
### Next.js
```javascript
import { withNext } from "@llamaindex/autotool/next";
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default withNext(nextConfig);
```
### Node.js
```shell
node --import @llamaindex/autotool/node ./path/to/your/script.js
```
Third, add `"use tool"` on top of your tool file or change to `.tool.ts`.
```typescript
"use tool";
export function getWeather(city: string) {
// ...
}
// ...
```
Finally, export a chat handler function to the frontend using `llamaindex` Agent
```typescript
"use server";
// imports ...
export async function chatWithAI(message: string): Promise<JSX.Element> {
const agent = new OpenAIAgent({
tools: convertTools("llamaindex"),
});
const uiStream = createStreamableUI();
agent
.chat({
stream: true,
message,
})
.then(async (responseStream) => {
return responseStream.pipeTo(
new WritableStream({
start: () => {
uiStream.append("\n");
},
write: async (message) => {
uiStream.append(message.response.delta);
},
close: () => {
uiStream.done();
},
}),
);
});
return uiStream.value;
}
```
## License
MIT
@@ -0,0 +1,28 @@
# @llamaindex/autotool-01-node-example
## null
### Patch Changes
- Updated dependencies [e072c45]
- Updated dependencies [9e133ac]
- Updated dependencies [447105a]
- Updated dependencies [320be3f]
- llamaindex@0.3.11
- @llamaindex/autotool@0.0.1
## null
### Patch Changes
- Updated dependencies [4aba02e]
- llamaindex@0.3.10
- @llamaindex/autotool@0.0.1
## null
### Patch Changes
- Updated dependencies [c3747d0]
- llamaindex@0.3.9
- @llamaindex/autotool@0.0.1
@@ -0,0 +1,17 @@
{
"name": "@llamaindex/autotool-01-node-example",
"private": true,
"type": "module",
"dependencies": {
"@llamaindex/autotool": "workspace:*",
"llamaindex": "workspace:*",
"openai": "^4.43.0"
},
"devDependencies": {
"tsx": "^4.9.3"
},
"scripts": {
"start": "node --import tsx --import @llamaindex/autotool/node ./src/index.ts"
},
"version": null
}
@@ -0,0 +1,11 @@
import { getWeather } from "./utils.js";
/**
* Get current location
*/
export function getCurrentLocation() {
console.log("Getting current location");
return "London";
}
export { getWeather };
@@ -0,0 +1,23 @@
import { convertTools } from "@llamaindex/autotool";
import { OpenAI } from "openai";
import "./index.tool.js";
const openai = new OpenAI();
{
const response = await openai.chat.completions.create({
model: "gpt-3.5-turbo",
messages: [
{
role: "user",
content: "What's my current weather?",
},
],
tools: convertTools("openai"),
stream: false,
});
const toolCalls = response.choices[0].message.tool_calls ?? [];
for (const toolCall of toolCalls) {
toolCall.function.name;
}
}
@@ -0,0 +1,8 @@
/**
* Get the weather for a city
* @param city The city to get the weather for
* @returns The weather for the city, e.g. "Sunny", "Rainy", etc.
*/
export function getWeather(city: string) {
return `The weather in ${city} is sunny!`;
}
@@ -0,0 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./lib",
"module": "node16",
"moduleResolution": "node16"
},
"include": ["./src"]
}
@@ -0,0 +1,3 @@
# Rename this file to `.env.local` to use environment variables locally with `next dev`
# https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables
MY_HOST="example.com"
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
@@ -0,0 +1,28 @@
# @llamaindex/autotool-02-next-example
## 0.1.3
### Patch Changes
- Updated dependencies [e072c45]
- Updated dependencies [9e133ac]
- Updated dependencies [447105a]
- Updated dependencies [320be3f]
- llamaindex@0.3.11
- @llamaindex/autotool@0.0.1
## 0.1.2
### Patch Changes
- Updated dependencies [4aba02e]
- llamaindex@0.3.10
- @llamaindex/autotool@0.0.1
## 0.1.1
### Patch Changes
- Updated dependencies [c3747d0]
- llamaindex@0.3.9
- @llamaindex/autotool@0.0.1
@@ -0,0 +1,30 @@
This is a [LlamaIndex](https://www.llamaindex.ai/) project using [Next.js](https://nextjs.org/) bootstrapped with [`create-llama`](https://github.com/run-llama/LlamaIndexTS/tree/main/packages/create-llama).
## Getting Started
First, install the dependencies:
```
npm install
```
Second, run the development server:
```
npm run dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about LlamaIndex, take a look at the following resources:
- [LlamaIndex Documentation](https://docs.llamaindex.ai) - learn about LlamaIndex (Python features).
- [LlamaIndexTS Documentation](https://ts.llamaindex.ai) - learn about LlamaIndex (Typescript features).
You can check out [the LlamaIndexTS GitHub repository](https://github.com/run-llama/LlamaIndexTS) - your feedback and contributions are welcome!
@@ -0,0 +1,38 @@
"use server";
import { OpenAIAgent } from "llamaindex";
// import your tools on top, that's it
import { runWithStreamableUI } from "@/context";
import "@/tool";
import { convertTools } from "@llamaindex/autotool";
import { createStreamableUI } from "ai/rsc";
import type { JSX } from "react";
export async function chatWithAI(message: string): Promise<JSX.Element> {
const agent = new OpenAIAgent({
tools: convertTools("llamaindex"),
});
const uiStream = createStreamableUI();
runWithStreamableUI(uiStream, () =>
agent
.chat({
stream: true,
message,
})
.then(async (responseStream) => {
return responseStream.pipeTo(
new WritableStream({
start: () => {
uiStream.append("\n");
},
write: async (message) => {
uiStream.append(message.response.delta);
},
close: () => {
uiStream.done();
},
}),
);
}),
).catch(uiStream.error);
return uiStream.value;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -0,0 +1,94 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 47.4% 11.2%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--card: 0 0% 100%;
--card-foreground: 222.2 47.4% 11.2%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 100% 50%;
--destructive-foreground: 210 40% 98%;
--ring: 215 20.2% 65.1%;
--radius: 0.5rem;
}
.dark {
--background: 224 71% 4%;
--foreground: 213 31% 91%;
--muted: 223 47% 11%;
--muted-foreground: 215.4 16.3% 56.9%;
--accent: 216 34% 17%;
--accent-foreground: 210 40% 98%;
--popover: 224 71% 4%;
--popover-foreground: 215 20.2% 65.1%;
--border: 216 34% 17%;
--input: 216 34% 17%;
--card: 224 71% 4%;
--card-foreground: 213 31% 91%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 1.2%;
--secondary: 222.2 47.4% 11.2%;
--secondary-foreground: 210 40% 98%;
--destructive: 0 63% 31%;
--destructive-foreground: 210 40% 98%;
--ring: 216 34% 17%;
--radius: 0.5rem;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
font-feature-settings:
"rlig" 1,
"calt" 1;
}
.background-gradient {
background-color: #fff;
background-image: radial-gradient(
at 21% 11%,
rgba(186, 186, 233, 0.53) 0,
transparent 50%
),
radial-gradient(at 85% 0, hsla(46, 57%, 78%, 0.52) 0, transparent 50%),
radial-gradient(at 91% 36%, rgba(194, 213, 255, 0.68) 0, transparent 50%),
radial-gradient(at 8% 40%, rgba(251, 218, 239, 0.46) 0, transparent 50%);
}
}
@@ -0,0 +1,26 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { Toaster } from "sonner";
import "./globals.css";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Create Llama App",
description: "Generated by create-llama",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
<Toaster />
{children}
</body>
</html>
);
}
@@ -0,0 +1,11 @@
import { ChatSection } from "@/components/chat-section";
export const runtime = "edge";
export default function Home() {
return (
<main className="flex min-h-screen flex-col items-center gap-10 p-24 background-gradient">
<ChatSection />
</main>
);
}
@@ -0,0 +1,35 @@
"use client";
import { chatWithAI } from "@/actions";
import { ReactNode, useActionState } from "react";
import { toast } from "sonner";
export function ChatSection() {
const [state, formAction] = useActionState<ReactNode | null, FormData>(
async (state, payload) => {
const input = payload.get("input") as string | null;
if (!input) {
toast.error("Please type a message");
return null;
}
return chatWithAI(input);
},
null,
);
return (
<form>
<div className="border border-gray-400 p-2 max-w-md">{state}</div>
<input
className="border border-gray-400 p-2"
type="text"
name="input"
placeholder="Type your message here"
/>
<button
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
formAction={formAction}
>
Chat
</button>
</form>
);
}
@@ -0,0 +1,9 @@
export function LocationCard() {
return (
<div className="border border-gray-400 p-2 max-w-md">
<h1>Weather</h1>
<p>San Francisco, CA</p>
<p>Sunny</p>
</div>
);
}
@@ -0,0 +1,23 @@
export function Spinner() {
return (
<div role="status">
<svg
aria-hidden="true"
className="w-8 h-8 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600"
viewBox="0 0 100 101"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
fill="currentColor"
/>
<path
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
fill="currentFill"
/>
</svg>
<span className="sr-only">Loading...</span>
</div>
);
}
@@ -0,0 +1,14 @@
import type { createStreamableUI } from "ai/rsc";
import { AsyncLocalStorage } from "node:async_hooks";
type StreamableUI = ReturnType<typeof createStreamableUI>;
const streamUIAsyncLocalStorage = new AsyncLocalStorage<StreamableUI>();
export function getCurrentStreamableUI() {
return streamUIAsyncLocalStorage.getStore();
}
export function runWithStreamableUI<T>(streamUI: StreamableUI, fn: () => T): T {
return streamUIAsyncLocalStorage.run(streamUI, fn);
}
@@ -0,0 +1,6 @@
import { withNext } from "@llamaindex/autotool/next";
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default withNext(nextConfig);
@@ -0,0 +1,37 @@
{
"name": "@llamaindex/autotool-02-next-example",
"private": true,
"version": "0.1.3",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@llamaindex/autotool": "workspace:*",
"@radix-ui/react-slot": "^1.0.2",
"ai": "^3.1.3",
"class-variance-authority": "^0.7.0",
"dotenv": "^16.3.1",
"llamaindex": "workspace:*",
"lucide-react": "^0.378.0",
"next": "14.3.0-canary.51",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-markdown": "^9.0.1",
"react-syntax-highlighter": "^15.5.0",
"sonner": "^1.4.41",
"tailwind-merge": "^2.1.0"
},
"devDependencies": {
"@types/node": "^20.12.11",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"@types/react-syntax-highlighter": "^15.5.11",
"autoprefixer": "^10.4.16",
"cross-env": "^7.0.3",
"postcss": "^8.4.32",
"tailwindcss": "^3.3.6",
"typescript": "^5.4.5"
}
}
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

@@ -0,0 +1,78 @@
import type { Config } from "tailwindcss";
import { fontFamily } from "tailwindcss/defaultTheme";
const config: Config = {
darkMode: ["class"],
content: ["app/**/*.{ts,tsx}", "components/**/*.{ts,tsx}"],
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive) / <alpha-value>)",
foreground: "hsl(var(--destructive-foreground) / <alpha-value>)",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
xl: `calc(var(--radius) + 4px)`,
lg: `var(--radius)`,
md: `calc(var(--radius) - 2px)`,
sm: "calc(var(--radius) - 4px)",
},
fontFamily: {
sans: ["var(--font-sans)", ...fontFamily.sans],
},
keyframes: {
"accordion-down": {
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
},
},
plugins: [],
};
export default config;
@@ -0,0 +1,27 @@
"use tool";
import { getCurrentStreamableUI } from "@/context";
export async function getMyUserID() {
const ui = getCurrentStreamableUI()!;
ui.update("Getting user ID...");
await new Promise((resolve) => setTimeout(resolve, 2000));
return "12345";
}
export async function showUserInfo(userId: string) {
const ui = getCurrentStreamableUI()!;
ui.update("Getting user info...");
await new Promise((resolve) => setTimeout(resolve, 2000));
ui.update(
<div>
User ID: {userId}
<br />
Name: John Doe
</div>,
);
return `User ID: ${userId}\nName: John Doe\nEmail: alex@gmail.com\nPhone: 123-456-7890\nAddress: 123 Main St\nCity: San Francisco\nState: CA\nZip: 94105\nCountry: USA\n`;
}
export function getWeather(address: string) {
return `The weather in ${address} is sunny!`;
}
@@ -0,0 +1,28 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
},
"forceConsistentCasingInFileNames": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
+82
View File
@@ -0,0 +1,82 @@
{
"name": "@llamaindex/autotool",
"type": "module",
"version": "0.0.1",
"description": "auto transpile your JS function to LLM Agent compatible",
"files": [
"dist",
"CHANGELOG.md"
],
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"default": "./dist/index.js"
},
"./next": {
"types": "./dist/next.d.ts",
"import": "./dist/next.js",
"require": "./dist/next.cjs",
"default": "./dist/next.js"
},
"./webpack": {
"types": "./dist/webpack.d.ts",
"import": "./dist/webpack.js",
"require": "./dist/webpack.cjs",
"default": "./dist/webpack.js"
},
"./vite": {
"types": "./dist/vite.d.ts",
"import": "./dist/vite.js",
"require": "./dist/vite.cjs",
"default": "./dist/vite.js"
},
"./loader": {
"types": "./dist/loader.d.ts",
"import": "./dist/loader.js",
"require": "./dist/loader.cjs",
"default": "./dist/loader.js"
},
"./node": "./dist/node.js"
},
"scripts": {
"build": "bunchee",
"dev": "bunchee --watch"
},
"dependencies": {
"@swc/core": "^1.5.5",
"jotai": "^2.8.0",
"typedoc": "^0.25.13",
"unplugin": "^1.10.1"
},
"peerDependencies": {
"llamaindex": "^0.3.11",
"openai": "^4",
"typescript": "^4"
},
"peerDependenciesMeta": {
"openai": {
"optional": true
},
"llamaindex": {
"optional": true
},
"typescript": {
"optional": true
}
},
"devDependencies": {
"@swc/types": "^0.1.6",
"@types/json-schema": "^7.0.15",
"@types/node": "^20.12.11",
"bunchee": "^5.1.5",
"llamaindex": "workspace:*",
"next": "14.2.3",
"rollup": "^4.17.2",
"tsx": "^4.9.3",
"typescript": "^5.4.5",
"vitest": "^1.6.0",
"webpack": "^5.91.0"
}
}
+103
View File
@@ -0,0 +1,103 @@
import type {
JSONSchema7,
JSONSchema7Definition,
JSONSchema7TypeName,
} from "json-schema";
import type { ToolMetadata } from "llamaindex";
import type { SourceMapInput } from "rollup";
import td from "typedoc";
import type { SourceMapCompact } from "unplugin";
import type { InfoString } from "./internal";
export const isToolFile = (url: string) => /tool\.[jt]sx?$/.test(url);
export const isJSorTS = (url: string) => /\.m?[jt]sx?$/.test(url);
async function parseRoot(entryPoint: string) {
const app = await td.Application.bootstrapWithPlugins(
{
entryPoints: [entryPoint],
},
[
new td.TypeDocReader(),
new td.PackageJsonReader(),
new td.TSConfigReader(),
],
);
const project = await app.convert();
if (project) {
return app.serializer.projectToObject(project, process.cwd());
}
throw new Error("Failed to parse root");
}
export async function transformAutoTool(
code: string,
url: string,
): Promise<{
code: string;
map?: SourceMapInput | SourceMapCompact | null;
}> {
const json = await parseRoot(url);
const children = json.children;
if (Array.isArray(children)) {
const schema = {
type: "object",
properties: {} as {
[key: string]: JSONSchema7Definition;
},
additionalItems: false,
required: [] as string[],
} satisfies JSONSchema7;
const info: InfoString = {
originalFunction: undefined,
parameterMapping: {},
};
children.forEach((child) => {
// replace starting and ending quotes, to make it a function in the runtime
info.originalFunction = child.name;
const metadata: ToolMetadata = {
name: child.name,
description: "",
parameters: schema,
};
child.signatures?.forEach((signature) => {
const description = signature.comment?.summary
.map((x) => x.text)
.join("\n");
if (description) {
metadata.description += description;
}
signature.parameters?.map((parameter, idx) => {
if (parameter.type?.type === "intrinsic") {
// parameter.type.name
schema.properties[parameter.name as string] = {
type: parameter.type.name as JSONSchema7TypeName,
description: parameter.comment?.summary
.map((x) => x.text)
.join("\n"),
} as JSONSchema7Definition;
schema.required.push(parameter.name as string);
info.parameterMapping[parameter.name as string] = idx;
}
});
});
const infoJSON = JSON.stringify(info)
// remove quotes from `originalFunction` value
.replace(/"originalFunction":"(.*?)"/g, '"originalFunction":$1');
code =
code + `\ninjectMetadata(${JSON.stringify(metadata)}, ${infoJSON});`;
});
}
if (
!/^import\s+{\sinjectMetadata\s}\s+from\s+['"]@llamaindex\/tool['"]/.test(
code,
)
) {
code = `import {injectMetadata} from '@llamaindex/autotool';\n${code}`;
}
return {
code,
map: null,
};
}
+82
View File
@@ -0,0 +1,82 @@
import { atom } from "jotai/vanilla";
import type { BaseToolWithCall, ToolMetadata } from "llamaindex";
import type { ChatCompletionTool } from "openai/resources/chat/completions";
import { store, toolMetadataAtom, toolsAtom, type Info } from "./internal";
export type { Info };
/**
* @internal This function is used by the compiler to inject metadata into the source code.
*/
export function injectMetadata(metadata: ToolMetadata, info: Info) {
store.get(toolMetadataAtom).push([metadata, info]);
}
const openaiToolsAtom = atom<ChatCompletionTool[]>((get) => {
const metadata = get(toolMetadataAtom);
return metadata.map(([metadata]) => ({
type: "function",
function: {
parameters: metadata.parameters,
name: metadata.name,
description: metadata.description,
},
}));
});
const llamaindexToolsAtom = atom<BaseToolWithCall[]>((get) => {
const metadata = get(toolMetadataAtom);
const fns = get(toolsAtom);
return metadata.map(([metadata, info]) => ({
call: (input: Record<string, unknown>) => {
const args = Object.entries(info.parameterMapping).reduce(
(arr, [name, idx]) => {
arr[idx] = input[name];
return arr;
},
[] as unknown[],
);
const fn = fns[metadata.name] ?? info.originalFunction;
if (!fn) {
throw new Error(`Cannot find function to call: ${metadata.name}`);
}
return fn(...args);
},
metadata,
}));
});
export function convertTools(format: "openai"): ChatCompletionTool[];
export function convertTools(format: "llamaindex"): BaseToolWithCall[];
export function convertTools(
format: string,
): ChatCompletionTool[] | BaseToolWithCall[] {
switch (format) {
case "openai": {
return store.get(openaiToolsAtom);
}
case "llamaindex": {
return store.get(llamaindexToolsAtom);
}
}
throw new Error(`Unknown format: ${format}`);
}
/**
* Call a tool by name with the given input.
*/
export function callTool(
name: string,
input: string | Record<string, unknown>,
): unknown | Promise<unknown> {
const tools = store.get(llamaindexToolsAtom);
const targetTool = tools.find((tool) => tool.metadata.name === name);
if (!targetTool) {
throw new Error(`Cannot find tool: ${name}`);
}
return targetTool.call(
// for OpenAI, input is a string
// for ClaudeAI, input is an object
typeof input === "string" ? JSON.parse(input) : input,
);
}
+26
View File
@@ -0,0 +1,26 @@
import { atom, createStore } from "jotai/vanilla";
import type { ToolMetadata } from "llamaindex";
export type Info = {
originalFunction?: (...args: any[]) => any;
/**
* In current LLM, it doesn't support non-object parameter, so we mock arguments as object, and use this mapping to convert it back.
*/
parameterMapping: Record<string, number>;
};
/**
* This is used in parser side to store the original function and parameter mapping.
*
* In the runtime, originalFunction is a JS function.
*
* @internal
*/
export type InfoString = {
originalFunction?: string;
parameterMapping: Record<string, number>;
};
export const store = createStore();
export const toolMetadataAtom = atom<[ToolMetadata, Info][]>([]);
export const toolsAtom = atom<Record<string, (...args: any[]) => any>>({});
+38
View File
@@ -0,0 +1,38 @@
/**
* This is a node module loader hook that injects metadata into the source code.
*
* @module
*/
import { parse } from "@swc/core";
import type { ExpressionStatement } from "@swc/types";
import type { LoadHook } from "node:module";
import { fileURLToPath } from "node:url";
import { isJSorTS, isToolFile, transformAutoTool } from "./compiler";
export const load: LoadHook = async (url, context, nextLoad) => {
const output = await nextLoad(url, context);
if (typeof output.source === "string" && isJSorTS(url)) {
const isTool = isToolFile(url);
const hasToolDirective = (await parse(output.source)).body
.filter(
(node): node is ExpressionStatement =>
node.type === "ExpressionStatement",
)
.some(
(node) =>
node.expression.type === "StringLiteral" &&
node.expression.value === "use tool",
);
if (isTool || hasToolDirective) {
const { code } = await transformAutoTool(
output.source,
fileURLToPath(url),
);
return {
...output,
source: code,
};
}
}
return output;
};
+13
View File
@@ -0,0 +1,13 @@
import type { NextConfig } from "next";
import webpackPlugin from "./webpack";
export function withNext(config: NextConfig) {
return {
...config,
webpack: (webpackConfig: any, context: any) => {
webpackConfig = config.webpack?.(webpackConfig, context) ?? webpackConfig;
webpackConfig.plugins.push(webpackPlugin());
return webpackConfig;
},
};
}
+16
View File
@@ -0,0 +1,16 @@
/**
* @example
* ```shell
* node --import @llamaindex/autotool/node ./dist/index.js
* ```
*
* @example
* ```shell
* node --import tsx --import @llamaindex/autotool/node ./src/index.ts
* ```
*
* @module
*/
import { register } from "node:module";
register("./loader.js", import.meta.url);
+35
View File
@@ -0,0 +1,35 @@
import { parse } from "@swc/core";
import type { ExpressionStatement } from "@swc/types";
import { createUnplugin, type UnpluginFactory } from "unplugin";
import { isJSorTS, isToolFile, transformAutoTool } from "./compiler";
export interface Options {}
const name = "llama-index-tool";
export const unpluginFactory: UnpluginFactory<Options | undefined> = () => ({
name,
async transform(code, id) {
if (!isJSorTS(id)) {
return code;
}
const isTool = isToolFile(id);
const hasToolDirective = (await parse(code)).body
.filter(
(node): node is ExpressionStatement =>
node.type === "ExpressionStatement",
)
.some(
(node) =>
node.expression.type === "StringLiteral" &&
node.expression.value === "use tool",
);
if (isTool || hasToolDirective) {
return transformAutoTool(code, id);
}
},
});
export const unplugin = /* #__PURE__ */ createUnplugin(unpluginFactory);
export default unplugin;
+6
View File
@@ -0,0 +1,6 @@
import { createVitePlugin } from "unplugin";
import { unpluginFactory } from "./plugin";
const vitePlugin = createVitePlugin(unpluginFactory);
export default vitePlugin;
+6
View File
@@ -0,0 +1,6 @@
import { createWebpackPlugin } from "unplugin";
import { unpluginFactory } from "./plugin";
const webpackPlugin = createWebpackPlugin(unpluginFactory);
export default webpackPlugin;
+19
View File
@@ -0,0 +1,19 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"outDir": "./lib",
"types": ["node"]
},
"include": ["./src"],
"references": [
{
"path": "../core/tsconfig.json"
},
{
"path": "../env/tsconfig.json"
}
]
}
+7
View File
@@ -0,0 +1,7 @@
{
"detectiveOptions": {
"ts": {
"skipTypeImports": true
}
}
}
+53
View File
@@ -1,5 +1,58 @@
# llamaindex
## 0.3.11
### Patch Changes
- e072c45: fix: remove non-standard API `pipeline`
- 9e133ac: refactor: remove `defaultFS` from parameters
We don't accept passing fs in the parameter since it's unnecessary for a determined JS environment.
This was a polyfill way for the non-Node.js environment, but now we use another way to polyfill APIs.
- 447105a: Improve Gemini message and context preparation
- 320be3f: Force ChromaDB version to 1.7.3 (to prevent NextJS issues)
- Updated dependencies [e072c45]
- Updated dependencies [9e133ac]
- @llamaindex/env@0.1.3
## 0.3.10
### Patch Changes
- 4aba02e: feat: support gpt4-o
## 0.3.9
### Patch Changes
- c3747d0: fix: import `@xenova/transformers`
For now, if you use llamaindex in next.js, you need to add a plugin from `llamaindex/next` to ensure some module resolutions are correct.
## 0.3.8
### Patch Changes
- ce94780: Add page number to read PDFs and use generated IDs for PDF and markdown content
## 0.3.7
### Patch Changes
- b6a6606: feat: allow change host of ollama
- b6a6606: chore: export ollama in default js runtime
## 0.3.6
### Patch Changes
- efa326a: chore: update package.json
- Updated dependencies [efa326a]
- Updated dependencies [efa326a]
- @llamaindex/env@0.1.2
## 0.3.5
### Patch Changes
+8
View File
@@ -1,5 +1,13 @@
# @llamaindex/core-e2e
## 0.0.5
### Patch Changes
- c3747d0: fix: import `@xenova/transformers`
For now, if you use llamaindex in next.js, you need to add a plugin from `llamaindex/next` to ensure some module resolutions are correct.
## 0.0.4
### Patch Changes
@@ -1,5 +1,51 @@
# @llamaindex/cloudflare-worker-agent-test
## 0.0.12
### Patch Changes
- Updated dependencies [e072c45]
- Updated dependencies [9e133ac]
- Updated dependencies [447105a]
- Updated dependencies [320be3f]
- llamaindex@0.3.11
## 0.0.11
### Patch Changes
- Updated dependencies [4aba02e]
- llamaindex@0.3.10
## 0.0.10
### Patch Changes
- Updated dependencies [c3747d0]
- llamaindex@0.3.9
## 0.0.9
### Patch Changes
- Updated dependencies [ce94780]
- llamaindex@0.3.8
## 0.0.8
### Patch Changes
- Updated dependencies [b6a6606]
- Updated dependencies [b6a6606]
- llamaindex@0.3.7
## 0.0.7
### Patch Changes
- Updated dependencies [efa326a]
- llamaindex@0.3.6
## 0.0.6
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/cloudflare-worker-agent-test",
"version": "0.0.6",
"version": "0.0.12",
"type": "module",
"private": true,
"scripts": {
@@ -12,11 +12,13 @@
"cf-typegen": "wrangler types"
},
"devDependencies": {
"@cloudflare/vitest-pool-workers": "^0.2.3",
"@cloudflare/workers-types": "^4.20240423.0",
"@cloudflare/vitest-pool-workers": "^0.2.6",
"@cloudflare/workers-types": "^4.20240502.0",
"@vitest/runner": "1.3.0",
"@vitest/snapshot": "1.3.0",
"typescript": "^5.4.5",
"vitest": "1.3.0",
"wrangler": "^3.52.0"
"wrangler": "^3.53.1"
},
"dependencies": {
"llamaindex": "workspace:*"
@@ -1,5 +1,55 @@
# @llamaindex/next-agent-test
## 0.1.12
### Patch Changes
- Updated dependencies [e072c45]
- Updated dependencies [9e133ac]
- Updated dependencies [447105a]
- Updated dependencies [320be3f]
- llamaindex@0.3.11
## 0.1.11
### Patch Changes
- Updated dependencies [4aba02e]
- llamaindex@0.3.10
## 0.1.10
### Patch Changes
- c3747d0: fix: import `@xenova/transformers`
For now, if you use llamaindex in next.js, you need to add a plugin from `llamaindex/next` to ensure some module resolutions are correct.
- Updated dependencies [c3747d0]
- llamaindex@0.3.9
## 0.1.9
### Patch Changes
- Updated dependencies [ce94780]
- llamaindex@0.3.8
## 0.1.8
### Patch Changes
- Updated dependencies [b6a6606]
- Updated dependencies [b6a6606]
- llamaindex@0.3.7
## 0.1.7
### Patch Changes
- Updated dependencies [efa326a]
- llamaindex@0.3.6
## 0.1.6
### Patch Changes
@@ -1,4 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default nextConfig;
import withLlamaIndex from "llamaindex/next";
export default withLlamaIndex(nextConfig);
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/next-agent-test",
"version": "0.1.6",
"version": "0.1.12",
"private": true,
"scripts": {
"dev": "next dev",
@@ -9,20 +9,20 @@
"lint": "next lint"
},
"dependencies": {
"ai": "^3.0.34",
"ai": "^3.1.3",
"llamaindex": "workspace:*",
"next": "14.2.3",
"react": "18.2.0",
"react-dom": "18.2.0"
"react": "18.3.1",
"react-dom": "18.3.1"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^18.2.79",
"@types/react-dom": "^18.2.25",
"eslint": "^8",
"@types/node": "^20.12.11",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"eslint": "^8.57.0",
"eslint-config-next": "14.2.3",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5"
"typescript": "^5.4.5"
}
}
@@ -1,5 +1,39 @@
# test-edge-runtime
## 0.1.11
### Patch Changes
- Updated dependencies [e072c45]
- Updated dependencies [9e133ac]
- Updated dependencies [447105a]
- Updated dependencies [320be3f]
- llamaindex@0.3.11
## 0.1.10
### Patch Changes
- Updated dependencies [4aba02e]
- llamaindex@0.3.10
## 0.1.9
### Patch Changes
- c3747d0: fix: import `@xenova/transformers`
For now, if you use llamaindex in next.js, you need to add a plugin from `llamaindex/next` to ensure some module resolutions are correct.
- Updated dependencies [c3747d0]
- llamaindex@0.3.9
## 0.1.8
### Patch Changes
- @llamaindex/edge@0.3.6
## 0.1.7
### Patch Changes
@@ -1,4 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default nextConfig;
import withLlamaIndex from "llamaindex/next";
export default withLlamaIndex(nextConfig);
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/nextjs-edge-runtime-test",
"version": "0.1.7",
"version": "0.1.11",
"private": true,
"scripts": {
"dev": "next dev",
@@ -8,15 +8,15 @@
"start": "next start"
},
"dependencies": {
"@llamaindex/edge": "workspace:*",
"next": "14.1.3",
"react": "^18",
"react-dom": "^18"
"llamaindex": "workspace:*",
"next": "14.2.3",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/node": "^20.12.7",
"@types/react": "^18.2.79",
"@types/react-dom": "^18.2.25",
"typescript": "^5"
"@types/node": "^20.12.11",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"typescript": "^5.4.5"
}
}
@@ -1,232 +0,0 @@
.main {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
padding: 6rem;
min-height: 100vh;
}
.description {
display: inherit;
justify-content: inherit;
align-items: inherit;
font-size: 0.85rem;
max-width: var(--max-width);
width: 100%;
z-index: 2;
font-family: var(--font-mono);
}
.description a {
display: flex;
justify-content: center;
align-items: center;
gap: 0.5rem;
}
.description p {
position: relative;
margin: 0;
padding: 1rem;
background-color: rgba(var(--callout-rgb), 0.5);
border: 1px solid rgba(var(--callout-border-rgb), 0.3);
border-radius: var(--border-radius);
}
.code {
font-weight: 700;
font-family: var(--font-mono);
}
.grid {
display: grid;
grid-template-columns: repeat(4, minmax(25%, auto));
max-width: 100%;
width: var(--max-width);
}
.card {
padding: 1rem 1.2rem;
border-radius: var(--border-radius);
background: rgba(var(--card-rgb), 0);
border: 1px solid rgba(var(--card-border-rgb), 0);
transition:
background 200ms,
border 200ms;
}
.card span {
display: inline-block;
transition: transform 200ms;
}
.card h2 {
font-weight: 600;
margin-bottom: 0.7rem;
}
.card p {
margin: 0;
opacity: 0.6;
font-size: 0.9rem;
line-height: 1.5;
max-width: 30ch;
text-wrap: balance;
}
.center {
display: flex;
justify-content: center;
align-items: center;
position: relative;
padding: 4rem 0;
}
.center::before {
background: var(--secondary-glow);
border-radius: 50%;
width: 480px;
height: 360px;
margin-left: -400px;
}
.center::after {
background: var(--primary-glow);
width: 240px;
height: 180px;
z-index: -1;
}
.center::before,
.center::after {
content: "";
left: 50%;
position: absolute;
filter: blur(45px);
transform: translateZ(0);
}
.logo {
position: relative;
}
/* Enable hover only on non-touch devices */
@media (hover: hover) and (pointer: fine) {
.card:hover {
background: rgba(var(--card-rgb), 0.1);
border: 1px solid rgba(var(--card-border-rgb), 0.15);
}
.card:hover span {
transform: translateX(4px);
}
}
@media (prefers-reduced-motion) {
.card:hover span {
transform: none;
}
}
/* Mobile */
@media (max-width: 700px) {
.content {
padding: 4rem;
}
.grid {
grid-template-columns: 1fr;
margin-bottom: 120px;
max-width: 320px;
text-align: center;
}
.card {
padding: 1rem 2.5rem;
}
.card h2 {
margin-bottom: 0.5rem;
}
.center {
padding: 8rem 0 6rem;
}
.center::before {
transform: none;
height: 300px;
}
.description {
font-size: 0.8rem;
}
.description a {
padding: 1rem;
}
.description p,
.description div {
display: flex;
justify-content: center;
position: fixed;
width: 100%;
}
.description p {
align-items: center;
inset: 0 0 auto;
padding: 2rem 1rem 1.4rem;
border-radius: 0;
border: none;
border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
background: linear-gradient(
to bottom,
rgba(var(--background-start-rgb), 1),
rgba(var(--callout-rgb), 0.5)
);
background-clip: padding-box;
backdrop-filter: blur(24px);
}
.description div {
align-items: flex-end;
pointer-events: none;
inset: auto 0 0;
padding: 2rem;
height: 200px;
background: linear-gradient(
to bottom,
transparent 0%,
rgb(var(--background-end-rgb)) 40%
);
z-index: 1;
}
}
/* Tablet and Smaller Desktop */
@media (min-width: 701px) and (max-width: 1120px) {
.grid {
grid-template-columns: repeat(2, 50%);
}
}
@media (prefers-color-scheme: dark) {
.vercelLogo {
filter: invert(1);
}
.logo {
filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
}
}
@keyframes rotate {
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}
@@ -1,98 +1,20 @@
import Image from "next/image";
import "../utils/llm";
import styles from "./page.module.css";
import { tokenizerResultPromise } from "@/utils/llm";
import { use } from "react";
export const runtime = "edge";
export default function Home() {
const result = use(tokenizerResultPromise);
return (
<main className={styles.main}>
<div className={styles.description}>
<p>
Get started by editing&nbsp;
<code className={styles.code}>src/app/page.tsx</code>
</p>
<main>
<div>
<h1>Next.js Edge Runtime</h1>
<div>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
By{" "}
<Image
src="/vercel.svg"
alt="Vercel Logo"
className={styles.vercelLogo}
width={100}
height={24}
priority
/>
</a>
{result.map((value, index) => (
<span key={index}>{value}</span>
))}
</div>
</div>
<div className={styles.center}>
<Image
className={styles.logo}
src="/next.svg"
alt="Next.js Logo"
width={180}
height={37}
priority
/>
</div>
<div className={styles.grid}>
<a
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2>
Docs <span>-&gt;</span>
</h2>
<p>Find in-depth information about Next.js features and API.</p>
</a>
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2>
Learn <span>-&gt;</span>
</h2>
<p>Learn about Next.js in an interactive course with&nbsp;quizzes!</p>
</a>
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2>
Templates <span>-&gt;</span>
</h2>
<p>Explore starter templates for Next.js.</p>
</a>
<a
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2>
Deploy <span>-&gt;</span>
</h2>
<p>
Instantly deploy your Next.js site to a shareable URL with Vercel.
</p>
</a>
</div>
</main>
);
}
@@ -1,9 +1,23 @@
"use server";
// test runtime
import "llamaindex";
import { ClipEmbedding } from "llamaindex/embeddings/ClipEmbedding";
import "llamaindex/readers/SimpleDirectoryReader";
// @ts-expect-error
if (typeof EdgeRuntime !== "string") {
throw new Error("Expected run in EdgeRuntime");
}
export const tokenizerResultPromise = new Promise<number[]>(
(resolve, reject) => {
const embedding = new ClipEmbedding();
//#region make sure @xenova/transformers is working in edge runtime
embedding
.getTokenizer()
.then((tokenizer) => {
resolve(tokenizer.encode("hello world"));
})
.catch(reject);
//#endregion
},
);
@@ -1,5 +1,6 @@
{
"compilerOptions": {
"target": "ESNext",
"lib": ["dom", "dom.iterable", "esnext"],
"outDir": "./dist",
"allowJs": true,
@@ -1,5 +1,51 @@
# @llamaindex/waku-query-engine-test
## 0.0.12
### Patch Changes
- Updated dependencies [e072c45]
- Updated dependencies [9e133ac]
- Updated dependencies [447105a]
- Updated dependencies [320be3f]
- llamaindex@0.3.11
## 0.0.11
### Patch Changes
- Updated dependencies [4aba02e]
- llamaindex@0.3.10
## 0.0.10
### Patch Changes
- Updated dependencies [c3747d0]
- llamaindex@0.3.9
## 0.0.9
### Patch Changes
- Updated dependencies [ce94780]
- llamaindex@0.3.8
## 0.0.8
### Patch Changes
- Updated dependencies [b6a6606]
- Updated dependencies [b6a6606]
- llamaindex@0.3.7
## 0.0.7
### Patch Changes
- Updated dependencies [efa326a]
- llamaindex@0.3.6
## 0.0.6
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/waku-query-engine-test",
"version": "0.0.6",
"version": "0.0.12",
"type": "module",
"private": true,
"scripts": {
@@ -16,10 +16,10 @@
"waku": "0.20.1"
},
"devDependencies": {
"@types/react": "18.2.74",
"@types/react-dom": "18.2.24",
"@types/react": "18.3.1",
"@types/react-dom": "18.3.0",
"autoprefixer": "10.4.19",
"tailwindcss": "3.4.3",
"typescript": "5.4.4"
"typescript": "5.4.5"
}
}
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/core-e2e",
"private": true,
"version": "0.0.4",
"version": "0.0.5",
"type": "module",
"scripts": {
"e2e": "node --import tsx --import ./mock-register.js --test ./node/*.e2e.ts",
@@ -10,9 +10,9 @@
},
"devDependencies": {
"@faker-js/faker": "^8.4.1",
"@types/node": "^20.12.7",
"@types/node": "^20.12.11",
"consola": "^3.2.3",
"llamaindex": "workspace:*",
"tsx": "^4.7.2"
"tsx": "^4.9.3"
}
}
+3 -3
View File
@@ -1,11 +1,11 @@
{
"name": "@llamaindex/core",
"version": "0.3.5",
"version": "0.3.11",
"exports": "./src/index.ts",
"imports": {
"@llamaindex/env": "jsr:@llamaindex/env@0.1.1"
"@llamaindex/env": "jsr:@llamaindex/env@0.1.3"
},
"publish": {
"include": ["LICENSE", "README.md", "src/**/*"]
"include": ["LICENSE", "README.md", "src/**/*", "jsr.json"]
}
}
+34 -19
View File
@@ -1,48 +1,64 @@
{
"name": "llamaindex",
"version": "0.3.5",
"version": "0.3.11",
"expectedMinorVersion": "3",
"license": "MIT",
"type": "module",
"keywords": [
"llm",
"llama",
"openai",
"gpt",
"data science",
"prompt",
"prompt engineering",
"chatgpt",
"machine learning",
"ml",
"embedding",
"vectorstore",
"data framework",
"llamaindex"
],
"dependencies": {
"@anthropic-ai/sdk": "^0.20.6",
"@anthropic-ai/sdk": "^0.20.9",
"@aws-crypto/sha256-js": "^5.2.0",
"@datastax/astra-db-ts": "^1.0.1",
"@google/generative-ai": "^0.8.0",
"@grpc/grpc-js": "^1.10.6",
"@datastax/astra-db-ts": "^1.1.0",
"@google/generative-ai": "^0.11.0",
"@grpc/grpc-js": "^1.10.7",
"@huggingface/inference": "^2.6.7",
"@llamaindex/cloud": "0.0.5",
"@llamaindex/env": "workspace:*",
"@mistralai/mistralai": "^0.1.3",
"@mistralai/mistralai": "^0.2.0",
"@pinecone-database/pinecone": "^2.2.0",
"@qdrant/js-client-rest": "^1.8.2",
"@types/lodash": "^4.17.0",
"@qdrant/js-client-rest": "^1.9.0",
"@types/lodash": "^4.17.1",
"@types/papaparse": "^5.3.14",
"@types/pg": "^8.11.5",
"@types/pg": "^8.11.6",
"@xenova/transformers": "^2.17.1",
"@zilliz/milvus2-sdk-node": "^2.4.1",
"ajv": "^8.12.0",
"assemblyai": "^4.4.1",
"@zilliz/milvus2-sdk-node": "^2.4.2",
"ajv": "^8.13.0",
"assemblyai": "^4.4.2",
"chromadb": "~1.7.3",
"cohere-ai": "^7.9.5",
"js-tiktoken": "^1.0.11",
"lodash": "^4.17.21",
"magic-bytes.js": "^1.10.0",
"mammoth": "^1.7.1",
"mammoth": "^1.7.2",
"md-utils-ts": "^2.0.0",
"mongodb": "^6.5.0",
"mongodb": "^6.6.1",
"notion-md-crawler": "^1.0.0",
"openai": "^4.38.0",
"openai": "^4.46.0",
"papaparse": "^5.4.1",
"pathe": "^1.1.2",
"pdf2json": "^3.0.5",
"pdf2json": "3.0.5",
"pg": "^8.11.5",
"pgvector": "^0.1.8",
"portkey-ai": "^0.1.16",
"rake-modified": "^1.0.8",
"string-strip-html": "^13.4.8",
"wikipedia": "^2.1.2",
"wink-nlp": "^1.14.3"
"wink-nlp": "^2.2.2"
},
"peerDependencies": {
"@notionhq/client": "^2.2.15"
@@ -50,10 +66,9 @@
"devDependencies": {
"@notionhq/client": "^2.2.15",
"@swc/cli": "^0.3.12",
"@swc/core": "^1.4.16",
"@swc/core": "^1.5.5",
"concurrently": "^8.2.2",
"glob": "^10.3.12",
"madge": "^7.0.0",
"typescript": "^5.4.5"
},
"engines": {
+89 -53
View File
@@ -1,5 +1,5 @@
import { createSHA256, path, randomUUID } from "@llamaindex/env";
import _ from "lodash";
import { chunkSizeCheck, lazyInitHash } from "./internal/decorator/node.js";
export enum NodeRelationship {
SOURCE = "SOURCE",
@@ -37,6 +37,16 @@ export type RelatedNodeType<T extends Metadata = Metadata> =
| RelatedNodeInfo<T>
| RelatedNodeInfo<T>[];
export type BaseNodeParams<T extends Metadata = Metadata> = {
id_?: string;
metadata?: T;
excludedEmbedMetadataKeys?: string[];
excludedLlmMetadataKeys?: string[];
relationships?: Partial<Record<NodeRelationship, RelatedNodeType<T>>>;
hash?: string;
embedding?: number[];
};
/**
* Generic abstract class for retrievable nodes
*/
@@ -47,21 +57,37 @@ export abstract class BaseNode<T extends Metadata = Metadata> {
*
* Set to a UUID by default.
*/
id_: string = randomUUID();
id_: string;
embedding?: number[];
// Metadata fields
metadata: T = {} as T;
excludedEmbedMetadataKeys: string[] = [];
excludedLlmMetadataKeys: string[] = [];
relationships: Partial<Record<NodeRelationship, RelatedNodeType<T>>> = {};
hash: string = "";
metadata: T;
excludedEmbedMetadataKeys: string[];
excludedLlmMetadataKeys: string[];
relationships: Partial<Record<NodeRelationship, RelatedNodeType<T>>>;
constructor(init?: Partial<BaseNode<T>>) {
Object.assign(this, init);
@lazyInitHash
accessor hash: string = "";
protected constructor(init?: BaseNodeParams<T>) {
const {
id_,
metadata,
excludedEmbedMetadataKeys,
excludedLlmMetadataKeys,
relationships,
hash,
embedding,
} = init || {};
this.id_ = id_ ?? randomUUID();
this.metadata = metadata ?? ({} as T);
this.excludedEmbedMetadataKeys = excludedEmbedMetadataKeys ?? [];
this.excludedLlmMetadataKeys = excludedLlmMetadataKeys ?? [];
this.relationships = relationships ?? {};
this.embedding = embedding;
}
abstract getType(): ObjectType;
abstract get type(): ObjectType;
abstract getContent(metadataMode: MetadataMode): string;
abstract getMetadataStr(metadataMode: MetadataMode): string;
@@ -146,7 +172,12 @@ export abstract class BaseNode<T extends Metadata = Metadata> {
* @see toMutableJSON - use to return a mutable JSON instead
*/
toJSON(): Record<string, any> {
return { ...this, type: this.getType() };
return {
...this,
type: this.type,
// hash is an accessor property, so it's not included in the rest operator
hash: this.hash,
};
}
clone(): BaseNode {
@@ -159,32 +190,43 @@ export abstract class BaseNode<T extends Metadata = Metadata> {
* @return {Record<string, any>} - The JSON representation of the object.
*/
toMutableJSON(): Record<string, any> {
return _.cloneDeep(this.toJSON());
return structuredClone(this.toJSON());
}
}
export type TextNodeParams<T extends Metadata = Metadata> =
BaseNodeParams<T> & {
text?: string;
textTemplate?: string;
startCharIdx?: number;
endCharIdx?: number;
metadataSeparator?: string;
};
/**
* TextNode is the default node type for text. Most common node type in LlamaIndex.TS
*/
export class TextNode<T extends Metadata = Metadata> extends BaseNode<T> {
text: string = "";
textTemplate: string = "";
text: string;
textTemplate: string;
startCharIdx?: number;
endCharIdx?: number;
// textTemplate: NOTE write your own formatter if needed
// metadataTemplate: NOTE write your own formatter if needed
metadataSeparator: string = "\n";
metadataSeparator: string;
constructor(init?: Partial<TextNode<T>>) {
constructor(init: TextNodeParams<T> = {}) {
super(init);
Object.assign(this, init);
if (new.target === TextNode) {
// Don't generate the hash repeatedly so only do it if this is
// constructing the derived class
this.hash = init?.hash ?? this.generateHash();
const { text, textTemplate, startCharIdx, endCharIdx, metadataSeparator } =
init;
this.text = text ?? "";
this.textTemplate = textTemplate ?? "";
if (startCharIdx) {
this.startCharIdx = startCharIdx;
}
this.endCharIdx = endCharIdx;
this.metadataSeparator = metadataSeparator ?? "\n";
}
/**
@@ -194,7 +236,7 @@ export class TextNode<T extends Metadata = Metadata> extends BaseNode<T> {
*/
generateHash() {
const hashFunction = createSHA256();
hashFunction.update(`type=${this.getType()}`);
hashFunction.update(`type=${this.type}`);
hashFunction.update(
`startCharIdx=${this.startCharIdx} endCharIdx=${this.endCharIdx}`,
);
@@ -202,10 +244,11 @@ export class TextNode<T extends Metadata = Metadata> extends BaseNode<T> {
return hashFunction.digest();
}
getType(): ObjectType {
get type() {
return ObjectType.TEXT;
}
@chunkSizeCheck
getContent(metadataMode: MetadataMode = MetadataMode.NONE): string {
const metadataStr = this.getMetadataStr(metadataMode).trim();
return `${metadataStr}\n\n${this.text}`.trim();
@@ -246,19 +289,21 @@ export class TextNode<T extends Metadata = Metadata> extends BaseNode<T> {
}
}
export type IndexNodeParams<T extends Metadata = Metadata> =
TextNodeParams<T> & {
indexId: string;
};
export class IndexNode<T extends Metadata = Metadata> extends TextNode<T> {
indexId: string = "";
indexId: string;
constructor(init?: Partial<IndexNode<T>>) {
constructor(init?: IndexNodeParams<T>) {
super(init);
Object.assign(this, init);
if (new.target === IndexNode) {
this.hash = init?.hash ?? this.generateHash();
}
const { indexId } = init || {};
this.indexId = indexId ?? "";
}
getType(): ObjectType {
get type() {
return ObjectType.INDEX;
}
}
@@ -267,16 +312,11 @@ export class IndexNode<T extends Metadata = Metadata> extends TextNode<T> {
* A document is just a special text node with a docId.
*/
export class Document<T extends Metadata = Metadata> extends TextNode<T> {
constructor(init?: Partial<Document<T>>) {
constructor(init?: TextNodeParams<T>) {
super(init);
Object.assign(this, init);
if (new.target === Document) {
this.hash = init?.hash ?? this.generateHash();
}
}
getType() {
get type() {
return ObjectType.DOCUMENT;
}
}
@@ -303,21 +343,21 @@ export function jsonToNode(json: any, type?: ObjectType) {
export type ImageType = string | Blob | URL;
export type ImageNodeConstructorProps<T extends Metadata> = Pick<
ImageNode<T>,
"image" | "id_"
> &
Partial<ImageNode<T>>;
export type ImageNodeParams<T extends Metadata = Metadata> =
TextNodeParams<T> & {
image: ImageType;
};
export class ImageNode<T extends Metadata = Metadata> extends TextNode<T> {
image: ImageType; // image as blob
constructor(init: ImageNodeConstructorProps<T>) {
constructor(init: ImageNodeParams<T>) {
super(init);
this.image = init.image;
const { image } = init;
this.image = image;
}
getType(): ObjectType {
get type() {
return ObjectType.IMAGE;
}
@@ -360,15 +400,11 @@ export class ImageNode<T extends Metadata = Metadata> extends TextNode<T> {
}
export class ImageDocument<T extends Metadata = Metadata> extends ImageNode<T> {
constructor(init: ImageNodeConstructorProps<T>) {
constructor(init: ImageNodeParams<T>) {
super(init);
if (new.target === ImageDocument) {
this.hash = init?.hash ?? this.generateHash();
}
}
getType() {
get type() {
return ObjectType.IMAGE_DOCUMENT;
}
}
+1
View File
@@ -371,6 +371,7 @@ export function messagesToHistoryStr(messages: ChatMessage[]) {
}
export const defaultContextSystemPrompt = ({ context = "" }) => {
if (!context) return "";
return `Context information is below.
---------------------
${context}
+10 -7
View File
@@ -13,6 +13,11 @@ import {
setCallbackManager,
withCallbackManager,
} from "./internal/settings/CallbackManager.js";
import {
getChunkSize,
setChunkSize,
withChunkSize,
} from "./internal/settings/chunk-size.js";
import type { LLM } from "./llm/types.js";
import type { NodeParser } from "./nodeParsers/types.js";
@@ -41,14 +46,12 @@ class GlobalSettings implements Config {
#promptHelper: PromptHelper | null = null;
#embedModel: BaseEmbedding | null = null;
#nodeParser: NodeParser | null = null;
#chunkSize?: number;
#chunkOverlap?: number;
#llmAsyncLocalStorage = new AsyncLocalStorage<LLM>();
#promptHelperAsyncLocalStorage = new AsyncLocalStorage<PromptHelper>();
#embedModelAsyncLocalStorage = new AsyncLocalStorage<BaseEmbedding>();
#nodeParserAsyncLocalStorage = new AsyncLocalStorage<NodeParser>();
#chunkSizeAsyncLocalStorage = new AsyncLocalStorage<number>();
#chunkOverlapAsyncLocalStorage = new AsyncLocalStorage<number>();
#promptAsyncLocalStorage = new AsyncLocalStorage<PromptConfig>();
@@ -115,8 +118,8 @@ class GlobalSettings implements Config {
get nodeParser(): NodeParser {
if (this.#nodeParser === null) {
this.#nodeParser = new SimpleNodeParser({
chunkSize: this.#chunkSize,
chunkOverlap: this.#chunkOverlap,
chunkSize: this.chunkSize,
chunkOverlap: this.chunkOverlap,
});
}
@@ -147,15 +150,15 @@ class GlobalSettings implements Config {
}
set chunkSize(chunkSize: number | undefined) {
this.#chunkSize = chunkSize;
setChunkSize(chunkSize);
}
get chunkSize(): number | undefined {
return this.#chunkSizeAsyncLocalStorage.getStore() ?? this.#chunkSize;
return getChunkSize();
}
withChunkSize<Result>(chunkSize: number, fn: () => Result): Result {
return this.#chunkSizeAsyncLocalStorage.run(chunkSize, fn);
return withChunkSize(chunkSize, fn);
}
get chunkOverlap(): number | undefined {
+32 -48
View File
@@ -1,9 +1,4 @@
import {
ReadableStream,
TransformStream,
pipeline,
randomUUID,
} from "@llamaindex/env";
import { ReadableStream, TransformStream, randomUUID } from "@llamaindex/env";
import { Settings } from "../Settings.js";
import {
type ChatEngine,
@@ -21,7 +16,6 @@ import type {
LLM,
MessageContent,
} from "../llm/index.js";
import { extractText } from "../llm/utils.js";
import type { BaseToolWithCall, ToolOutput } from "../types.js";
import type {
AgentTaskContext,
@@ -169,7 +163,7 @@ export abstract class AgentWorker<
abstract taskHandler: TaskHandler<AI, Store, AdditionalMessageOptions>;
public createTask(
query: string,
query: MessageContent,
context: AgentTaskContext<AI, Store, AdditionalMessageOptions>,
): ReadableStream<TaskStepOutput<AI, Store, AdditionalMessageOptions>> {
context.store.messages.push({
@@ -305,7 +299,7 @@ export abstract class AgentRunner<
});
}
}
return this.#runner.createTask(extractText(message), {
return this.#runner.createTask(message, {
stream,
toolCallCount: 0,
llm: this.#llm,
@@ -340,46 +334,36 @@ export abstract class AgentRunner<
| ReadableStream<AgentStreamChatResponse<AdditionalMessageOptions>>
> {
const task = this.createTask(params.message, !!params.stream);
const stepOutput = await pipeline(
task,
async (
iter: AsyncIterable<
TaskStepOutput<AI, Store, AdditionalMessageOptions>
>,
) => {
for await (const stepOutput of iter) {
// update chat history for each round
this.#chatHistory = [...stepOutput.taskStep.context.store.messages];
if (stepOutput.isLast) {
return stepOutput;
}
}
throw new Error("Task did not complete");
},
);
const { output, taskStep } = stepOutput;
if (isAsyncIterable(output)) {
return output.pipeThrough<
AgentStreamChatResponse<AdditionalMessageOptions>
>(
new TransformStream({
transform(chunk, controller) {
controller.enqueue({
response: chunk,
get sources() {
return [...taskStep.context.store.toolOutputs];
for await (const stepOutput of task) {
// update chat history for each round
this.#chatHistory = [...stepOutput.taskStep.context.store.messages];
if (stepOutput.isLast) {
const { output, taskStep } = stepOutput;
if (isAsyncIterable(output)) {
return output.pipeThrough<
AgentStreamChatResponse<AdditionalMessageOptions>
>(
new TransformStream({
transform(chunk, controller) {
controller.enqueue({
response: chunk,
get sources() {
return [...taskStep.context.store.toolOutputs];
},
});
},
});
},
}),
);
} else {
return {
response: output,
get sources() {
return [...taskStep.context.store.toolOutputs];
},
} satisfies AgentChatResponse<AdditionalMessageOptions>;
}),
);
} else {
return {
response: output,
get sources() {
return [...taskStep.context.store.toolOutputs];
},
} satisfies AgentChatResponse<AdditionalMessageOptions>;
}
}
}
throw new Error("Task ended without a last step.");
}
}
+10 -18
View File
@@ -1,4 +1,5 @@
import { pipeline, ReadableStream } from "@llamaindex/env";
import { ReadableStream } from "@llamaindex/env";
import { Settings } from "../Settings.js";
import { stringifyJSONToMessageContent } from "../internal/utils.js";
import type {
ChatResponseChunk,
@@ -8,7 +9,6 @@ import type {
} from "../llm/index.js";
import { OpenAI } from "../llm/openai.js";
import { ObjectRetriever } from "../objects/index.js";
import { Settings } from "../Settings.js";
import type { BaseToolWithCall } from "../types.js";
import { AgentRunner, AgentWorker, type AgentParamsBase } from "./base.js";
import type { TaskHandler } from "./types.js";
@@ -130,22 +130,14 @@ export class OpenAIAgent extends AgentRunner<OpenAI> {
if (hasToolCall) {
// you need to consume the response to get the full toolCalls
const toolCalls = await pipeline(
pipStream,
async (
iter: AsyncIterable<ChatResponseChunk<ToolCallLLMMessageOptions>>,
) => {
const toolCalls = new Map<string, ToolCall | PartialToolCall>();
for await (const chunk of iter) {
if (chunk.options && "toolCall" in chunk.options) {
const toolCall = chunk.options.toolCall;
toolCalls.set(toolCall.id, toolCall);
}
}
return [...toolCalls.values()];
},
);
for (const toolCall of toolCalls) {
const toolCalls = new Map<string, ToolCall | PartialToolCall>();
for await (const chunk of pipStream) {
if (chunk.options && "toolCall" in chunk.options) {
const toolCall = chunk.options.toolCall;
toolCalls.set(toolCall.id, toolCall);
}
}
for (const toolCall of toolCalls.values()) {
const targetTool = tools.find(
(tool) => tool.metadata.name === toolCall.name,
);
@@ -12,6 +12,8 @@ import type {
LLMStreamEvent,
LLMToolCallEvent,
LLMToolResultEvent,
RetrievalEndEvent,
RetrievalStartEvent,
} from "../llm/types.js";
export class LlamaIndexCustomEvent<T = any> extends CustomEvent<T> {
@@ -45,6 +47,8 @@ export interface LlamaIndexEventMaps {
* @deprecated
*/
retrieve: CustomEvent<RetrievalCallbackResponse>;
"retrieve-start": RetrievalStartEvent;
"retrieve-end": RetrievalEndEvent;
/**
* @deprecated
*/
+17 -24
View File
@@ -1,12 +1,17 @@
import _ from "lodash";
import type { ImageType } from "../Node.js";
import { lazyLoadTransformers } from "../internal/deps/transformers.js";
import { MultiModalEmbedding } from "./MultiModalEmbedding.js";
// only import type, to avoid bundling error
import type {
CLIPTextModelWithProjection,
CLIPVisionModelWithProjection,
PreTrainedTokenizer,
Processor,
} from "@xenova/transformers";
async function readImage(input: ImageType) {
const { RawImage } = await import(
/* webpackIgnore: true */
"@xenova/transformers"
);
const { RawImage } = await lazyLoadTransformers();
if (input instanceof Blob) {
return await RawImage.fromBlob(input);
} else if (_.isString(input) || input instanceof URL) {
@@ -25,39 +30,30 @@ export class ClipEmbedding extends MultiModalEmbedding {
modelType: ClipEmbeddingModelType =
ClipEmbeddingModelType.XENOVA_CLIP_VIT_BASE_PATCH16;
private tokenizer: any;
private processor: any;
private visionModel: any;
private textModel: any;
private tokenizer: PreTrainedTokenizer | null = null;
private processor: Processor | null = null;
private visionModel: CLIPVisionModelWithProjection | null = null;
private textModel: CLIPTextModelWithProjection | null = null;
async getTokenizer() {
const { AutoTokenizer } = await lazyLoadTransformers();
if (!this.tokenizer) {
const { AutoTokenizer } = await import(
/* webpackIgnore: true */
"@xenova/transformers"
);
this.tokenizer = await AutoTokenizer.from_pretrained(this.modelType);
}
return this.tokenizer;
}
async getProcessor() {
const { AutoProcessor } = await lazyLoadTransformers();
if (!this.processor) {
const { AutoProcessor } = await import(
/* webpackIgnore: true */
"@xenova/transformers"
);
this.processor = await AutoProcessor.from_pretrained(this.modelType);
}
return this.processor;
}
async getVisionModel() {
const { CLIPVisionModelWithProjection } = await lazyLoadTransformers();
if (!this.visionModel) {
const { CLIPVisionModelWithProjection } = await import(
/* webpackIgnore: true */
"@xenova/transformers"
);
this.visionModel = await CLIPVisionModelWithProjection.from_pretrained(
this.modelType,
);
@@ -67,11 +63,8 @@ export class ClipEmbedding extends MultiModalEmbedding {
}
async getTextModel() {
const { CLIPTextModelWithProjection } = await lazyLoadTransformers();
if (!this.textModel) {
const { CLIPTextModelWithProjection } = await import(
/* webpackIgnore: true */
"@xenova/transformers"
);
this.textModel = await CLIPTextModelWithProjection.from_pretrained(
this.modelType,
);
@@ -1,3 +1,4 @@
import { lazyLoadTransformers } from "../internal/deps/transformers.js";
import { BaseEmbedding } from "./types.js";
export enum HuggingFaceEmbeddingModelType {
@@ -31,7 +32,7 @@ export class HuggingFaceEmbedding extends BaseEmbedding {
async getExtractor() {
if (!this.extractor) {
const { pipeline } = await import("@xenova/transformers");
const { pipeline } = await lazyLoadTransformers();
this.extractor = await pipeline("feature-extraction", this.modelType, {
quantized: this.quantized,
});
+1
View File
@@ -2,6 +2,7 @@ export * from "./GeminiEmbedding.js";
export * from "./JinaAIEmbedding.js";
export * from "./MistralAIEmbedding.js";
export * from "./MultiModalEmbedding.js";
export { OllamaEmbedding } from "./OllamaEmbedding.js";
export * from "./OpenAIEmbedding.js";
export { FireworksEmbedding } from "./fireworks.js";
export { TogetherEmbedding } from "./together.js";
+2 -2
View File
@@ -1,4 +1,4 @@
import { defaultFS } from "@llamaindex/env";
import { fs } from "@llamaindex/env";
import _ from "lodash";
import { filetypemime } from "magic-bytes.js";
import type { ImageType } from "../Node.js";
@@ -243,7 +243,7 @@ export async function imageToDataUrl(input: ImageType): Promise<string> {
_.isString(input)
) {
// string or file URL
const dataBuffer = await defaultFS.readFile(
const dataBuffer = await fs.readFile(
input instanceof URL ? input.pathname : input,
);
input = new Blob([dataBuffer]);
-2
View File
@@ -10,5 +10,3 @@ export {
HuggingFaceEmbedding,
HuggingFaceEmbeddingModelType,
} from "./embeddings/HuggingFaceEmbedding.js";
export { OllamaEmbedding } from "./embeddings/OllamaEmbedding.js";
export { Ollama, type OllamaParams } from "./llm/ollama.js";
+20 -20
View File
@@ -1,14 +1,8 @@
import type {
BaseNode,
Document,
Metadata,
NodeWithScore,
} from "../../Node.js";
import type { BaseNode, Document, NodeWithScore } from "../../Node.js";
import { ImageNode, ObjectType, splitNodesByType } from "../../Node.js";
import type { BaseRetriever, RetrieveParams } from "../../Retriever.js";
import type { ServiceContext } from "../../ServiceContext.js";
import {
Settings,
embedModelFromSettingsOrContext,
nodeParserFromSettingsOrContext,
} from "../../Settings.js";
@@ -25,6 +19,7 @@ import {
createDocStoreStrategy,
} from "../../ingestion/strategies/index.js";
import { wrapEventCaller } from "../../internal/context/EventCaller.js";
import { getCallbackManager } from "../../internal/settings/CallbackManager.js";
import type { BaseNodePostprocessor } from "../../postprocessors/types.js";
import type { StorageContext } from "../../storage/StorageContext.js";
import { storageContextFromDefaults } from "../../storage/StorageContext.js";
@@ -316,7 +311,7 @@ export class VectorStoreIndex extends BaseIndex<IndexDict> {
// NOTE: if the vector store keeps text,
// we only need to add image and index nodes
for (let i = 0; i < nodes.length; ++i) {
const type = nodes[i].getType();
const { type } = nodes[i];
if (
!vectorStore.storesText ||
type === ObjectType.INDEX ||
@@ -411,10 +406,16 @@ export class VectorIndexRetriever implements BaseRetriever {
this.imageSimilarityTopK = imageSimilarityTopK ?? DEFAULT_SIMILARITY_TOP_K;
}
@wrapEventCaller
async retrieve({
query,
preFilters,
}: RetrieveParams): Promise<NodeWithScore[]> {
getCallbackManager().dispatchEvent("retrieve-start", {
payload: {
query,
},
});
let nodesWithScores = await this.textRetrieve(
query,
preFilters as MetadataFilters,
@@ -422,7 +423,17 @@ export class VectorIndexRetriever implements BaseRetriever {
nodesWithScores = nodesWithScores.concat(
await this.textToImageRetrieve(query, preFilters as MetadataFilters),
);
this.sendEvent(query, nodesWithScores);
getCallbackManager().dispatchEvent("retrieve-end", {
payload: {
query,
nodes: nodesWithScores,
},
});
// send deprecated event
getCallbackManager().dispatchEvent("retrieve", {
query,
nodes: nodesWithScores,
});
return nodesWithScores;
}
@@ -459,17 +470,6 @@ export class VectorIndexRetriever implements BaseRetriever {
return this.buildNodeListFromQueryResult(result);
}
@wrapEventCaller
protected sendEvent(
query: string,
nodesWithScores: NodeWithScore<Metadata>[],
) {
Settings.callbackManager.dispatchEvent("retrieve", {
query,
nodes: nodesWithScores,
});
}
protected async buildVectorStoreQuery(
embedModel: BaseEmbedding,
query: string,
@@ -0,0 +1,60 @@
import { getEnv } from "@llamaindex/env";
import type { BaseNode } from "../../Node.js";
import { getChunkSize } from "../settings/chunk-size.js";
const emitOnce = false;
export function chunkSizeCheck(
contentGetter: () => string,
_context: ClassMethodDecoratorContext | ClassGetterDecoratorContext,
) {
return function <Node extends BaseNode>(this: Node) {
const content = contentGetter.call(this);
const chunkSize = getChunkSize();
const enableChunkSizeCheck = getEnv("ENABLE_CHUNK_SIZE_CHECK") === "true";
if (
enableChunkSizeCheck &&
chunkSize !== undefined &&
content.length > chunkSize
) {
console.warn(
`Node (${this.id_}) is larger than chunk size: ${content.length}`,
);
if (!emitOnce) {
console.warn(
"Will truncate the content if it is larger than chunk size",
);
console.warn("If you want to disable this behavior:");
console.warn(" 1. Set Settings.chunkSize = undefined");
console.warn(" 2. Set Settings.chunkSize to a larger value");
console.warn(
" 3. Change the way of splitting content into smaller chunks",
);
}
return content.slice(0, chunkSize);
}
return content;
};
}
export function lazyInitHash(
value: ClassAccessorDecoratorTarget<BaseNode, string>,
_context: ClassAccessorDecoratorContext,
): ClassAccessorDecoratorResult<BaseNode, string> {
return {
get() {
const oldValue = value.get.call(this);
if (oldValue === "") {
const hash = this.generateHash();
value.set.call(this, hash);
}
return value.get.call(this);
},
set(newValue: string) {
value.set.call(this, newValue);
},
init(value: string): string {
return value;
},
};
}
@@ -0,0 +1,15 @@
let transformer: typeof import("@xenova/transformers") | null = null;
export async function lazyLoadTransformers() {
if (!transformer) {
transformer = await import("@xenova/transformers");
}
// @ts-expect-error
if (typeof EdgeRuntime === "string") {
// there is no local file system in the edge runtime
transformer.env.allowLocalModels = false;
}
// fixme: handle cloudflare workers case here?
return transformer;
}
@@ -0,0 +1,19 @@
import { AsyncLocalStorage } from "@llamaindex/env";
const chunkSizeAsyncLocalStorage = new AsyncLocalStorage<number | undefined>();
const globalChunkSize: number | null = null;
export function getChunkSize(): number | undefined {
return globalChunkSize ?? chunkSizeAsyncLocalStorage.getStore();
}
export function setChunkSize(chunkSize: number | undefined) {
chunkSizeAsyncLocalStorage.enterWith(chunkSize);
}
export function withChunkSize<Result>(
embeddedModel: number,
fn: () => Result,
): Result {
return chunkSizeAsyncLocalStorage.run(embeddedModel, fn);
}
+30 -44
View File
@@ -139,7 +139,7 @@ class GeminiHelper {
> = {
user: "user",
system: "user",
assistant: "user",
assistant: "model",
memory: "user",
};
@@ -152,38 +152,26 @@ class GeminiHelper {
};
public static mergeNeighboringSameRoleMessages(
messages: ChatMessage[],
): ChatMessage[] {
// Gemini does not support multiple messages of the same role in a row, so we merge them
const mergedMessages: ChatMessage[] = [];
let i: number = 0;
while (i < messages.length) {
const currentMessage: ChatMessage = messages[i];
// Initialize merged content with current message content
const mergedContent: MessageContent[] = [currentMessage.content];
// Check if the next message exists and has the same role
while (
i + 1 < messages.length &&
this.ROLES_TO_GEMINI[messages[i + 1].role] ===
this.ROLES_TO_GEMINI[currentMessage.role]
) {
i++;
const nextMessage: ChatMessage = messages[i];
mergedContent.push(nextMessage.content);
}
// Create a new ChatMessage object with merged content
const mergedMessage: ChatMessage = {
role: currentMessage.role,
content: mergedContent.join("\n"),
};
mergedMessages.push(mergedMessage);
i++;
}
return mergedMessages;
messages: GeminiMessageContent[],
): GeminiMessageContent[] {
return messages.reduce(
(
result: GeminiMessageContent[],
current: GeminiMessageContent,
index: number,
) => {
if (index > 0 && messages[index - 1].role === current.role) {
result[result.length - 1].parts = [
...result[result.length - 1].parts,
...current.parts,
];
} else {
result.push(current);
}
return result;
},
[],
);
}
public static messageContentToGeminiParts(content: MessageContent): Part[] {
@@ -214,8 +202,8 @@ class GeminiHelper {
message: ChatMessage,
): GeminiMessageContent {
return {
role: this.ROLES_TO_GEMINI[message.role],
parts: this.messageContentToGeminiParts(message.content),
role: GeminiHelper.ROLES_TO_GEMINI[message.role],
parts: GeminiHelper.messageContentToGeminiParts(message.content),
};
}
}
@@ -260,22 +248,20 @@ export class Gemini extends ToolCallLLM<GeminiAdditionalChatOptions> {
chat: ChatSession;
messageContent: Part[];
} {
const { messages } = params;
const mergedMessages =
GeminiHelper.mergeNeighboringSameRoleMessages(messages);
const history = mergedMessages.slice(0, -1);
const nextMessage = mergedMessages[mergedMessages.length - 1];
const messageContent = GeminiHelper.chatMessageToGemini(nextMessage).parts;
const messages = GeminiHelper.mergeNeighboringSameRoleMessages(
params.messages.map(GeminiHelper.chatMessageToGemini),
);
const history = messages.slice(0, -1);
const client = this.session.gemini.getGenerativeModel(this.metadata);
const chat = client.startChat({
history: history.map(GeminiHelper.chatMessageToGemini),
history,
});
return {
chat,
messageContent,
messageContent: messages[messages.length - 1].parts,
};
}
+2 -1
View File
@@ -5,7 +5,7 @@ export {
Anthropic,
} from "./anthropic.js";
export { FireworksLLM } from "./fireworks.js";
export { GEMINI_MODEL, Gemini } from "./gemini.js";
export { GEMINI_MODEL, Gemini, GeminiSession } from "./gemini.js";
export { Groq } from "./groq.js";
export { HuggingFaceInferenceAPI } from "./huggingface.js";
export {
@@ -17,6 +17,7 @@ export * from "./openai.js";
export { Portkey } from "./portkey.js";
export * from "./replicate_ai.js";
// Note: The type aliases for replicate are to simplify usage for Llama 2 (we're using replicate for Llama 2 support)
export { Ollama, type OllamaParams } from "./ollama.js";
export {
ALL_AVAILABLE_REPLICATE_MODELS,
DeuceChatStrategy,
+78 -100
View File
@@ -1,11 +1,23 @@
import { BaseEmbedding } from "../embeddings/types.js";
import ollama, {
import {
Ollama as OllamaBase,
type Config,
type CopyRequest,
type CreateRequest,
type DeleteRequest,
type EmbeddingsRequest,
type EmbeddingsResponse,
type GenerateRequest,
type ListResponse,
type ChatResponse as OllamaChatResponse,
type GenerateResponse as OllamaGenerateResponse,
type Options,
type ProgressResponse,
type PullRequest,
type PushRequest,
type ShowRequest,
type ShowResponse,
type StatusResponse,
} from "../internal/deps/ollama.js";
import type {
ChatResponse,
@@ -35,15 +47,21 @@ const completionAccessor = (
export type OllamaParams = {
model: string;
config?: Partial<Config>;
options?: Partial<Options>;
};
/**
* This class both implements the LLM and Embedding interfaces.
*/
export class Ollama extends BaseEmbedding implements LLM {
export class Ollama
extends BaseEmbedding
implements LLM, Omit<OllamaBase, "chat">
{
readonly hasStreaming = true;
ollama: OllamaBase;
// https://ollama.ai/library
model: string;
@@ -57,6 +75,7 @@ export class Ollama extends BaseEmbedding implements LLM {
constructor(params: OllamaParams) {
super();
this.model = params.model;
this.ollama = new OllamaBase(params.config);
if (params.options) {
this.options = {
...this.options,
@@ -97,7 +116,7 @@ export class Ollama extends BaseEmbedding implements LLM {
},
};
if (!stream) {
const chatResponse = await ollama.chat({
const chatResponse = await this.ollama.chat({
...payload,
stream: false,
});
@@ -110,7 +129,7 @@ export class Ollama extends BaseEmbedding implements LLM {
raw: chatResponse,
};
} else {
const stream = await ollama.chat({
const stream = await this.ollama.chat({
...payload,
stream: true,
});
@@ -137,7 +156,7 @@ export class Ollama extends BaseEmbedding implements LLM {
},
};
if (!stream) {
const response = await ollama.generate({
const response = await this.ollama.generate({
...payload,
stream: false,
});
@@ -146,7 +165,7 @@ export class Ollama extends BaseEmbedding implements LLM {
raw: response,
};
} else {
const stream = await ollama.generate({
const stream = await this.ollama.generate({
...payload,
stream: true,
});
@@ -162,7 +181,7 @@ export class Ollama extends BaseEmbedding implements LLM {
...this.options,
},
};
const response = await ollama.embeddings({
const response = await this.ollama.embeddings({
...payload,
});
return response.embedding;
@@ -176,104 +195,63 @@ export class Ollama extends BaseEmbedding implements LLM {
return this.getEmbedding(query);
}
// ollama specific methods, inherited from the ollama library
static async list() {
const { models } = await ollama.list();
return models;
}
// Inherited from OllamaBase
static async detail(modelName: string, options?: Omit<ShowRequest, "model">) {
return ollama.show({
model: modelName,
...options,
});
}
static async create(
modelName: string,
options?: Omit<CreateRequest, "model"> & {
stream: false;
},
push(
request: PushRequest & { stream: true },
): Promise<AsyncGenerator<ProgressResponse, any, unknown>>;
push(
request: PushRequest & { stream?: false | undefined },
): Promise<ProgressResponse>;
static async create(
modelName: string,
options: Omit<CreateRequest, "model"> & {
stream: true;
},
push(request: any): any {
return this.ollama.push(request);
}
abort(): void {
return this.ollama.abort();
}
encodeImage(image: string | Uint8Array): Promise<string> {
return this.ollama.encodeImage(image);
}
generate(
request: GenerateRequest & { stream: true },
): Promise<AsyncGenerator<OllamaGenerateResponse>>;
generate(
request: GenerateRequest & { stream?: false | undefined },
): Promise<OllamaGenerateResponse>;
generate(request: any): any {
return this.ollama.generate(request);
}
create(
request: CreateRequest & { stream: true },
): Promise<AsyncGenerator<ProgressResponse>>;
static async create(
modelName: string,
options?: Omit<CreateRequest, "model"> & {
stream: boolean;
},
) {
return ollama.create({
model: modelName,
...options,
stream: (options ? !!options.stream : false) as never,
}) as Promise<ProgressResponse> | Promise<AsyncGenerator<ProgressResponse>>;
}
static async delete(modelName: string) {
return ollama.delete({
model: modelName,
});
}
static async copy(source: string, destination: string) {
return ollama.copy({
source,
destination,
});
}
static async pull(
modelName: string,
options?: Omit<CreateRequest, "model"> & {
stream: false;
},
create(
request: CreateRequest & { stream?: false | undefined },
): Promise<ProgressResponse>;
static async pull(
modelName: string,
options: Omit<CreateRequest, "model"> & {
stream: true;
},
): Promise<AsyncGenerator<ProgressResponse>>;
static async pull(
modelName: string,
options?: Omit<CreateRequest, "model"> & {
stream: boolean;
},
) {
return ollama.pull({
model: modelName,
...options,
stream: (options ? !!options.stream : false) as never,
}) as Promise<ProgressResponse> | Promise<AsyncGenerator<ProgressResponse>>;
create(request: any): any {
return this.ollama.create(request);
}
static async push(
modelName: string,
options?: Omit<CreateRequest, "model"> & {
stream: false;
},
): Promise<ProgressResponse>;
static async push(
modelName: string,
options: Omit<CreateRequest, "model"> & {
stream: true;
},
pull(
request: PullRequest & { stream: true },
): Promise<AsyncGenerator<ProgressResponse>>;
static async push(
modelName: string,
options?: Omit<CreateRequest, "model"> & {
stream: boolean;
},
) {
return ollama.push({
model: modelName,
...options,
stream: (options ? !!options.stream : false) as never,
}) as Promise<ProgressResponse> | Promise<AsyncGenerator<ProgressResponse>>;
pull(
request: PullRequest & { stream?: false | undefined },
): Promise<ProgressResponse>;
pull(request: any): any {
return this.ollama.pull(request);
}
delete(request: DeleteRequest): Promise<StatusResponse> {
return this.ollama.delete(request);
}
copy(request: CopyRequest): Promise<StatusResponse> {
return this.ollama.copy(request);
}
list(): Promise<ListResponse> {
return this.ollama.list();
}
show(request: ShowRequest): Promise<ShowResponse> {
return this.ollama.show(request);
}
embeddings(request: EmbeddingsRequest): Promise<EmbeddingsResponse> {
return this.ollama.embeddings(request);
}
}
+3
View File
@@ -110,6 +110,9 @@ export const GPT4_MODELS = {
"gpt-4-1106-preview": { contextWindow: 128000 },
"gpt-4-0125-preview": { contextWindow: 128000 },
"gpt-4-vision-preview": { contextWindow: 128000 },
// fixme: wait for openai documentation
"gpt-4o": { contextWindow: 128000 },
"gpt-4o-2024-05-13": { contextWindow: 128000 },
};
// NOTE we don't currently support gpt-3.5-turbo-instruct and don't plan to in the near future
+8
View File
@@ -1,7 +1,15 @@
import type { Tokenizers } from "../GlobalsHelper.js";
import type { NodeWithScore } from "../Node.js";
import type { BaseEvent } from "../internal/type.js";
import type { BaseTool, JSONObject, ToolOutput, UUID } from "../types.js";
export type RetrievalStartEvent = BaseEvent<{
query: string;
}>;
export type RetrievalEndEvent = BaseEvent<{
query: string;
nodes: NodeWithScore[];
}>;
export type LLMStartEvent = BaseEvent<{
id: UUID;
messages: ChatMessage[];
+36
View File
@@ -0,0 +1,36 @@
/**
* This is a Next.js configuration file that is used to customize the build process.
*
* @example
* ```js
* // next.config.js
* const withLlamaIndex = require("llamaindex/next")
*
* module.exports = withLlamaIndex({
* // Your Next.js configuration
* })
* ```
*
* This is only for Next.js projects, do not export this function on top-level.
*
* @module
*/
export default function withLlamaIndex(config: any) {
const userWebpack = config.webpack;
//#region hack for `@xenova/transformers`
// Ignore node-specific modules when bundling for the browser
// See https://webpack.js.org/configuration/resolve/#resolvealias
config.webpack = function (webpackConfig: any) {
if (userWebpack) {
webpackConfig = userWebpack(webpackConfig);
}
webpackConfig.resolve.alias = {
...webpackConfig.resolve.alias,
sharp$: false,
"onnxruntime-node$": false,
};
return webpackConfig;
};
//#endregion
return config;
}
+3 -7
View File
@@ -1,5 +1,4 @@
import type { GenericFileSystem } from "@llamaindex/env";
import { defaultFS } from "@llamaindex/env";
import { fs } from "@llamaindex/env";
import type { ParseConfig } from "papaparse";
import Papa from "papaparse";
import { Document } from "../Node.js";
@@ -40,11 +39,8 @@ export class PapaCSVReader implements FileReader {
* @param {GenericFileSystem} [fs=DEFAULT_FS] - The file system to use for reading the file.
* @returns {Promise<Document[]>}
*/
async loadData(
file: string,
fs: GenericFileSystem = defaultFS,
): Promise<Document[]> {
const fileContent = await fs.readFile(file);
async loadData(file: string): Promise<Document[]> {
const fileContent = await fs.readFile(file, "utf-8");
const result = Papa.parse(fileContent, this.papaConfig);
const textList = result.data.map((row: any) => {
// Compatible with header row mode
+3 -7
View File
@@ -1,16 +1,12 @@
import type { GenericFileSystem } from "@llamaindex/env";
import { defaultFS } from "@llamaindex/env";
import { fs } from "@llamaindex/env";
import mammoth from "mammoth";
import { Document } from "../Node.js";
import type { FileReader } from "./type.js";
export class DocxReader implements FileReader {
/** DocxParser */
async loadData(
file: string,
fs: GenericFileSystem = defaultFS,
): Promise<Document[]> {
const dataBuffer = await fs.readRawFile(file);
async loadData(file: string): Promise<Document[]> {
const dataBuffer = await fs.readFile(file);
const { value } = await mammoth.extractRawText({ buffer: dataBuffer });
return [new Document({ text: value, id_: file })];
}
+3 -8
View File
@@ -1,5 +1,4 @@
import type { GenericFileSystem } from "@llamaindex/env";
import { defaultFS } from "@llamaindex/env";
import { fs } from "@llamaindex/env";
import { Document } from "../Node.js";
import type { FileReader } from "./type.js";
@@ -15,14 +14,10 @@ export class HTMLReader implements FileReader {
* Public method for this reader.
* Required by BaseReader interface.
* @param file Path/name of the file to be loaded.
* @param fs fs wrapper interface for getting the file content.
* @returns Promise<Document[]> A Promise object, eventually yielding zero or one Document parsed from the HTML content of the specified file.
*/
async loadData(
file: string,
fs: GenericFileSystem = defaultFS,
): Promise<Document[]> {
const dataBuffer = await fs.readFile(file);
async loadData(file: string): Promise<Document[]> {
const dataBuffer = await fs.readFile(file, "utf-8");
const htmlOptions = this.getOptions();
const content = await this.parseContent(dataBuffer, htmlOptions);
return [new Document({ text: content, id_: file })];
+3 -7
View File
@@ -1,5 +1,4 @@
import type { GenericFileSystem } from "@llamaindex/env";
import { defaultFS } from "@llamaindex/env";
import { fs } from "@llamaindex/env";
import type { Document } from "../Node.js";
import { ImageDocument } from "../Node.js";
import type { FileReader } from "./type.js";
@@ -15,11 +14,8 @@ export class ImageReader implements FileReader {
* @param fs fs wrapper interface for getting the file content.
* @returns Promise<Document[]> A Promise object, eventually yielding zero or one ImageDocument of the specified file.
*/
async loadData(
file: string,
fs: GenericFileSystem = defaultFS,
): Promise<Document[]> {
const dataBuffer = await fs.readRawFile(file);
async loadData(file: string): Promise<Document[]> {
const dataBuffer = await fs.readFile(file);
const blob = new Blob([dataBuffer]);
return [new ImageDocument({ image: blob, id_: file })];
}
+59 -15
View File
@@ -1,8 +1,51 @@
import { defaultFS, getEnv, type GenericFileSystem } from "@llamaindex/env";
import { fs, getEnv } from "@llamaindex/env";
import { filetypemime } from "magic-bytes.js";
import { Document } from "../Node.js";
import type { FileReader, Language, ResultType } from "./type.js";
const SupportedFiles: { [key: string]: string } = {
".pdf": "application/pdf",
".doc": "application/msword",
".docx":
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
".docm": "application/vnd.ms-word.document.macroEnabled.12",
".dot": "application/msword",
".dotx":
"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
".dotm": "application/vnd.ms-word.template.macroEnabled.12",
".rtf": "application/rtf",
".wps": "application/vnd.ms-works",
".wpd": "application/wordperfect",
".sxw": "application/vnd.sun.xml.writer",
".stw": "application/vnd.sun.xml.writer.template",
".sxg": "application/vnd.sun.xml.writer.global",
".pages": "application/x-iwork-pages-sffpages",
".mw": "application/macwriteii",
".mcw": "application/macwriteii",
".uot": "application/x-uo",
".uof": "application/vnd.uoml+xml",
".uos": "application/vnd.sun.xml.calc",
".uop": "application/vnd.openofficeorg.presentation",
".ppt": "application/vnd.ms-powerpoint",
".pptx":
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
".pot": "application/vnd.ms-powerpoint",
".pptm": "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
".potx":
"application/vnd.openxmlformats-officedocument.presentationml.template",
".potm": "application/vnd.ms-powerpoint.template.macroEnabled.12",
".key": "application/x-iwork-keynote-sffkey",
".odp": "application/vnd.oasis.opendocument.presentation",
".odg": "application/vnd.oasis.opendocument.graphics",
".otp": "application/vnd.oasis.opendocument.presentation-template",
".fopd": "application/vnd.oasis.opendocument.presentation",
".sxi": "application/vnd.sun.xml.impress",
".sti": "application/vnd.sun.xml.impress.template",
".epub": "application/epub+zip",
".html": "text/html",
".htm": "text/html",
};
/**
* Represents a reader for parsing files using the LlamaParse API.
* See https://github.com/run-llama/llama_parse
@@ -36,19 +79,13 @@ export class LlamaParseReader implements FileReader {
this.apiKey = params.apiKey;
}
async loadData(
file: string,
fs: GenericFileSystem = defaultFS,
): Promise<Document[]> {
if (!file.endsWith(".pdf")) {
throw new Error("Currently, only PDF files are supported.");
}
async loadData(file: string): Promise<Document[]> {
const metadata = { file_path: file };
// Load data, set the mime type
const data = await fs.readRawFile(file);
const data = await fs.readFile(file);
const mimeType = await this.getMimeType(data);
const body = new FormData();
body.set("file", new Blob([data], { type: mimeType }), file);
body.append("language", this.language);
@@ -67,7 +104,7 @@ export class LlamaParseReader implements FileReader {
headers,
});
if (!response.ok) {
throw new Error(`Failed to parse the PDF file: ${await response.text()}`);
throw new Error(`Failed to parse the file: ${await response.text()}`);
}
const jsonResponse = await response.json();
@@ -94,7 +131,7 @@ export class LlamaParseReader implements FileReader {
const end = Date.now();
if (end - start > this.maxTimeout * 1000) {
throw new Error(
`Timeout while parsing the PDF file: ${await response.text()}`,
`Timeout while parsing the file: ${await response.text()}`,
);
}
if (this.verbose && tries % 10 === 0) {
@@ -116,9 +153,16 @@ export class LlamaParseReader implements FileReader {
private async getMimeType(data: Buffer): Promise<string> {
const mimes = filetypemime(data);
if (!mimes.includes("application/pdf")) {
throw new Error("Currently, only PDF files are supported.");
const validMime = mimes.find((mime) =>
Object.values(SupportedFiles).includes(mime),
);
if (!validMime) {
const supportedExtensions = Object.keys(SupportedFiles).join(", ");
throw new Error(
`File has type "${mimes}" which does not match supported MIME Types. Supported formats include: ${supportedExtensions}`,
);
}
return "application/pdf";
return validMime;
}
}
+9 -13
View File
@@ -1,5 +1,4 @@
import type { GenericFileSystem } from "@llamaindex/env";
import { defaultFS } from "@llamaindex/env";
import { fs } from "@llamaindex/env";
import { Document } from "../Node.js";
import type { FileReader } from "./type.js";
@@ -88,23 +87,20 @@ export class MarkdownReader implements FileReader {
return this.markdownToTups(modifiedContent);
}
async loadData(
file: string,
fs: GenericFileSystem = defaultFS,
): Promise<Document[]> {
const content = await fs.readFile(file);
async loadData(file: string): Promise<Document[]> {
const content = await fs.readFile(file, "utf-8");
const tups = this.parseTups(content);
const results: Document[] = [];
let counter = 0;
for (const [header, value] of tups) {
const id_ = `${file}_${counter}`;
if (header) {
results.push(
new Document({
text: `\n\n${header}\n${value}`,
}),
);
const text = `\n\n${header}\n${value}`;
results.push(new Document({ text, id_ }));
} else {
results.push(new Document({ text: value }));
results.push(new Document({ text: value, id_ }));
}
counter += 1;
}
return results;
}
+10 -15
View File
@@ -1,5 +1,4 @@
import type { GenericFileSystem } from "@llamaindex/env";
import { createSHA256, defaultFS } from "@llamaindex/env";
import { fs } from "@llamaindex/env";
import { Document } from "../Node.js";
import type { BaseReader } from "./type.js";
@@ -7,19 +6,15 @@ import type { BaseReader } from "./type.js";
* Read the text of a PDF
*/
export class PDFReader implements BaseReader {
async loadData(
file: string,
fs: GenericFileSystem = defaultFS,
): Promise<Document[]> {
const content = await fs.readRawFile(file);
const text = await readPDF(content);
return text.map((text) => {
const sha256 = createSHA256();
sha256.update(text);
return new Document({
text,
id_: sha256.digest(),
});
async loadData(file: string): Promise<Document[]> {
const content = await fs.readFile(file);
const pages = await readPDF(content);
return pages.map((text, page) => {
const id_ = `${file}_${page + 1}`;
const metadata = {
page_number: page + 1,
};
return new Document({ text, id_, metadata });
});
}
}
@@ -1,5 +1,4 @@
import type { CompleteFileSystem } from "@llamaindex/env";
import { defaultFS, path } from "@llamaindex/env";
import { fs, path } from "@llamaindex/env";
import { Document, type Metadata } from "../Node.js";
import { walk } from "../storage/FileSystem.js";
import { TextFileReader } from "./TextFileReader.js";
@@ -19,7 +18,6 @@ enum ReaderStatus {
export type SimpleDirectoryReaderLoadDataParams = {
directoryPath: string;
fs?: CompleteFileSystem;
defaultReader?: BaseReader | null;
fileExtToReader?: Record<string, BaseReader>;
};
@@ -45,7 +43,6 @@ export class SimpleDirectoryReader implements BaseReader {
const {
directoryPath,
fs = defaultFS,
defaultReader = new TextFileReader(),
fileExtToReader,
} = params;
@@ -58,7 +55,7 @@ export class SimpleDirectoryReader implements BaseReader {
}
const docs: Document[] = [];
for await (const filePath of walk(fs, directoryPath)) {
for await (const filePath of walk(directoryPath)) {
try {
const fileExt = path.extname(filePath).slice(1).toLowerCase();
+3 -7
View File
@@ -1,5 +1,4 @@
import type { CompleteFileSystem } from "@llamaindex/env";
import { defaultFS } from "@llamaindex/env";
import { fs } from "@llamaindex/env";
import { Document } from "../Node.js";
import type { BaseReader } from "./type.js";
@@ -8,11 +7,8 @@ import type { BaseReader } from "./type.js";
*/
export class TextFileReader implements BaseReader {
async loadData(
file: string,
fs: CompleteFileSystem = defaultFS,
): Promise<Document[]> {
const dataBuffer = await fs.readFile(file);
async loadData(file: string): Promise<Document[]> {
const dataBuffer = await fs.readFile(file, "utf-8");
return [new Document({ text: dataBuffer, id_: file })];
}
}

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