Compare commits

...

57 Commits

Author SHA1 Message Date
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
github-actions[bot] 72687b4f69 Release 0.3.5 (#805)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-03 18:16:39 -05:00
Alex Yang 0c67e1f8f3 build: fix new version script 2024-05-03 18:13:24 -05:00
Alex Yang 4a0619758a chore: fix jsr.json 2024-05-03 18:09:05 -05:00
Alex Yang bc7a11cdbe fix: inline ollama build (#807) 2024-05-03 18:03:23 -05:00
Alex Yang 5596e31947 feat: improve @llamaindex/env (#787) 2024-05-03 18:03:14 -05:00
Alex Yang 2fe2b813ba fix: filter with multiple filters in ChromaDB (#784) 2024-05-03 17:07:45 -05:00
Alex Yang be5df5b01b fix(core): multple chat on anthropic agent (#799) 2024-05-03 16:18:46 -05:00
JT-Dev-215 e74fe88342 fix: change <-> to <=> in the SELECT query (#804)
Co-authored-by: Alex Yang <himself65@outlook.com>
2024-05-03 12:10:36 -05:00
github-actions[bot] f1862ccab1 Release 0.3.4 (#797)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-02 20:02:06 -05:00
Yi Ding 9e74a4327f feat: add top k to asQueryEngine (#801)
Co-authored-by: Alex Yang <himself65@outlook.com>
2024-05-02 19:59:36 -05:00
Alex Yang 5e61934d5a fix: remove clone object in CallbackManager.dispatchEvent (#802) 2024-05-02 19:55:41 -05:00
Alex Yang 2008efe0ee feat: add verbose mode to Agent (#800) 2024-05-02 19:54:05 -05:00
Alex Yang ee719a1fda fix: streaming for ReAct Agent (#798) 2024-05-02 18:52:18 -05:00
Alex Yang 1dce275a7c fix: export StorageContext on edge runtime (#793) 2024-05-02 14:52:16 -05:00
Thuc Pham d10533ef77 feat: add hugging face llm (#796) 2024-05-02 18:43:05 +08:00
github-actions[bot] 8aeb8ae690 Release 0.3.3 (#792)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-01 21:47:16 -05:00
Thuc Pham e8c41c5c27 fix: wrong gemini streaming chat response (#791) 2024-05-02 08:39:57 +07:00
github-actions[bot] 051b4ddfa2 Release 0.3.2 (#790)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-01 19:30:09 -05:00
Alex Yang 61103b677b fix: streaming for Agent.createTask (#788) 2024-05-01 19:26:06 -05:00
Alex Yang e69cac672a docs: update blog post 2024-05-01 13:01:55 -05:00
Alex Yang 94246a3ca8 chore: bump jsr.json 2024-05-01 12:59:03 -05:00
github-actions[bot] b440a008e5 Release 0.3.1 (#786)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-01 12:39:37 -05:00
Alex Yang 46227f2a70 fix: build error on next.js nodejs runtime (#785) 2024-05-01 12:37:43 -05:00
Alex Yang 77f0298f6f chore: update jsr.json 2024-04-30 22:47:09 -05:00
github-actions[bot] c14e112236 Release 0.3.0 (#783)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-30 22:46:10 -05:00
Alex Yang 62b035fdc1 build: fix test package naming 2024-04-30 22:42:06 -05:00
Alex Yang aa0be1469b build: update expectedMinorVersion 2024-04-30 22:37:14 -05:00
Alex Yang 5016f21d52 feat(core): better next.js/cloudflare/vite support 2024-04-30 22:34:54 -05:00
Marcus Schiesser 130b7992a1 refactor: clean gemini embedding (#781) 2024-04-30 10:51:22 +07:00
Yi Ding 0d50b22dbf fix(core): add more exports on llm/index (#780) 2024-04-28 20:43:14 -05:00
Alex Yang db1d1f57c9 build(wasm-tools): fix type check 2024-04-28 20:29:01 -05:00
Alex Yang dccb8163d8 fix(core): polyfill Web Stream APIs (#777) 2024-04-28 18:35:33 -05:00
Fabian Wimmer 1ab3ba407e feat: add Language and parsingInstruction to LlamaParseReader (#779)
Co-authored-by: Alex Yang <himself65@outlook.com>
2024-04-28 17:00:58 -05:00
Alex Yang b03f765733 chore: update husky script (#776) 2024-04-27 01:10:34 -05:00
Alex Yang 7488d3c235 fix: agent callback with step infomation (#774) 2024-04-26 18:13:05 -05:00
github-actions[bot] 5cb270d07f Release 0.2.13 (#773)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-26 13:26:12 -05:00
Alex Yang 62771058aa fix: empty tools (#772) 2024-04-26 13:10:57 -05:00
github-actions[bot] ca348a6570 Release 0.2.12 (#770)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-26 13:11:23 +07:00
Marcus Schiesser 44a7fd72e8 ci: publish github release on tag pushes (#771) 2024-04-26 13:09:25 +07:00
Thuc Pham d8d952d937 feat: init gemini llm (#769) 2024-04-26 11:04:33 +07:00
220 changed files with 13810 additions and 4884 deletions
+37
View File
@@ -0,0 +1,37 @@
name: Publish to GitHub Releases
on:
push:
tags:
- "llamaindex@*"
jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
cache: "pnpm"
- name: Install dependencies
run: pnpm install
- name: Build tarball
run: |
pnpm pack
working-directory: packages/core
- name: Create release
uses: ncipollo/release-action@v1
with:
artifacts: "packages/core/llamaindex-*.tgz"
name: Release ${{ github.ref }}
bodyFile: "packages/core/CHANGELOG.md"
token: ${{ secrets.GITHUB_TOKEN }}
+16 -8
View File
@@ -69,7 +69,7 @@ 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
@@ -84,9 +84,16 @@ jobs:
name: typecheck-build-dist
path: ./packages/core/dist
if-no-files-found: error
core-edge-runtime:
e2e-core-examples:
strategy:
matrix:
packages:
- cloudflare-worker-agent
- nextjs-agent
- nextjs-edge-runtime
- waku-query-engine
runs-on: ubuntu-latest
name: Build Core Example (${{ matrix.packages }})
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
@@ -97,11 +104,12 @@ jobs:
cache: "pnpm"
- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm run build --filter @llamaindex/edge
- name: Build Edge Runtime
- name: Build llamaindex
run: pnpm run build
working-directory: ./packages/edge/e2e/test-edge-runtime
- name: Build ${{ matrix.packages }}
run: pnpm run build
working-directory: packages/core/e2e/examples/${{ matrix.packages }}
typecheck-examples:
runs-on: ubuntu-latest
@@ -116,7 +124,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
pnpm format:write
pnpm lint
npx lint-staged
-1
View File
@@ -1 +0,0 @@
pnpm test
+1 -1
View File
@@ -1 +1 @@
18
20
+140 -79
View File
@@ -19,25 +19,29 @@ Try examples online:
LlamaIndex.TS aims to be a lightweight, easy to use set of libraries to help you integrate large language models into your applications with your own data.
## Getting started with an example:
## Multiple JS Environment Support
LlamaIndex.TS requires Node v18 or higher. You can download it from https://nodejs.org or use https://nvm.sh (our preferred option).
LlamaIndex.TS supports multiple JS environments, including:
In a new folder:
- Node.js (18, 20, 22) ✅
- Deno ✅
- Bun ✅
- React Server Components (Next.js) ✅
```bash
export OPENAI_API_KEY="sk-......" # Replace with your key from https://platform.openai.com/account/api-keys
pnpm init
pnpm install typescript
pnpm exec tsc --init # if needed
For now, browser support is limited due to the lack of support for [AsyncLocalStorage-like APIs](https://github.com/tc39/proposal-async-context)
## Getting started
```shell
npm install llamaindex
pnpm install llamaindex
pnpm install @types/node
yarn add llamaindex
jsr install @llamaindex/core
```
Create the file example.ts
### Node.js
```ts
// example.ts
import fs from "fs/promises";
import { Document, VectorStoreIndex } from "llamaindex";
@@ -67,10 +71,121 @@ async function main() {
main();
```
Then you can run it using
```bash
pnpm dlx ts-node example.ts
# `pnpm install tsx` before running the script
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
// src/apps/page.tsx
"use client";
import { chatWithAgent } from "@/actions";
import type { JSX } from "react";
import { useFormState } from "react-dom";
// You can use the Edge runtime in Next.js by adding this line:
// export const runtime = "edge";
export default function Home() {
const [ui, action] = useFormState<JSX.Element | null>(async () => {
return chatWithAgent("hello!", []);
}, null);
return (
<main>
{ui}
<form action={action}>
<button>Chat</button>
</form>
</main>
);
}
```
```tsx
// src/actions/index.ts
"use server";
import { createStreamableUI } from "ai/rsc";
import { OpenAIAgent } from "llamaindex";
import type { ChatMessage } from "llamaindex/llm/types";
export async function chatWithAgent(
question: string,
prevMessages: ChatMessage[] = [],
) {
const agent = new OpenAIAgent({
tools: [
// ... adding your tools here
],
});
const responseStream = await agent.chat({
stream: true,
message: question,
chatHistory: prevMessages,
});
const uiStream = createStreamableUI(<div>loading...</div>);
responseStream
.pipeTo(
new WritableStream({
start: () => {
uiStream.update("response:");
},
write: async (message) => {
uiStream.append(message.response.delta);
},
}),
)
.catch(console.error);
return uiStream.value;
}
```
### Cloudflare Workers
```ts
// src/index.ts
export default {
async fetch(
request: Request,
env: Env,
ctx: ExecutionContext,
): Promise<Response> {
const { setEnvs } = await import("@llamaindex/env");
// set environment variables so that the OpenAIAgent can use them
setEnvs(env);
const { OpenAIAgent } = await import("llamaindex");
const agent = new OpenAIAgent({
tools: [],
});
const responseStream = await agent.chat({
stream: true,
message: "Hello? What is the weather today?",
});
const textEncoder = new TextEncoder();
const response = responseStream.pipeThrough(
new TransformStream({
transform: (chunk, controller) => {
controller.enqueue(textEncoder.encode(chunk.response.delta));
},
}),
);
return new Response(response);
},
};
```
## Playground
@@ -93,79 +208,25 @@ Check out our NextJS playground at https://llama-playground.vercel.app/. The sou
- [SimplePrompt](/packages/core/src/Prompt.ts): A simple standardized function call definition that takes in inputs and formats them in a template literal. SimplePrompts can be specialized using currying and combined using other SimplePrompt functions.
## Using NextJS
## Tips when using in non-Node.js environments
If you're using the NextJS App Router, you can choose between the Node.js and the [Edge runtime](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes#edge-runtime).
When you are importing `llamaindex` in a non-Node.js environment(such as React Server Components, Cloudflare Workers, etc.)
Some classes are not exported from top-level entry file.
With NextJS 13 and 14, using the Node.js runtime is the default. You can explicitly set the Edge runtime in your [router handler](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) by adding this line:
The reason is that some classes are only compatible with Node.js runtime,(e.g. `PDFReader`) which uses Node.js specific APIs(like `fs`, `child_process`, `crypto`).
If you need any of those classes, you have to import them instead directly though their file path in the package.
Here's an example for importing the `PineconeVectorStore` class:
```typescript
export const runtime = "edge";
```
The following sections explain further differences in using the Node.js or Edge runtime.
### Using the Node.js runtime
Add the following config to your `next.config.js` to ignore specific packages in the server-side bundling:
```js
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
serverComponentsExternalPackages: [
"pdf2json",
"@zilliz/milvus2-sdk-node",
"sharp",
"onnxruntime-node",
],
},
webpack: (config) => {
config.externals.push({
pdf2json: "commonjs pdf2json",
"@zilliz/milvus2-sdk-node": "commonjs @zilliz/milvus2-sdk-node",
sharp: "commonjs sharp",
"onnxruntime-node": "commonjs onnxruntime-node",
});
return config;
},
};
module.exports = nextConfig;
```
### Using the Edge runtime
We publish a dedicated package (`@llamaindex/edge` instead of `llamaindex`) for using the Edge runtime. To use it, first install the package:
```shell
pnpm install @llamaindex/edge
```
> _Note_: Ensure that your `package.json` doesn't include the `llamaindex` package if you're using `@llamaindex/edge`.
Then make sure to use the correct import statement in your code:
```typescript
// replace 'llamaindex' with '@llamaindex/edge'
import {} from "@llamaindex/edge";
```
A further difference is that the `@llamaindex/edge` package doesn't export classes from the `readers` or `storage` folders. The reason is that most of these classes are not compatible with the Edge runtime.
If you need any of those classes, you have to import them instead directly. Here's an example for importing the `PineconeVectorStore` class:
```typescript
import { PineconeVectorStore } from "@llamaindex/edge/storage/vectorStore/PineconeVectorStore";
import { PineconeVectorStore } from "llamaindex/storage/vectorStore/PineconeVectorStore";
```
As the `PDFReader` is not working with the Edge runtime, here's how to use the `SimpleDirectoryReader` with the `LlamaParseReader` to load PDFs:
```typescript
import { SimpleDirectoryReader } from "@llamaindex/edge/readers/SimpleDirectoryReader";
import { LlamaParseReader } from "@llamaindex/edge/readers/LlamaParseReader";
import { SimpleDirectoryReader } from "llamaindex/readers/SimpleDirectoryReader";
import { LlamaParseReader } from "llamaindex/readers/LlamaParseReader";
export const DATA_DIR = "./data";
@@ -183,7 +244,7 @@ export async function getDocuments() {
> _Note_: Reader classes have to be added explictly to the `fileExtToReader` map in the Edge version of the `SimpleDirectoryReader`.
You'll find a complete example of using the Edge runtime with LlamaIndexTS here: https://github.com/run-llama/create_llama_projects/tree/main/nextjs-edge-llamaparse
You'll find a complete example with LlamaIndexTS here: https://github.com/run-llama/create_llama_projects/tree/main/nextjs-edge-llamaparse
## Supported LLMs:
+94
View File
@@ -1,5 +1,99 @@
# docs
## 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
- Updated dependencies [bc7a11c]
- Updated dependencies [2fe2b81]
- Updated dependencies [5596e31]
- Updated dependencies [e74fe88]
- Updated dependencies [be5df5b]
- llamaindex@0.3.5
## 0.0.12
### Patch Changes
- Updated dependencies [1dce275]
- Updated dependencies [d10533e]
- Updated dependencies [2008efe]
- Updated dependencies [5e61934]
- Updated dependencies [9e74a43]
- Updated dependencies [ee719a1]
- llamaindex@0.3.4
## 0.0.11
### Patch Changes
- Updated dependencies [e8c41c5]
- llamaindex@0.3.3
## 0.0.10
### Patch Changes
- Updated dependencies [61103b6]
- llamaindex@0.3.2
## 0.0.9
### Patch Changes
- Updated dependencies [46227f2]
- llamaindex@0.3.1
## 0.0.8
### Patch Changes
- Updated dependencies [5016f21]
- llamaindex@0.3.0
## 0.0.7
### Patch Changes
- Updated dependencies [6277105]
- llamaindex@0.2.13
## 0.0.6
### Patch Changes
- Updated dependencies [d8d952d]
- llamaindex@0.2.12
## 0.0.5
### Patch Changes
+493
View File
@@ -0,0 +1,493 @@
---
title: LlamaIndexTS v0.3.0
description: This is my first post on Docusaurus.
slug: welcome-llamaindexts-v0.3
authors:
- name: Alex Yang
title: LlamaIndexTS maintainer, Node.js Member
url: https://github.com/himself65
image_url: https://github.com/himself65.png
tags: [llamaindex, agent]
hide_table_of_contents: false
---
- [What's new in LlamaIndexTS v0.3.0](#whats-new-in-llamaindexts-v030)
- [Improvement in LlamaIndexTS v0.3.0](#improvement-in-llamaindexts-v030)
- [What's the next?](#whats-the-next)
## What's new in LlamaIndexTS v0.3.0
## Agents
In this release, we've not only ported the Agent module from the LlamaIndex Python version but have significantly
enhanced it to be more powerful and user-friendly for JavaScript/TypeScript applications.
Starting from v0.3.0, we are introducing multiple agents specifically designed for RAG applications, including:
- `OpenAIAgent`
- `AnthropicAgent`
- `ReActAgent`:
```ts
import { OpenAIAgent } from "llamaindex";
import { tools } from "./tools";
const agent = new OpenAIAgent({
tools: [...tools],
});
const { response } = await agent.chat({
message: "What is weather today?",
stream: false,
});
console.log(response.message.content);
```
We are also introducing the abstract AgentRunner class, which allows you to create your own agent by simply implementing
the task handler.
```ts
import { AgentRunner, OpenAI } from "llamaindex";
class MyLLM extends OpenAI {}
export class MyAgentWorker extends AgentWorker<MyLLM> {
taskHandler = MyAgent.taskHandler;
}
export class MyAgent extends AgentRunner<MyLLM> {
constructor(params: Params) {
super({
llm: params.llm,
chatHistory: params.chatHistory ?? [],
systemPrompt: params.systemPrompt ?? null,
runner: new MyAgentWorker(),
tools:
"tools" in params
? params.tools
: params.toolRetriever.retrieve.bind(params.toolRetriever),
});
}
// create store is a function to create a store for each task, by default it only includes `messages` and `toolOutputs`
createStore = AgentRunner.defaultCreateStore;
static taskHandler: TaskHandler<Anthropic> = async (step, enqueueOutput) => {
const { llm, stream } = step.context;
// initialize the input
const response = await llm.chat({
stream,
messages: step.context.store.messages,
});
// store the response for next task step
step.context.store.messages = [
...step.context.store.messages,
response.message,
];
// your logic here to decide whether to continue the task
const shouldContinue = Math.random(); /* <-- replace with your logic here */
enqueueOutput({
taskStep: step,
output: response,
isLast: !shouldContinue,
});
if (shouldContinue) {
const content = await someHeavyFunctionCall();
// if you want to continue the task, you can insert your new context for the next task step
step.context.store.messages = [
...step.context.store.messages,
{
content,
role: "user",
},
];
}
};
}
```
### Web Stream API for Streaming response
Web Stream is a web standard utilized in many modern web frameworks and libraries (like React 19, Deno, Node 22). We
have migrated streaming responses to Web Stream to ensure broader compatibility.
For instance, you can use the streaming response in a simple HTTP Server:
```ts
import { createServer } from "http";
import { OpenAIAgent } from "llamaindex";
import { OpenAIStream, streamToResponse } from "ai";
import { tools } from "./tools";
const agent = new OpenAIAgent({
tools: [...tools],
});
const server = createServer(async (req, res) => {
const response = await agent.chat({
message: "What is weather today?",
stream: true,
});
// Transform the response into a string readable stream
const stream: ReadableStream<string> = response.pipeThrough(
new TransformStream({
transform: (chunk, controller) => {
controller.enqueue(chunk.response.delta);
},
}),
);
// Pipe the stream to the response
streamToResponse(stream, res);
});
server.listen(3000);
```
Or it can be integrated into React Server Components (RSC) in Next.js:
```tsx
// app/actions/index.tsx
"use server";
import { createStreamableUI } from "ai/rsc";
import { OpenAIAgent } from "llamaindex";
import type { ChatMessage } from "llamaindex/llm/types";
export async function chatWithAgent(
question: string,
prevMessages: ChatMessage[] = [],
) {
const agent = new OpenAIAgent({
tools: [],
});
const responseStream = await agent.chat({
stream: true,
message: question,
chatHistory: prevMessages,
});
const uiStream = createStreamableUI(<div>loading...</div>);
responseStream
.pipeTo(
new WritableStream({
start: () => {
uiStream.update("response:");
},
write: async (message) => {
uiStream.append(message.response.delta);
},
}),
)
.catch(uiStream.error);
return uiStream.value;
}
```
```tsx
// app/src/page.tsx
"use client";
import { chatWithAgent } from "@/actions";
import type { JSX } from "react";
import { useFormState } from "react-dom";
export const runtime = "edge";
export default function Home() {
const [state, action] = useFormState<JSX.Element | null>(async () => {
return chatWithAgent("hello!", []);
}, null);
return (
<main>
{state}
<form action={action}>
<button>Chat</button>
</form>
</main>
);
}
```
## Improvement in LlamaIndexTS v0.3.0
### Better TypeScript support
We have made significant improvements to the type system to ensure that all code is thoroughly checked before it is
published. This ongoing enhancement has already resulted in better module reliability and developer experience.
For example, we have improved `FunctionTool` type with generic support:
```ts
type Input = {
a: number;
b: number;
};
const sumNumbers = FunctionTool.from<Input>(
({ a, b }) => `${a + b}`, // a and b will be checked as number
// JSON schema will be an error if you type wrong.
{
name: "sumNumbers",
description: "Use this function to sum two numbers",
parameters: {
type: "object",
properties: {
a: {
type: "number",
description: "The first number",
},
b: {
type: "number",
description: "The second number",
},
},
required: ["a", "b"],
},
},
);
```
![type checking](./img/function_tool_example.png)
### Better Next.js, Deno, Cloudflare Worker, and Waku(Vite) support
In addition to Node.js, LlamaIndexTS now offers enhanced support for Next.js, Deno, and Cloudflare Workers, making it
more versatile across different platforms.
For now, you can install llamaindex and directly import it into your existing Next.js, Deno or Cloudflare Worker project
**without any extra configuration**.
#### [Deno](https://deno.com/)
You can use LlamaIndexTS in Deno by installation through JSR:
```sh
jsr add @llamaindex/core
```
#### [Cloudflare Worker](https://developers.cloudflare.com/workers/)
For Cloudflare Workers, here is a starter template:
```typescript
export default {
async fetch(
request: Request,
env: Env,
ctx: ExecutionContext,
): Promise<Response> {
const { setEnvs } = await import("@llamaindex/env");
setEnvs(env);
const { OpenAIAgent } = await import("llamaindex");
const agent = new OpenAIAgent({
tools: [],
});
const responseStream = await agent.chat({
stream: true,
message: "Hello? What is the weather today?",
});
const textEncoder = new TextEncoder();
const response = responseStream.pipeThrough(
new TransformStream({
transform: (chunk, controller) => {
controller.enqueue(textEncoder.encode(chunk.response.delta));
},
}),
);
return new Response(response);
},
};
```
### [Waku (Vite)](https://waku.gg/)
Waku powered by Vite is a minimal React framework that supports multiple JS environments, including Deno, Cloudflare, and
Node.js.
You can use LlamaIndexTS with Node.js output to enable full Node.js support with React.
```sh
npm install llamaindex
```
```ts
// file: src/actions.ts
"use server";
import { Document, VectorStoreIndex } from "llamaindex";
import { readFile } from "node:fs/promises";
const path = "node_modules/llamaindex/examples/abramov.txt";
const essay = await readFile(path, "utf-8");
// Create Document object with essay
const document = new Document({ text: essay, id_: path });
// Split text and create embeddings. Store them in a VectorStoreIndex
const index = await VectorStoreIndex.fromDocuments([document]);
const queryEngine = index.asQueryEngine();
export async function chatWithAI(question: string): Promise<string> {
const { response } = await queryEngine.query({ query: question });
return response;
}
```
```tsx
// file: src/pages/index.tsx
import { chatWithAI } from "./actions";
export default async function HomePage() {
return (
<div>
<Chat askQuestion={chatWithAI} />
</div>
);
}
```
```tsx
// file: src/components/Chat.tsx
"use client";
export type ChatProps = {
askQuestion: (question: string) => Promise<string>;
};
export const Chat = (props: ChatProps) => {
const [response, setResponse] = useState<string | null>(null);
return (
<section className="border-blue-400 -mx-4 mt-4 rounded border border-dashed p-4">
<h2 className="text-lg font-bold">Chat with AI</h2>
{response ? (
<p className="text-sm text-gray-600 max-w-sm">{response}</p>
) : null}
<form
action={async (formData) => {
const question = formData.get("question") as string | null;
if (question) {
setResponse(await props.askQuestion(question));
}
}}
>
<input
type="text"
name="question"
className="border border-gray-400 rounded-sm px-2 py-0.5 text-sm"
/>
<button className="rounded-sm bg-black px-2 py-0.5 text-sm text-white">
Ask
</button>
</form>
</section>
);
};
```
```shell
waku dev # development mode
waku build # build for production
waku start # start the production server
```
Note that not all the modules are supported in all JS environments because of
lack of the file system, network API,
and incompatibility with the Node.js API by upstream dependencies.
But we are trying to make it more compatible with all the environments.
## What's the next?
As we continue to develop LlamaIndexTS, our focus remains on providing more comprehensive and powerful tools for
creating custom agents.
### Align with the Python `llama-index`
We aim to align LlamaIndexTS with the Python version to ensure API consistency and ease of use for developers familiar
with the Python ecosystem.
### Align with the Web Standard and JS development
Not all python APIs are compatible and easy to use in JavaScript/TypeScript.
We are trying to make the API more compatible with the Web Standard and JavaScript modern development.
### More Agents
Future releases will introduce more agents from the Python Llama-Index and explore APIs tailored to real-world use
cases.
### 🧪 `@llamaindex/tool`
We are exploring innovative ways to create tools for agents. The `@llamaindex/tool` library allows you to transform any
function into a tool for an agent, simplifying the development process and reducing runtime costs.
```ts
export function getWeather(city: string) {
return `The weather in ${city} is sunny.`;
}
// you don't need to worry about the shcema with different llm tools
export function getTemperature(city: string) {
return `The temperature in ${city} is 25°C.`;
}
export function getCurrentCity() {
return "New York";
}
```
These functions can be easily integrated into your applications, such as Next.js:
```ts
"use server";
import { OpenAI } from "openai";
import { getTools } from "@llamaindex/tool";
export async function chat(message: string) {
const openai = new OpenAI();
openai.chat.completions.create({
messages: [
{
role: "user",
content: "What is the weather in the current city?",
},
],
tools: getTools("openai"),
});
}
```
```ts
// next.config.js
const withTool = require("@llamaindex/tool/next");
const config = {
// Your original Next.js config
};
module.exports = withTool(config);
```
The functions are automatically transformed into tools for the agent at compile time, which eliminates any extra runtime
costs. This feature is particularly beneficial when you need to debug or deploy your assistant.
For deploying your local functions into OpenAI, you can use a simple command:
```sh
npm install -g @llamaindex/tool
mkai --tools ./src/index.llama.ts
# Successfully created assistant: asst_XXX
# chat with your assistant by `chatai --assistant asst_XXX`
chatai --assistant asst_XXX
# Open your browser and chat with your assistant
# Running at http://localhost:3000
```
This deployment process simplifies the testing and implementation of your custom tools in a live environment.
As this project is still in its early stages, we continue to explore the best ways to create and integrate tools for
agents. For more information and updates, visit the @llamaindex/tool repository.
This release of LlamaIndexTS v0.3.0 marks a significant step forward in our journey to provide developers with robust,
flexible tools for building advanced agents. We are excited to see how our community utilizes these new capabilities to
create innovative solutions and look forward to continuing to support and enhance LlamaIndexTS in future updates.
Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

@@ -0,0 +1,33 @@
# Gemini
To use Gemini embeddings, you need to import `GeminiEmbedding` from `llamaindex`.
```ts
import { GeminiEmbedding, Settings } from "llamaindex";
// Update Embed Model
Settings.embedModel = new GeminiEmbedding();
const document = new Document({ text: essay, id_: "essay" });
const index = await VectorStoreIndex.fromDocuments([document]);
const queryEngine = index.asQueryEngine();
const query = "What is the meaning of life?";
const results = await queryEngine.query({
query,
});
```
Per default, `GeminiEmbedding` is using the `gemini-pro` model. You can change the model by passing the `model` parameter to the constructor.
For example:
```ts
import { GEMINI_MODEL, GeminiEmbedding } from "llamaindex";
Settings.embedModel = new GeminiEmbedding({
model: GEMINI_MODEL.GEMINI_PRO_LATEST,
});
```
@@ -0,0 +1,71 @@
# Gemini
## Usage
```ts
import { Gemini, Settings, GEMINI_MODEL } from "llamaindex";
Settings.llm = new Gemini({
model: GEMINI_MODEL.GEMINI_PRO,
});
```
## Load and index documents
For this example, we will use a single document. In a real-world scenario, you would have multiple documents to index.
```ts
const document = new Document({ text: essay, id_: "essay" });
const index = await VectorStoreIndex.fromDocuments([document]);
```
## Query
```ts
const queryEngine = index.asQueryEngine();
const query = "What is the meaning of life?";
const results = await queryEngine.query({
query,
});
```
## Full Example
```ts
import {
Gemini,
Document,
VectorStoreIndex,
Settings,
GEMINI_MODEL,
} from "llamaindex";
Settings.llm = new Gemini({
model: GEMINI_MODEL.GEMINI_PRO,
});
async function main() {
const document = new Document({ text: essay, id_: "essay" });
// Load and index documents
const index = await VectorStoreIndex.fromDocuments([document]);
// Create a query engine
const queryEngine = index.asQueryEngine({
retriever,
});
const query = "What is the meaning of life?";
// Query
const response = await queryEngine.query({
query,
});
// Log the response
console.log(response.response);
}
```
+6 -1
View File
@@ -66,7 +66,11 @@ const config = {
[require("@docusaurus/remark-plugin-npm2yarn"), { sync: true }],
],
},
blog: false,
blog: {
blogTitle: "LlamaIndexTS blog",
blogDescription: "The official blog of LlamaIndexTS",
postsPerPage: "ALL",
},
gtag: {
trackingID: "G-NB9B8LW9W5",
anonymizeIP: true,
@@ -97,6 +101,7 @@ const config = {
type: "localeDropdown",
position: "left",
},
{ to: "blog", label: "Blog", position: "right" },
{
href: "https://github.com/run-llama/LlamaIndexTS",
label: "GitHub",
+14 -14
View File
@@ -1,6 +1,6 @@
{
"name": "docs",
"version": "0.0.5",
"version": "0.0.17",
"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": [
+1
View File
@@ -0,0 +1 @@
DEBUG=llamaindex
+39
View File
@@ -0,0 +1,39 @@
import { ChatResponseChunk, OpenAIAgent } from "llamaindex";
import { ReadableStream } from "node:stream/web";
import {
getCurrentIDTool,
getUserInfoTool,
getWeatherTool,
} from "./utils/tools";
async function main() {
// Create an OpenAIAgent with the function tools
const agent = new OpenAIAgent({
tools: [getCurrentIDTool, getUserInfoTool, getWeatherTool],
});
const task = await agent.createTask(
"What is my current address weather based on my profile?",
true,
);
for await (const stepOutput of task) {
const stream = stepOutput.output as ReadableStream<ChatResponseChunk>;
if (stepOutput.isLast) {
for await (const chunk of stream) {
process.stdout.write(chunk.delta);
}
process.stdout.write("\n");
} else {
// handing function call
console.log("handling function call...");
for await (const chunk of stream) {
console.log("debug:", JSON.stringify(chunk.raw));
}
}
}
}
void main().then(() => {
console.log("Done");
});
+1 -1
View File
@@ -53,7 +53,7 @@ async function main() {
message: "How much is 5 + 5? then divide by 2",
});
console.log(String(response));
console.log(response.response.message);
}
void main().then(() => {
+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(() => {
+40
View File
@@ -0,0 +1,40 @@
import { ChatResponseChunk, ReActAgent } from "llamaindex";
import { ReadableStream } from "node:stream/web";
import {
getCurrentIDTool,
getUserInfoTool,
getWeatherTool,
} from "./utils/tools";
async function main() {
// Create an OpenAIAgent with the function tools
const agent = new ReActAgent({
tools: [getCurrentIDTool, getUserInfoTool, getWeatherTool],
});
const task = await agent.createTask(
"What is my current address weather based on my profile?",
true,
);
for await (const stepOutput of task) {
const stream = stepOutput.output as ReadableStream<ChatResponseChunk>;
if (stepOutput.isLast) {
for await (const chunk of stream) {
process.stdout.write(chunk.delta);
}
process.stdout.write("\n");
} else {
// handing function call
console.log("handling function call...");
for await (const chunk of stream) {
console.log("debug:", JSON.stringify(chunk.raw));
}
}
console.log("---");
}
}
void main().then(() => {
console.log("Done");
});
+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");
});
-83
View File
@@ -1,83 +0,0 @@
import { FunctionTool, OpenAIAgent } from "llamaindex";
// Define a function to sum two numbers
function sumNumbers({ a, b }: { a: number; b: number }) {
return `${a + b}`;
}
// Define a function to divide two numbers
function divideNumbers({ a, b }: { a: number; b: number }) {
return `${a / b}`;
}
// Define the parameters of the sum function as a JSON schema
const sumJSON = {
type: "object",
properties: {
a: {
type: "number",
description: "The first number",
},
b: {
type: "number",
description: "The second number",
},
},
required: ["a", "b"],
} as const;
const divideJSON = {
type: "object",
properties: {
a: {
type: "number",
description: "The dividend",
},
b: {
type: "number",
description: "The divisor",
},
},
required: ["a", "b"],
} as const;
async function main() {
// Create a function tool from the sum function
const functionTool = new FunctionTool(sumNumbers, {
name: "sumNumbers",
description: "Use this function to sum two numbers",
parameters: sumJSON,
});
// Create a function tool from the divide function
const functionTool2 = new FunctionTool(divideNumbers, {
name: "divideNumbers",
description: "Use this function to divide two numbers",
parameters: divideJSON,
});
// Create an OpenAIAgent with the function tools
const agent = new OpenAIAgent({
tools: [functionTool, functionTool2],
});
// Create a task to sum and divide numbers
const task = await agent.createTask("How much is 5 + 5? then divide by 2");
let count = 0;
for await (const stepOutput of task) {
console.log(`Runnning step ${count++}`);
console.log(`======== OUTPUT ==========`);
console.log(stepOutput.output.message.content);
console.log(`==========================`);
if (stepOutput.isLast) {
console.log(stepOutput.output.message.content);
}
}
}
void main().then(() => {
console.log("Done");
});
+6 -2
View File
@@ -66,8 +66,12 @@ async function main() {
stream: true,
});
for await (const chunk of stream.response) {
process.stdout.write(chunk.response);
console.log("Response:");
for await (const {
response: { delta },
} of stream) {
process.stdout.write(delta);
}
}
+54
View File
@@ -0,0 +1,54 @@
import { FunctionTool } from "llamaindex";
export const getCurrentIDTool = FunctionTool.from(
() => {
console.log("Getting user id...");
return crypto.randomUUID();
},
{
name: "get_user_id",
description: "Get a random user id",
},
);
export const getUserInfoTool = FunctionTool.from(
({ userId }: { userId: string }) => {
console.log("Getting user info...", userId);
return `Name: Alex; Address: 1234 Main St, CA; User ID: ${userId}`;
},
{
name: "get_user_info",
description: "Get user info",
parameters: {
type: "object",
properties: {
userId: {
type: "string",
description: "The user id",
},
},
required: ["userId"],
},
},
);
export const getWeatherTool = FunctionTool.from(
({ address }: { address: string }) => {
console.log("Getting weather...", address);
return `${address} is in a sunny location!`;
},
{
name: "get_weather",
description: "Get the current weather for a location",
parameters: {
type: "object",
properties: {
address: {
type: "string",
description: "The address",
},
},
required: ["address"],
},
},
);
+4 -2
View File
@@ -16,8 +16,10 @@ async function main() {
stream: true,
});
for await (const chunk of response.response) {
process.stdout.write(chunk.response);
for await (const {
response: { delta },
} of response) {
process.stdout.write(delta);
}
}
Binary file not shown.
+21
View File
@@ -0,0 +1,21 @@
import { Gemini, GEMINI_MODEL } from "llamaindex";
(async () => {
if (!process.env.GOOGLE_API_KEY) {
throw new Error("Please set the GOOGLE_API_KEY environment variable.");
}
const gemini = new Gemini({
model: GEMINI_MODEL.GEMINI_PRO,
});
const result = await gemini.chat({
messages: [
{ content: "You want to talk in rhymes.", role: "system" },
{
content:
"How much wood would a woodchuck chuck if a woodchuck could chuck wood?",
role: "user",
},
],
});
console.log(result);
})();
+15
View File
@@ -0,0 +1,15 @@
import { GEMINI_EMBEDDING_MODEL, GeminiEmbedding } from "llamaindex";
async function main() {
if (!process.env.GOOGLE_API_KEY) {
throw new Error("Please set the GOOGLE_API_KEY environment variable.");
}
const embedModel = new GeminiEmbedding({
model: GEMINI_EMBEDDING_MODEL.EMBEDDING_001,
});
const texts = ["hello", "world"];
const embeddings = await embedModel.getTextEmbeddingsBatch(texts);
console.log(`\nWe have ${embeddings.length} embeddings`);
}
main().catch(console.error);
+22
View File
@@ -0,0 +1,22 @@
import { HuggingFaceInferenceAPI } from "llamaindex";
(async () => {
if (!process.env.HUGGING_FACE_TOKEN) {
throw new Error("Please set the HUGGING_FACE_TOKEN environment variable.");
}
const hf = new HuggingFaceInferenceAPI({
accessToken: process.env.HUGGING_FACE_TOKEN,
model: "mistralai/Mixtral-8x7B-Instruct-v0.1",
});
const result = await hf.chat({
messages: [
{ content: "You want to talk in rhymes.", role: "system" },
{
content:
"How much wood would a woodchuck chuck if a woodchuck could chuck wood?",
role: "user",
},
],
});
console.log(result);
})();
+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({
+7 -7
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",
"@pinecone-database/pinecone": "^2.2.0",
"@zilliz/milvus2-sdk-node": "^2.4.2",
"chromadb": "^1.8.1",
"commander": "^11.1.0",
"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": {
+4 -3
View File
@@ -10,14 +10,15 @@
"start:markdown": "node --import tsx ./src/markdown.ts",
"start:pdf": "node --import tsx ./src/pdf.ts",
"start:llamaparse": "node --import tsx ./src/llamaparse.ts",
"start:notion": "node --import tsx ./src/notion.ts"
"start:notion": "node --import tsx ./src/notion.ts",
"start:llamaparse2": "node --import tsx ./src/llamaparse_2.ts"
},
"dependencies": {
"llamaindex": "*"
},
"devDependencies": {
"@types/node": "^20.12.7",
"tsx": "^4.7.2",
"@types/node": "^20.12.11",
"tsx": "^4.9.3",
"typescript": "^5.4.5"
}
}
+26
View File
@@ -0,0 +1,26 @@
import fs from "fs/promises";
import { LlamaParseReader } from "llamaindex";
async function main() {
// Load PDF using LlamaParse. set apiKey here or in environment variable LLAMA_CLOUD_API_KEY
const reader = new LlamaParseReader({
resultType: "markdown",
language: "en",
parsingInstruction:
"The provided document is a manga comic book. Most pages do NOT have title. It does not contain tables. Try to reconstruct the dialogue happening in a cohesive way. Output any math equation in LATEX markdown (between $$)",
});
const documents = await reader.loadData("../data/manga.pdf"); // The manga.pdf in the data folder is just a copy of the TOS, due to copyright laws. You have to place your own. I used "The Manga Guide to Calculus" by Hiroyuki Kojima
// Assuming documents contain an array of pages or sections
const parsedManga = documents.map((page) => page.text).join("\n---\n");
// Output the parsed manga to .md file. Will be placed in ../example/readers/
try {
await fs.writeFile("./parsedManga.md", parsedManga);
console.log("Output successfully written to parsedManga.md");
} catch (err) {
console.error("Error writing to file:", err);
}
}
main().catch(console.error);
+1
View File
@@ -8,6 +8,7 @@
"strict": true,
"skipLibCheck": true,
"lib": ["ES2022"],
"types": ["node"],
"outDir": "./lib",
"tsBuildInfoFile": "./lib/.tsbuildinfo",
"incremental": true,
+9 -9
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\"",
"build": "turbo run build --filter=\"!docs\" --filter=\"!*-test\"",
"build:release": "turbo run build lint test --filter=\"!docs\" --filter=\"!*-test\"",
"dev": "turbo run dev",
"format": "prettier --ignore-unknown --cache --check .",
"format:write": "prettier --ignore-unknown --write .",
@@ -15,22 +15,22 @@
"release": "pnpm run check-minor-version && pnpm run build:release && changeset publish",
"release-snapshot": "pnpm run check-minor-version && pnpm run build:release && changeset publish --tag snapshot",
"check-minor-version": "node ./scripts/check-minor-version",
"new-version": "changeset version && pnpm run check-minor-version && pnpm run build:release",
"new-version": "changeset version && pnpm run check-minor-version && pnpm format:write && pnpm run build:release",
"new-snapshot": "pnpm run build:release && changeset version --snapshot"
},
"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",
"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,9 @@
# @llamaindex/autotool-01-node-example
## 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,9 @@
# @llamaindex/autotool-02-next-example
## 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.1",
"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"]
}
+78
View File
@@ -0,0 +1,78 @@
{
"name": "@llamaindex/autotool",
"type": "module",
"version": "0.0.1",
"description": "",
"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.9",
"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"
}
]
}
+2 -1
View File
@@ -1,3 +1,4 @@
.turbo
/README.md
LICENSE
LICENSE
*.tgz
+94
View File
@@ -1,5 +1,99 @@
# llamaindex
## 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
- bc7a11c: fix: inline ollama build
- 2fe2b81: fix: filter with multiple filters in ChromaDB
- 5596e31: feat: improve `@llamaindex/env`
- e74fe88: fix: change <-> to <=> in the SELECT query
- be5df5b: fix: anthropic agent on multiple chat
- Updated dependencies [5596e31]
- @llamaindex/env@0.1.1
## 0.3.4
### Patch Changes
- 1dce275: fix: export `StorageContext` on edge runtime
- d10533e: feat: add hugging face llm
- 2008efe: feat: add verbose mode to Agent
- 5e61934: fix: remove clone object in `CallbackManager.dispatchEvent`
- 9e74a43: feat: add top k to `asQueryEngine`
- ee719a1: fix: streaming for ReAct Agent
## 0.3.3
### Patch Changes
- e8c41c5: fix: wrong gemini streaming chat response
## 0.3.2
### Patch Changes
- 61103b6: fix: streaming for `Agent.createTask` API
## 0.3.1
### Patch Changes
- 46227f2: fix: build error on next.js nodejs runtime
## 0.3.0
### Minor Changes
- 5016f21: feat: improve next.js/cloudflare/vite support
### Patch Changes
- Updated dependencies [5016f21]
- @llamaindex/env@0.1.0
## 0.2.13
### Patch Changes
- 6277105: fix: allow passing empty tools to llms
## 0.2.12
### Patch Changes
- d8d952d: feat: add gemini llm and embedding
## 0.2.11
### Patch Changes
+21
View File
@@ -0,0 +1,21 @@
# @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
- be5df5b: fix: anthropic agent on multiple chat
## 0.0.3
### Patch Changes
- 61103b6: fix: streaming for `Agent.createTask` API
+4
View File
@@ -0,0 +1,4 @@
# Examples
This directory contains examples of how to use the core package.
Each example is not for production use, but rather to show how to use the core package at minimum.
@@ -0,0 +1,172 @@
# Logs
logs
_.log
npm-debug.log_
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
# Runtime data
pids
_.pid
_.seed
\*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
\*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
\*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
\*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.\*
# wrangler project
.dev.vars
.wrangler/
@@ -0,0 +1,81 @@
# @llamaindex/cloudflare-worker-agent-test
## 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
- Updated dependencies [bc7a11c]
- Updated dependencies [2fe2b81]
- Updated dependencies [5596e31]
- Updated dependencies [e74fe88]
- Updated dependencies [be5df5b]
- llamaindex@0.3.5
## 0.0.5
### Patch Changes
- Updated dependencies [1dce275]
- Updated dependencies [d10533e]
- Updated dependencies [2008efe]
- Updated dependencies [5e61934]
- Updated dependencies [9e74a43]
- Updated dependencies [ee719a1]
- llamaindex@0.3.4
## 0.0.4
### Patch Changes
- Updated dependencies [e8c41c5]
- llamaindex@0.3.3
## 0.0.3
### Patch Changes
- Updated dependencies [61103b6]
- llamaindex@0.3.2
## 0.0.2
### Patch Changes
- Updated dependencies [46227f2]
- llamaindex@0.3.1
## 0.0.1
### Patch Changes
- Updated dependencies [5016f21]
- llamaindex@0.3.0
@@ -0,0 +1,26 @@
{
"name": "@llamaindex/cloudflare-worker-agent-test",
"version": "0.0.10",
"type": "module",
"private": true,
"scripts": {
"deploy": "wrangler deploy",
"dev": "wrangler dev",
"build": "wrangler deploy --dry-run --outdir dist",
"start": "wrangler dev",
"test": "vitest",
"cf-typegen": "wrangler types"
},
"devDependencies": {
"@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.53.1"
},
"dependencies": {
"llamaindex": "workspace:*"
}
}
@@ -0,0 +1,29 @@
export default {
async fetch(
request: Request,
env: Env,
ctx: ExecutionContext,
): Promise<Response> {
const { setEnvs } = await import("@llamaindex/env");
setEnvs(env);
const { OpenAIAgent } = await import("llamaindex");
const agent = new OpenAIAgent({
tools: [],
});
const responseStream = await agent.chat({
stream: true,
message: "Hello? What is the weather today?",
});
const textEncoder = new TextEncoder();
const response = responseStream.pipeThrough<Uint8Array>(
// @ts-expect-error: see https://github.com/cloudflare/workerd/issues/2067
new TransformStream({
transform: (chunk, controller) => {
controller.enqueue(textEncoder.encode(chunk.response.delta));
},
}),
);
// @ts-expect-error: see https://github.com/cloudflare/workerd/issues/2067
return new Response(response);
},
};
@@ -0,0 +1,23 @@
import {
createExecutionContext,
env,
waitOnExecutionContext,
} from "cloudflare:test";
import { describe, expect, it } from "vitest";
import worker from "../src/index";
const IncomingRequest = Request<unknown, IncomingRequestCfProperties>;
describe("Hello World worker", () => {
// FIXME: https://github.com/cloudflare/workers-sdk/issues/5646
it.fails("responds with Hello World! (unit style)", async () => {
const request = new IncomingRequest("http://example.com");
// Create an empty context to pass to `worker.fetch()`.
const ctx = createExecutionContext();
const response = await worker.fetch(request, env, ctx);
// Wait for all `Promise`s passed to `ctx.waitUntil()` to settle before running test assertions
await waitOnExecutionContext(ctx);
// fixme: should be not "Hello World!"
expect(await response.text()).toMatchInlineSnapshot(`"Hello World!"`);
});
});
@@ -0,0 +1,11 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"types": [
"@cloudflare/workers-types/experimental",
"@cloudflare/vitest-pool-workers"
]
},
"include": ["./**/*.ts", "../src/env.d.ts"],
"exclude": []
}
@@ -0,0 +1,106 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
// "incremental": true, /* Enable incremental compilation */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"lib": [
"es2021"
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
"jsx": "react" /* Specify what JSX code is generated. */,
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "es2022" /* Specify what module code is generated. */,
// "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "Bundler" /* Specify how TypeScript looks up a file from a given module specifier. */,
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
"types": [
"@cloudflare/workers-types/2023-07-01"
] /* Specify type package names to be included without being referenced in a source file. */,
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
"resolveJsonModule": true /* Enable importing .json files */,
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
"allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */,
"checkJs": false /* Enable error reporting in type-checked JavaScript files. */,
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
"noEmit": true /* Disable emitting files from a compilation. */,
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
"isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */,
"allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */,
// "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"exclude": ["test"]
}
@@ -0,0 +1,11 @@
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
export default defineWorkersConfig({
test: {
poolOptions: {
workers: {
wrangler: { configPath: "./wrangler.toml" },
},
},
},
});
@@ -0,0 +1,3 @@
// Generated by Wrangler
// After adding bindings to `wrangler.toml`, regenerate this interface via `npm run cf-typegen`
interface Env {}
@@ -0,0 +1,108 @@
#:schema node_modules/wrangler/config-schema.json
name = "agent"
main = "src/index.ts"
compatibility_date = "2024-04-23"
compatibility_flags = ["nodejs_compat"]
# Automatically place your workloads in an optimal location to minimize latency.
# If you are running back-end logic in a Worker, running it closer to your back-end infrastructure
# rather than the end user may result in better performance.
# Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
# [placement]
# mode = "smart"
# Variable bindings. These are arbitrary, plaintext strings (similar to environment variables)
# Docs:
# - https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
# Note: Use secrets to store sensitive data.
# - https://developers.cloudflare.com/workers/configuration/secrets/
# [vars]
# MY_VARIABLE = "production_value"
# Bind the Workers AI model catalog. Run machine learning models, powered by serverless GPUs, on Cloudflares global network
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#workers-ai
# [ai]
# binding = "AI"
# Bind an Analytics Engine dataset. Use Analytics Engine to write analytics within your Pages Function.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#analytics-engine-datasets
# [[analytics_engine_datasets]]
# binding = "MY_DATASET"
# Bind a headless browser instance running on Cloudflare's global network.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#browser-rendering
# [browser]
# binding = "MY_BROWSER"
# Bind a D1 database. D1 is Cloudflares native serverless SQL database.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases
# [[d1_databases]]
# binding = "MY_DB"
# database_name = "my-database"
# database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# Bind a dispatch namespace. Use Workers for Platforms to deploy serverless functions programmatically on behalf of your customers.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#dispatch-namespace-bindings-workers-for-platforms
# [[dispatch_namespaces]]
# binding = "MY_DISPATCHER"
# namespace = "my-namespace"
# Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model.
# Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects
# [[durable_objects.bindings]]
# name = "MY_DURABLE_OBJECT"
# class_name = "MyDurableObject"
# Durable Object migrations.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#migrations
# [[migrations]]
# tag = "v1"
# new_classes = ["MyDurableObject"]
# Bind a Hyperdrive configuration. Use to accelerate access to your existing databases from Cloudflare Workers.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#hyperdrive
# [[hyperdrive]]
# binding = "MY_HYPERDRIVE"
# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Bind a KV Namespace. Use KV as persistent storage for small key-value pairs.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#kv-namespaces
# [[kv_namespaces]]
# binding = "MY_KV_NAMESPACE"
# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Bind an mTLS certificate. Use to present a client certificate when communicating with another service.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#mtls-certificates
# [[mtls_certificates]]
# binding = "MY_CERTIFICATE"
# certificate_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#queues
# [[queues.producers]]
# binding = "MY_QUEUE"
# queue = "my-queue"
# Bind a Queue consumer. Queue Consumers can retrieve tasks scheduled by Producers to act on them.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#queues
# [[queues.consumers]]
# queue = "my-queue"
# Bind an R2 Bucket. Use R2 to store arbitrarily large blobs of data, such as files.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#r2-buckets
# [[r2_buckets]]
# binding = "MY_BUCKET"
# bucket_name = "my-bucket"
# Bind another Worker service. Use this binding to call another Worker without network overhead.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings
# [[services]]
# binding = "MY_SERVICE"
# service = "my-service"
# Bind a Vectorize index. Use to store and query vector embeddings for semantic search, classification and other vector search use-cases.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#vectorize-indexes
# [[vectorize]]
# binding = "MY_INDEX"
# index_name = "my-index"
@@ -0,0 +1,4 @@
{
"root": false,
"extends": "next/core-web-vitals"
}
@@ -0,0 +1,85 @@
# @llamaindex/next-agent-test
## 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
- Updated dependencies [bc7a11c]
- Updated dependencies [2fe2b81]
- Updated dependencies [5596e31]
- Updated dependencies [e74fe88]
- Updated dependencies [be5df5b]
- llamaindex@0.3.5
## 0.1.5
### Patch Changes
- Updated dependencies [1dce275]
- Updated dependencies [d10533e]
- Updated dependencies [2008efe]
- Updated dependencies [5e61934]
- Updated dependencies [9e74a43]
- Updated dependencies [ee719a1]
- llamaindex@0.3.4
## 0.1.4
### Patch Changes
- Updated dependencies [e8c41c5]
- llamaindex@0.3.3
## 0.1.3
### Patch Changes
- Updated dependencies [61103b6]
- llamaindex@0.3.2
## 0.1.2
### Patch Changes
- Updated dependencies [46227f2]
- llamaindex@0.3.1
## 0.1.1
### Patch Changes
- Updated dependencies [5016f21]
- llamaindex@0.3.0
@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun 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 Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
@@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
import withLlamaIndex from "llamaindex/next";
export default withLlamaIndex(nextConfig);
@@ -0,0 +1,28 @@
{
"name": "@llamaindex/next-agent-test",
"version": "0.1.10",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"ai": "^3.1.3",
"llamaindex": "workspace:*",
"next": "14.2.3",
"react": "18.3.1",
"react-dom": "18.3.1"
},
"devDependencies": {
"@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.4.5"
}
}
@@ -0,0 +1,8 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
},
};
export default config;

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before

Width:  |  Height:  |  Size: 629 B

After

Width:  |  Height:  |  Size: 629 B

@@ -0,0 +1,32 @@
"use server";
import { createStreamableUI } from "ai/rsc";
import { OpenAIAgent } from "llamaindex";
import type { ChatMessage } from "llamaindex/llm/types";
export async function chatWithAgent(
question: string,
prevMessages: ChatMessage[] = [],
) {
const agent = new OpenAIAgent({
tools: [],
});
const responseStream = await agent.chat({
stream: true,
message: question,
chatHistory: prevMessages,
});
const uiStream = createStreamableUI(<div>loading...</div>);
responseStream
.pipeTo(
new WritableStream({
start: () => {
uiStream.update("response:");
},
write: async (message) => {
uiStream.append(message.response.delta);
},
}),
)
.catch(uiStream.error);
return uiStream.value;
}

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@@ -0,0 +1,22 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
);
}
@@ -0,0 +1,20 @@
"use client";
import { chatWithAgent } from "@/actions";
import type { JSX } from "react";
import { useFormState } from "react-dom";
export const runtime = "edge";
export default function Home() {
const [state, action] = useFormState<JSX.Element | null>(async () => {
return chatWithAgent("hello!", []);
}, null);
return (
<main>
{state}
<form action={action}>
<button>Chat</button>
</form>
</main>
);
}

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