mirror of
https://github.com/run-llama/LlamaIndexTS.git
synced 2026-07-11 00:04:07 -04:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 701e0ac2be | |||
| a285f8ba3a | |||
| 663821cdf6 | |||
| c4b95494ac | |||
| 980fb4e5a3 | |||
| 96f8f40291 | |||
| 1c698df6e0 | |||
| 298cb433be | |||
| 63af7dd99d | |||
| af5df1d083 | |||
| a3b44093c2 | |||
| c80bf3311f | |||
| 7940d249b0 |
@@ -1,6 +1,12 @@
|
||||
name: Run Tests
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -8,6 +14,11 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
e2e:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version: [18.x, 20.x, 21.x]
|
||||
name: E2E on Node.js ${{ matrix.node-version }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
Vendored
+2
-1
@@ -10,8 +10,9 @@
|
||||
"name": "Debug Example",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"runtimeExecutable": "pnpm",
|
||||
"console": "integratedTerminal",
|
||||
"cwd": "${workspaceFolder}/examples",
|
||||
"runtimeArgs": ["ts-node", "${fileBasename}"]
|
||||
"runtimeArgs": ["npx", "tsx", "${file}"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ This page shows how to track LLM cost using APIs.
|
||||
|
||||
The callback manager is a class that manages the callback functions.
|
||||
|
||||
You can register `llm-start`, and `llm-end` callbacks to the callback manager for tracking the cost.
|
||||
You can register `llm-start`, `llm-end`, and `llm-stream` callbacks to the callback manager for tracking the cost.
|
||||
|
||||
import CodeBlock from "@theme/CodeBlock";
|
||||
import CodeSource from "!raw-loader!../../../../examples/recipes/cost-analysis";
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
"@docusaurus/theme-classic": "^3.2.1",
|
||||
"@docusaurus/types": "^3.2.1",
|
||||
"@tsconfig/docusaurus": "^2.0.3",
|
||||
"@types/node": "^18.19.31",
|
||||
"@types/node": "^20.12.7",
|
||||
"docusaurus-plugin-typedoc": "^0.22.0",
|
||||
"typedoc": "^0.25.13",
|
||||
"typedoc-plugin-markdown": "^3.17.1",
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { FunctionTool, OpenAIAgent } from "llamaindex";
|
||||
|
||||
// Define a function to sum two numbers
|
||||
function sumNumbers({ a, b }: { a: number; b: number }): number {
|
||||
return a + b;
|
||||
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 }): number {
|
||||
return a / b;
|
||||
function divideNumbers({ a, b }: { a: number; b: number }) {
|
||||
return `${a / b}`;
|
||||
}
|
||||
|
||||
// Define the parameters of the sum function as a JSON schema
|
||||
@@ -24,7 +24,7 @@ const sumJSON = {
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
};
|
||||
} as const;
|
||||
|
||||
const divideJSON = {
|
||||
type: "object",
|
||||
@@ -39,7 +39,7 @@ const divideJSON = {
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
};
|
||||
} as const;
|
||||
|
||||
async function main() {
|
||||
// Create a function tool from the sum function
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Anthropic, FunctionTool, ReActAgent } from "llamaindex";
|
||||
|
||||
// Define a function to sum two numbers
|
||||
function sumNumbers({ a, b }: { a: number; b: number }): number {
|
||||
return a + b;
|
||||
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 }): number {
|
||||
return a / b;
|
||||
function divideNumbers({ a, b }: { a: number; b: number }) {
|
||||
return `${a / b}`;
|
||||
}
|
||||
|
||||
// Define the parameters of the sum function as a JSON schema
|
||||
@@ -24,7 +24,7 @@ const sumJSON = {
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
};
|
||||
} as const;
|
||||
|
||||
const divideJSON = {
|
||||
type: "object",
|
||||
@@ -39,7 +39,7 @@ const divideJSON = {
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
};
|
||||
} as const;
|
||||
|
||||
async function main() {
|
||||
// Create a function tool from the sum function
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { FunctionTool, OpenAIAgent } from "llamaindex";
|
||||
|
||||
// Define a function to sum two numbers
|
||||
function sumNumbers({ a, b }: { a: number; b: number }): number {
|
||||
return a + b;
|
||||
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 }): number {
|
||||
return a / b;
|
||||
function divideNumbers({ a, b }: { a: number; b: number }) {
|
||||
return `${a / b}`;
|
||||
}
|
||||
|
||||
// Define the parameters of the sum function as a JSON schema
|
||||
@@ -24,22 +24,22 @@ const sumJSON = {
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
};
|
||||
} as const;
|
||||
|
||||
const divideJSON = {
|
||||
type: "object",
|
||||
properties: {
|
||||
a: {
|
||||
type: "number",
|
||||
description: "The dividend a to divide",
|
||||
description: "The dividend",
|
||||
},
|
||||
b: {
|
||||
type: "number",
|
||||
description: "The divisor b to divide by",
|
||||
description: "The divisor",
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
};
|
||||
} as const;
|
||||
|
||||
async function main() {
|
||||
// Create a function tool from the sum function
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { FunctionTool, ReActAgent } from "llamaindex";
|
||||
|
||||
// Define a function to sum two numbers
|
||||
function sumNumbers({ a, b }: { a: number; b: number }): number {
|
||||
return a + b;
|
||||
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 }): number {
|
||||
return a / b;
|
||||
function divideNumbers({ a, b }: { a: number; b: number }) {
|
||||
return `${a / b}`;
|
||||
}
|
||||
|
||||
// Define the parameters of the sum function as a JSON schema
|
||||
@@ -24,7 +24,7 @@ const sumJSON = {
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
};
|
||||
} as const;
|
||||
|
||||
const divideJSON = {
|
||||
type: "object",
|
||||
@@ -39,7 +39,7 @@ const divideJSON = {
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
};
|
||||
} as const;
|
||||
|
||||
async function main() {
|
||||
// Create a function tool from the sum function
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { FunctionTool, OpenAIAgent } from "llamaindex";
|
||||
|
||||
// Define a function to sum two numbers
|
||||
function sumNumbers({ a, b }: { a: number; b: number }): number {
|
||||
return a + b;
|
||||
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 }): number {
|
||||
return a / b;
|
||||
function divideNumbers({ a, b }: { a: number; b: number }) {
|
||||
return `${a / b}`;
|
||||
}
|
||||
|
||||
// Define the parameters of the sum function as a JSON schema
|
||||
@@ -24,7 +24,7 @@ const sumJSON = {
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
};
|
||||
} as const;
|
||||
|
||||
const divideJSON = {
|
||||
type: "object",
|
||||
@@ -39,18 +39,18 @@ const divideJSON = {
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
};
|
||||
} as const;
|
||||
|
||||
async function main() {
|
||||
// Create a function tool from the sum function
|
||||
const functionTool = new FunctionTool(sumNumbers, {
|
||||
const functionTool = FunctionTool.from(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, {
|
||||
const functionTool2 = FunctionTool.from(divideNumbers, {
|
||||
name: "divideNumbers",
|
||||
description: "Use this function to divide two numbers",
|
||||
parameters: divideJSON,
|
||||
|
||||
@@ -5,21 +5,22 @@
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-js": "^5.2.0",
|
||||
"@datastax/astra-db-ts": "^0.1.4",
|
||||
"@notionhq/client": "^2.2.14",
|
||||
"@notionhq/client": "^2.2.15",
|
||||
"@pinecone-database/pinecone": "^1.1.3",
|
||||
"@zilliz/milvus2-sdk-node": "^2.3.5",
|
||||
"chromadb": "^1.8.1",
|
||||
"commander": "^11.1.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"js-tiktoken": "^1.0.10",
|
||||
"llamaindex": "workspace:latest",
|
||||
"llamaindex": "latest",
|
||||
"mongodb": "^6.5.0",
|
||||
"pathe": "^1.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.19.31",
|
||||
"@types/node": "^20.12.7",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.4"
|
||||
"tsx": "^4.7.2",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint ."
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"llamaindex": "latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.14",
|
||||
"@types/node": "^20.12.7",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.3"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ import { extractText } from "llamaindex/llm/utils";
|
||||
const encoding = encodingForModel("gpt-4-0125-preview");
|
||||
|
||||
const llm = new OpenAI({
|
||||
model: "gpt-4-0125-preview",
|
||||
// currently is "gpt-4-turbo-2024-04-09"
|
||||
model: "gpt-4-turbo",
|
||||
});
|
||||
|
||||
let tokenCount = 0;
|
||||
@@ -19,18 +20,25 @@ Settings.callbackManager.on("llm-start", (event) => {
|
||||
console.log("Token count:", tokenCount);
|
||||
// https://openai.com/pricing
|
||||
// $10.00 / 1M tokens
|
||||
console.log(`Price: $${(tokenCount / 1_000_000) * 10}`);
|
||||
});
|
||||
Settings.callbackManager.on("llm-end", (event) => {
|
||||
const { response } = event.detail.payload;
|
||||
tokenCount += encoding.encode(extractText(response.message.content)).length;
|
||||
console.log("Token count:", tokenCount);
|
||||
// https://openai.com/pricing
|
||||
// $30.00 / 1M tokens
|
||||
console.log(`Price: $${(tokenCount / 1_000_000) * 30}`);
|
||||
console.log(`Total Price: $${(tokenCount / 1_000_000) * 10}`);
|
||||
});
|
||||
|
||||
const question = "Hello, how are you?";
|
||||
Settings.callbackManager.on("llm-stream", (event) => {
|
||||
const { chunk } = event.detail.payload;
|
||||
const { delta } = chunk;
|
||||
tokenCount += encoding.encode(extractText(delta)).length;
|
||||
if (tokenCount > 20) {
|
||||
// This is just an example, you can set your own limit or handle it differently
|
||||
throw new Error("Token limit exceeded!");
|
||||
}
|
||||
});
|
||||
Settings.callbackManager.on("llm-end", () => {
|
||||
// https://openai.com/pricing
|
||||
// $30.00 / 1M tokens
|
||||
console.log(`Total Price: $${(tokenCount / 1_000_000) * 30}`);
|
||||
});
|
||||
|
||||
const question = "Hello, how are you? Please response about 50 tokens.";
|
||||
console.log("Question:", question);
|
||||
void llm
|
||||
.chat({
|
||||
|
||||
@@ -2,7 +2,6 @@ import { OpenAI } from "llamaindex";
|
||||
|
||||
async function main() {
|
||||
const llm = new OpenAI({ model: "gpt-4-turbo" });
|
||||
|
||||
const args: Parameters<typeof llm.chat>[0] = {
|
||||
additionalChatOptions: {
|
||||
tool_choice: "auto",
|
||||
|
||||
+3
-2
@@ -27,13 +27,14 @@
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-organize-imports": "^3.2.4",
|
||||
"turbo": "^1.13.2",
|
||||
"typescript": "^5.4.4"
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"packageManager": "pnpm@8.15.6+sha256.01c01eeb990e379b31ef19c03e9d06a14afa5250b82e81303f88721c99ff2e6f",
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"trim": "1.0.1",
|
||||
"@babel/traverse": "7.23.2"
|
||||
"@babel/traverse": "7.23.2",
|
||||
"protobufjs": "7.2.6"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# llamaindex
|
||||
|
||||
## 0.2.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Add ToolsFactory to generate agent tools
|
||||
|
||||
## 0.2.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 96f8f40: fix: agent stream
|
||||
- Updated dependencies
|
||||
- @llamaindex/env@0.0.7
|
||||
|
||||
## 0.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- a3b4409: Fix agent streaming with new OpenAI models
|
||||
|
||||
## 0.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { BaseNode, SimilarityType, type BaseEmbedding } from "llamaindex";
|
||||
|
||||
export class OpenAIEmbedding implements BaseEmbedding {
|
||||
embedBatchSize = 512;
|
||||
|
||||
async getQueryEmbedding(query: string) {
|
||||
return [0];
|
||||
}
|
||||
|
||||
async getTextEmbedding(text: string) {
|
||||
return [0];
|
||||
}
|
||||
|
||||
async getTextEmbeddings(texts: string[]) {
|
||||
return [[0]];
|
||||
}
|
||||
|
||||
async getTextEmbeddingsBatch(texts: string[]) {
|
||||
return [[0]];
|
||||
}
|
||||
|
||||
similarity(
|
||||
embedding1: number[],
|
||||
embedding2: number[],
|
||||
mode?: SimilarityType,
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
async transform(nodes: BaseNode[], _options?: any): Promise<BaseNode[]> {
|
||||
return nodes;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import { faker } from "@faker-js/faker";
|
||||
import type {
|
||||
ChatResponse,
|
||||
ChatResponseChunk,
|
||||
@@ -9,6 +8,9 @@ import type {
|
||||
LLMCompletionParamsNonStreaming,
|
||||
LLMCompletionParamsStreaming,
|
||||
} from "llamaindex/llm/types";
|
||||
import { extractText } from "llamaindex/llm/utils";
|
||||
import { strictEqual } from "node:assert";
|
||||
import { llmCompleteMockStorage } from "../../node/utils.js";
|
||||
|
||||
export function getOpenAISession() {
|
||||
return {};
|
||||
@@ -40,24 +42,39 @@ export class OpenAI implements LLM {
|
||||
| LLMChatParamsStreaming<Record<string, unknown>>
|
||||
| LLMChatParamsNonStreaming<Record<string, unknown>>,
|
||||
): unknown {
|
||||
if (params.stream) {
|
||||
return {
|
||||
[Symbol.asyncIterator]: async function* () {
|
||||
yield {
|
||||
delta: faker.word.words(),
|
||||
} satisfies ChatResponseChunk;
|
||||
},
|
||||
};
|
||||
if (llmCompleteMockStorage.llmEventStart.length > 0) {
|
||||
const chatMessage =
|
||||
llmCompleteMockStorage.llmEventStart.shift()!["messages"];
|
||||
strictEqual(chatMessage.length, params.messages.length);
|
||||
for (let i = 0; i < chatMessage.length; i++) {
|
||||
strictEqual(chatMessage[i].role, params.messages[i].role);
|
||||
strictEqual(chatMessage[i].content, params.messages[i].content);
|
||||
}
|
||||
|
||||
if (llmCompleteMockStorage.llmEventEnd.length > 0) {
|
||||
const { id, response } = llmCompleteMockStorage.llmEventEnd.shift()!;
|
||||
if (params.stream) {
|
||||
return {
|
||||
[Symbol.asyncIterator]: async function* () {
|
||||
while (true) {
|
||||
const idx = llmCompleteMockStorage.llmEventStream.findIndex(
|
||||
(e) => e.id === id,
|
||||
);
|
||||
if (idx === -1) {
|
||||
break;
|
||||
}
|
||||
const chunk = llmCompleteMockStorage.llmEventStream[idx].chunk;
|
||||
llmCompleteMockStorage.llmEventStream.splice(idx, 1);
|
||||
yield chunk;
|
||||
}
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
get raw(): never {
|
||||
throw new Error("not implemented");
|
||||
},
|
||||
message: {
|
||||
content: faker.lorem.paragraph(),
|
||||
role: "assistant",
|
||||
},
|
||||
} satisfies ChatResponse;
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
complete(
|
||||
params: LLMCompletionParamsStreaming,
|
||||
@@ -65,7 +82,23 @@ export class OpenAI implements LLM {
|
||||
complete(
|
||||
params: LLMCompletionParamsNonStreaming,
|
||||
): Promise<CompletionResponse>;
|
||||
async complete(params: unknown): Promise<unknown> {
|
||||
async complete(
|
||||
params: LLMCompletionParamsStreaming | LLMCompletionParamsNonStreaming,
|
||||
): Promise<AsyncIterable<CompletionResponse> | CompletionResponse> {
|
||||
if (llmCompleteMockStorage.llmEventStart.length > 0) {
|
||||
const chatMessage =
|
||||
llmCompleteMockStorage.llmEventStart.shift()!["messages"];
|
||||
strictEqual(chatMessage.length, 1);
|
||||
strictEqual(chatMessage[0].role, "user");
|
||||
strictEqual(chatMessage[0].content, params.prompt);
|
||||
}
|
||||
if (llmCompleteMockStorage.llmEventEnd.length > 0) {
|
||||
const response = llmCompleteMockStorage.llmEventEnd.shift()!["response"];
|
||||
return {
|
||||
raw: response,
|
||||
text: extractText(response.message.content),
|
||||
} satisfies CompletionResponse;
|
||||
}
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
import { consola } from "consola";
|
||||
import {
|
||||
OpenAI,
|
||||
OpenAIAgent,
|
||||
Settings,
|
||||
type LLM,
|
||||
type LLMEndEvent,
|
||||
type LLMStartEvent,
|
||||
} from "llamaindex";
|
||||
import { ok } from "node:assert";
|
||||
import type { WriteStream } from "node:fs";
|
||||
import { createWriteStream } from "node:fs";
|
||||
import { mkdir } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { after, before, beforeEach, describe, test } from "node:test";
|
||||
import { inspect } from "node:util";
|
||||
|
||||
let llm: LLM;
|
||||
let fsStream: WriteStream;
|
||||
before(async () => {
|
||||
const logUrl = new URL(
|
||||
join(
|
||||
"..",
|
||||
"logs",
|
||||
`basic.e2e.${new Date().toISOString().replace(/:/g, "-").replace(/\./g, "-")}.log`,
|
||||
),
|
||||
import.meta.url,
|
||||
);
|
||||
await mkdir(new URL(".", logUrl), { recursive: true });
|
||||
fsStream = createWriteStream(logUrl, {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
fsStream.end();
|
||||
});
|
||||
|
||||
beforeEach((s) => {
|
||||
fsStream.write("start: " + s.name + "\n");
|
||||
});
|
||||
|
||||
const llmEventStartHandler = (event: LLMStartEvent) => {
|
||||
const { payload } = event.detail;
|
||||
fsStream.write(
|
||||
"llmEventStart: " +
|
||||
inspect(payload, {
|
||||
depth: Infinity,
|
||||
}) +
|
||||
"\n",
|
||||
);
|
||||
};
|
||||
|
||||
const llmEventEndHandler = (event: LLMEndEvent) => {
|
||||
const { payload } = event.detail;
|
||||
fsStream.write(
|
||||
"llmEventEnd: " +
|
||||
inspect(payload, {
|
||||
depth: Infinity,
|
||||
}) +
|
||||
"\n",
|
||||
);
|
||||
};
|
||||
|
||||
before(() => {
|
||||
Settings.llm = new OpenAI({
|
||||
model: "gpt-3.5-turbo",
|
||||
});
|
||||
llm = Settings.llm;
|
||||
Settings.callbackManager.on("llm-start", llmEventStartHandler);
|
||||
Settings.callbackManager.on("llm-end", llmEventEndHandler);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
Settings.callbackManager.off("llm-start", llmEventStartHandler);
|
||||
Settings.callbackManager.off("llm-end", llmEventEndHandler);
|
||||
});
|
||||
|
||||
describe("llm", () => {
|
||||
test("llm.chat", async () => {
|
||||
const response = await llm.chat({
|
||||
messages: [
|
||||
{
|
||||
content: "Hello",
|
||||
role: "user",
|
||||
},
|
||||
],
|
||||
});
|
||||
consola.debug("response:", response);
|
||||
ok(typeof response.message.content === "string");
|
||||
});
|
||||
|
||||
test("stream llm.chat", async () => {
|
||||
const iter = await llm.chat({
|
||||
stream: true,
|
||||
messages: [
|
||||
{
|
||||
content: "hello",
|
||||
role: "user",
|
||||
},
|
||||
],
|
||||
});
|
||||
for await (const chunk of iter) {
|
||||
consola.debug("chunk:", chunk);
|
||||
ok(typeof chunk.delta === "string");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("agent", () => {
|
||||
test("agent.chat", async () => {
|
||||
const agent = new OpenAIAgent({
|
||||
tools: [
|
||||
{
|
||||
call: async () => {
|
||||
return "35 degrees and sunny in San Francisco";
|
||||
},
|
||||
metadata: {
|
||||
name: "Weather",
|
||||
description: "Get the weather",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
location: { type: "string" },
|
||||
},
|
||||
required: ["location"],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const result = await agent.chat({
|
||||
message: "What is the weather in San Francisco?",
|
||||
});
|
||||
consola.debug("response:", result.response);
|
||||
ok(typeof result.response === "string");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,292 @@
|
||||
import { consola } from "consola";
|
||||
import {
|
||||
Document,
|
||||
FunctionTool,
|
||||
OpenAI,
|
||||
OpenAIAgent,
|
||||
QueryEngineTool,
|
||||
Settings,
|
||||
SubQuestionQueryEngine,
|
||||
VectorStoreIndex,
|
||||
type LLM,
|
||||
} from "llamaindex";
|
||||
import { ok } from "node:assert";
|
||||
import { beforeEach, test } from "node:test";
|
||||
import { mockLLMEvent } from "./utils.js";
|
||||
|
||||
let llm: LLM;
|
||||
beforeEach(async () => {
|
||||
Settings.llm = new OpenAI({
|
||||
model: "gpt-3.5-turbo",
|
||||
});
|
||||
llm = Settings.llm;
|
||||
});
|
||||
|
||||
function sumNumbers({ a, b }: { a: number; b: number }) {
|
||||
return `${a + b}`;
|
||||
}
|
||||
|
||||
function divideNumbers({ a, b }: { a: number; b: number }) {
|
||||
return `${a / b}`;
|
||||
}
|
||||
|
||||
await test("llm", async (t) => {
|
||||
await mockLLMEvent(t, "llm");
|
||||
await t.test("llm.chat", async () => {
|
||||
const response = await llm.chat({
|
||||
messages: [
|
||||
{
|
||||
content: "Hello",
|
||||
role: "user",
|
||||
},
|
||||
],
|
||||
});
|
||||
consola.debug("response:", response);
|
||||
ok(typeof response.message.content === "string");
|
||||
});
|
||||
|
||||
await t.test("stream llm.chat", async () => {
|
||||
const iter = await llm.chat({
|
||||
stream: true,
|
||||
messages: [
|
||||
{
|
||||
content: "hello",
|
||||
role: "user",
|
||||
},
|
||||
],
|
||||
});
|
||||
for await (const chunk of iter) {
|
||||
consola.debug("chunk:", chunk);
|
||||
ok(typeof chunk.delta === "string");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await test("gpt-4-turbo", async (t) => {
|
||||
const llm = new OpenAI({ model: "gpt-4-turbo" });
|
||||
Settings.llm = llm;
|
||||
await mockLLMEvent(t, "gpt-4-turbo");
|
||||
await t.test("agent", async () => {
|
||||
const agent = new OpenAIAgent({
|
||||
llm,
|
||||
tools: [
|
||||
{
|
||||
call: async () => {
|
||||
return "45 degrees and sunny in San Jose";
|
||||
},
|
||||
metadata: {
|
||||
name: "Weather",
|
||||
description: "Get the weather",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
location: { type: "string" },
|
||||
},
|
||||
required: ["location"],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const { response } = await agent.chat({
|
||||
message: "What is the weather in San Jose?",
|
||||
});
|
||||
consola.debug("response:", response);
|
||||
ok(typeof response === "string");
|
||||
ok(response.includes("45"));
|
||||
});
|
||||
});
|
||||
|
||||
await test("agent", async (t) => {
|
||||
await mockLLMEvent(t, "agent");
|
||||
await t.test("chat", async () => {
|
||||
const agent = new OpenAIAgent({
|
||||
tools: [
|
||||
{
|
||||
call: async () => {
|
||||
return "35 degrees and sunny in San Francisco";
|
||||
},
|
||||
metadata: {
|
||||
name: "Weather",
|
||||
description: "Get the weather",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
location: { type: "string" },
|
||||
},
|
||||
required: ["location"],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const result = await agent.chat({
|
||||
message: "What is the weather in San Francisco?",
|
||||
});
|
||||
consola.debug("response:", result.response);
|
||||
ok(typeof result.response === "string");
|
||||
ok(result.response.includes("35"));
|
||||
});
|
||||
|
||||
await t.test("async function", async () => {
|
||||
const uniqueId = "123456789";
|
||||
const showUniqueId = FunctionTool.from<{
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
}>(
|
||||
async ({ firstName, lastName }) => {
|
||||
ok(typeof firstName === "string");
|
||||
ok(typeof lastName === "string");
|
||||
const fullName = firstName + lastName;
|
||||
ok(fullName.toLowerCase().includes("alex"));
|
||||
ok(fullName.toLowerCase().includes("yang"));
|
||||
return uniqueId;
|
||||
},
|
||||
{
|
||||
name: "unique_id",
|
||||
description: "show user unique id",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
firstName: { type: "string" },
|
||||
lastName: { type: "string" },
|
||||
},
|
||||
required: ["firstName", "lastName"],
|
||||
},
|
||||
},
|
||||
);
|
||||
const agent = new OpenAIAgent({
|
||||
tools: [showUniqueId],
|
||||
});
|
||||
const { response } = await agent.chat({
|
||||
message: "My name is Alex Yang. What is my unique id?",
|
||||
});
|
||||
consola.debug("response:", response);
|
||||
ok(response.includes(uniqueId));
|
||||
});
|
||||
|
||||
await t.test("sum numbers", async () => {
|
||||
const sumFunctionTool = new FunctionTool(sumNumbers, {
|
||||
name: "sumNumbers",
|
||||
description: "Use this function to sum two numbers",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
a: {
|
||||
type: "number",
|
||||
description: "The first number",
|
||||
},
|
||||
b: {
|
||||
type: "number",
|
||||
description: "The second number",
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
},
|
||||
});
|
||||
|
||||
const openaiAgent = new OpenAIAgent({
|
||||
tools: [sumFunctionTool],
|
||||
});
|
||||
|
||||
const response = await openaiAgent.chat({
|
||||
message: "how much is 1 + 1?",
|
||||
});
|
||||
|
||||
ok(response.response.includes("2"));
|
||||
});
|
||||
});
|
||||
|
||||
await test("agent stream", async (t) => {
|
||||
await mockLLMEvent(t, "agent_stream");
|
||||
await t.test("sum numbers stream", async () => {
|
||||
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;
|
||||
|
||||
const functionTool = FunctionTool.from(sumNumbers, {
|
||||
name: "sumNumbers",
|
||||
description: "Use this function to sum two numbers",
|
||||
parameters: sumJSON,
|
||||
});
|
||||
|
||||
const functionTool2 = FunctionTool.from(divideNumbers, {
|
||||
name: "divideNumbers",
|
||||
description: "Use this function to divide two numbers",
|
||||
parameters: divideJSON,
|
||||
});
|
||||
|
||||
const agent = new OpenAIAgent({
|
||||
tools: [functionTool, functionTool2],
|
||||
});
|
||||
|
||||
const { response } = await agent.chat({
|
||||
message: "Divide 16 by 2 then add 20",
|
||||
stream: true,
|
||||
});
|
||||
|
||||
let message = "";
|
||||
|
||||
for await (const chunk of response) {
|
||||
message += chunk.response;
|
||||
}
|
||||
|
||||
ok(message.includes("28"));
|
||||
});
|
||||
});
|
||||
|
||||
await test("queryEngine", async (t) => {
|
||||
await mockLLMEvent(t, "queryEngine_subquestion");
|
||||
await t.test("subquestion", async () => {
|
||||
const document = new Document({
|
||||
text: "Bill Gates stole from Apple.\n Steve Jobs stole from Xerox.",
|
||||
});
|
||||
const index = await VectorStoreIndex.fromDocuments([document]);
|
||||
|
||||
const queryEngineTools = [
|
||||
new QueryEngineTool({
|
||||
queryEngine: index.asQueryEngine(),
|
||||
metadata: {
|
||||
name: "bill_gates_idea",
|
||||
description: "Get what Bill Gates idea from.",
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
const queryEngine = SubQuestionQueryEngine.fromDefaults({
|
||||
queryEngineTools,
|
||||
});
|
||||
|
||||
const { response } = await queryEngine.query({
|
||||
query: "What did Bill Gates steal from?",
|
||||
});
|
||||
|
||||
ok(response.includes("Apple"));
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,394 @@
|
||||
{
|
||||
"llmEventStart": [
|
||||
{
|
||||
"id": "PRESERVE_0",
|
||||
"messages": [
|
||||
{
|
||||
"content": "What is the weather in San Francisco?",
|
||||
"role": "user"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"messages": [
|
||||
{
|
||||
"content": "What is the weather in San Francisco?",
|
||||
"role": "user"
|
||||
},
|
||||
{
|
||||
"content": "",
|
||||
"role": "assistant",
|
||||
"options": {
|
||||
"toolCalls": [
|
||||
{
|
||||
"id": "HIDDEN",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "Weather",
|
||||
"arguments": "{\"location\":\"San Francisco\"}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"content": "35 degrees and sunny in San Francisco",
|
||||
"role": "tool",
|
||||
"options": {
|
||||
"name": "Weather",
|
||||
"tool_call_id": "HIDDEN"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_2",
|
||||
"messages": [
|
||||
{
|
||||
"content": "My name is Alex Yang. What is my unique id?",
|
||||
"role": "user"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_3",
|
||||
"messages": [
|
||||
{
|
||||
"content": "My name is Alex Yang. What is my unique id?",
|
||||
"role": "user"
|
||||
},
|
||||
{
|
||||
"content": "",
|
||||
"role": "assistant",
|
||||
"options": {
|
||||
"toolCalls": [
|
||||
{
|
||||
"id": "HIDDEN",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "unique_id",
|
||||
"arguments": "{\"firstName\":\"Alex\",\"lastName\":\"Yang\"}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"content": "123456789",
|
||||
"role": "tool",
|
||||
"options": {
|
||||
"name": "unique_id",
|
||||
"tool_call_id": "HIDDEN"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_4",
|
||||
"messages": [
|
||||
{
|
||||
"content": "how much is 1 + 1?",
|
||||
"role": "user"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_5",
|
||||
"messages": [
|
||||
{
|
||||
"content": "how much is 1 + 1?",
|
||||
"role": "user"
|
||||
},
|
||||
{
|
||||
"content": "",
|
||||
"role": "assistant",
|
||||
"options": {
|
||||
"toolCalls": [
|
||||
{
|
||||
"id": "HIDDEN",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "sumNumbers",
|
||||
"arguments": "{\"a\":1,\"b\":1}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"content": "2",
|
||||
"role": "tool",
|
||||
"options": {
|
||||
"name": "sumNumbers",
|
||||
"tool_call_id": "HIDDEN"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"llmEventEnd": [
|
||||
{
|
||||
"id": "PRESERVE_0",
|
||||
"response": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": null,
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "HIDDEN",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "Weather",
|
||||
"arguments": "{\"location\":\"San Francisco\"}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": "tool_calls"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 49,
|
||||
"completion_tokens": 15,
|
||||
"total_tokens": 64
|
||||
},
|
||||
"system_fingerprint": "HIDDEN"
|
||||
},
|
||||
"message": {
|
||||
"content": "",
|
||||
"role": "assistant",
|
||||
"options": {
|
||||
"toolCalls": [
|
||||
{
|
||||
"id": "HIDDEN",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "Weather",
|
||||
"arguments": "{\"location\":\"San Francisco\"}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"response": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "The weather in San Francisco is currently 35 degrees and sunny."
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": "stop"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 78,
|
||||
"completion_tokens": 14,
|
||||
"total_tokens": 92
|
||||
},
|
||||
"system_fingerprint": "HIDDEN"
|
||||
},
|
||||
"message": {
|
||||
"content": "The weather in San Francisco is currently 35 degrees and sunny.",
|
||||
"role": "assistant",
|
||||
"options": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_2",
|
||||
"response": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": null,
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "HIDDEN",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "unique_id",
|
||||
"arguments": "{\"firstName\":\"Alex\",\"lastName\":\"Yang\"}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": "tool_calls"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 59,
|
||||
"completion_tokens": 18,
|
||||
"total_tokens": 77
|
||||
},
|
||||
"system_fingerprint": "HIDDEN"
|
||||
},
|
||||
"message": {
|
||||
"content": "",
|
||||
"role": "assistant",
|
||||
"options": {
|
||||
"toolCalls": [
|
||||
{
|
||||
"id": "HIDDEN",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "unique_id",
|
||||
"arguments": "{\"firstName\":\"Alex\",\"lastName\":\"Yang\"}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_3",
|
||||
"response": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "Your unique id is 123456789."
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": "stop"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 88,
|
||||
"completion_tokens": 10,
|
||||
"total_tokens": 98
|
||||
},
|
||||
"system_fingerprint": "HIDDEN"
|
||||
},
|
||||
"message": {
|
||||
"content": "Your unique id is 123456789.",
|
||||
"role": "assistant",
|
||||
"options": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_4",
|
||||
"response": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": null,
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "HIDDEN",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "sumNumbers",
|
||||
"arguments": "{\"a\":1,\"b\":1}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": "tool_calls"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 70,
|
||||
"completion_tokens": 18,
|
||||
"total_tokens": 88
|
||||
},
|
||||
"system_fingerprint": "HIDDEN"
|
||||
},
|
||||
"message": {
|
||||
"content": "",
|
||||
"role": "assistant",
|
||||
"options": {
|
||||
"toolCalls": [
|
||||
{
|
||||
"id": "HIDDEN",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "sumNumbers",
|
||||
"arguments": "{\"a\":1,\"b\":1}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_5",
|
||||
"response": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "The sum of 1 + 1 is 2."
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": "stop"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 97,
|
||||
"completion_tokens": 13,
|
||||
"total_tokens": 110
|
||||
},
|
||||
"system_fingerprint": "HIDDEN"
|
||||
},
|
||||
"message": {
|
||||
"content": "The sum of 1 + 1 is 2.",
|
||||
"role": "assistant",
|
||||
"options": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"llmEventStream": []
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"llmEventStart": [
|
||||
{
|
||||
"id": "PRESERVE_0",
|
||||
"messages": [
|
||||
{
|
||||
"content": "What is the weather in San Jose?",
|
||||
"role": "user"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"messages": [
|
||||
{
|
||||
"content": "What is the weather in San Jose?",
|
||||
"role": "user"
|
||||
},
|
||||
{
|
||||
"content": "",
|
||||
"role": "assistant",
|
||||
"options": {
|
||||
"toolCalls": [
|
||||
{
|
||||
"id": "HIDDEN",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "Weather",
|
||||
"arguments": "{\"location\":\"San Jose\"}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"content": "45 degrees and sunny in San Jose",
|
||||
"role": "tool",
|
||||
"options": {
|
||||
"name": "Weather",
|
||||
"tool_call_id": "HIDDEN"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"llmEventEnd": [
|
||||
{
|
||||
"id": "PRESERVE_0",
|
||||
"response": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": null,
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "HIDDEN",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "Weather",
|
||||
"arguments": "{\"location\":\"San Jose\"}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": "tool_calls"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 49,
|
||||
"completion_tokens": 15,
|
||||
"total_tokens": 64
|
||||
},
|
||||
"system_fingerprint": "HIDDEN"
|
||||
},
|
||||
"message": {
|
||||
"content": "",
|
||||
"role": "assistant",
|
||||
"options": {
|
||||
"toolCalls": [
|
||||
{
|
||||
"id": "HIDDEN",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "Weather",
|
||||
"arguments": "{\"location\":\"San Jose\"}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"response": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "The weather in San Jose is currently 45 degrees and sunny."
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": "stop"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 78,
|
||||
"completion_tokens": 14,
|
||||
"total_tokens": 92
|
||||
},
|
||||
"system_fingerprint": "HIDDEN"
|
||||
},
|
||||
"message": {
|
||||
"content": "The weather in San Jose is currently 45 degrees and sunny.",
|
||||
"role": "assistant",
|
||||
"options": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"llmEventStream": []
|
||||
}
|
||||
@@ -0,0 +1,476 @@
|
||||
{
|
||||
"llmEventStart": [
|
||||
{
|
||||
"id": "PRESERVE_0",
|
||||
"messages": [
|
||||
{
|
||||
"content": "Hello",
|
||||
"role": "user"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"messages": [
|
||||
{
|
||||
"content": "hello",
|
||||
"role": "user"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"llmEventEnd": [
|
||||
{
|
||||
"id": "PRESERVE_0",
|
||||
"response": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "Hello! How can I assist you today?"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": "stop"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 8,
|
||||
"completion_tokens": 9,
|
||||
"total_tokens": 17
|
||||
},
|
||||
"system_fingerprint": "HIDDEN"
|
||||
},
|
||||
"message": {
|
||||
"content": "Hello! How can I assist you today?",
|
||||
"role": "assistant",
|
||||
"options": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"response": {
|
||||
"raw": [
|
||||
{
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": "Hello"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": "Hello"
|
||||
},
|
||||
{
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": "!"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": "!"
|
||||
},
|
||||
{
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": " How"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": " How"
|
||||
},
|
||||
{
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": " can"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": " can"
|
||||
},
|
||||
{
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": " I"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": " I"
|
||||
},
|
||||
{
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": " assist"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": " assist"
|
||||
},
|
||||
{
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": " you"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": " you"
|
||||
},
|
||||
{
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": " today"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": " today"
|
||||
},
|
||||
{
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": "?"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": "?"
|
||||
}
|
||||
],
|
||||
"message": {
|
||||
"content": "Hello! How can I assist you today?",
|
||||
"role": "assistant",
|
||||
"options": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"llmEventStream": [
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"chunk": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": "Hello"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": "Hello"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"chunk": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": "!"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": "!"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"chunk": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": " How"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": " How"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"chunk": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": " can"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": " can"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"chunk": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": " I"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": " I"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"chunk": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": " assist"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": " assist"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"chunk": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": " you"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": " you"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"chunk": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": " today"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": " today"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"chunk": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"system_fingerprint": "HIDDEN",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"delta": {
|
||||
"content": "?"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"delta": "?"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
{
|
||||
"llmEventStart": [
|
||||
{
|
||||
"id": "PRESERVE_0",
|
||||
"messages": [
|
||||
{
|
||||
"content": "Given a user question, and a list of tools, output a list of relevant sub-questions that when composed can help answer the full user question:\n\n# Example 1\n<Tools>\n```json\n{\n \"uber_10k\": \"Provides information about Uber financials for year 2021\",\n \"lyft_10k\": \"Provides information about Lyft financials for year 2021\"\n}\n```\n\n<User Question>\nCompare and contrast the revenue growth and EBITDA of Uber and Lyft for year 2021\n\n<Output>\n```json\n[\n {\n \"subQuestion\": \"What is the revenue growth of Uber\",\n \"toolName\": \"uber_10k\"\n },\n {\n \"subQuestion\": \"What is the EBITDA of Uber\",\n \"toolName\": \"uber_10k\"\n },\n {\n \"subQuestion\": \"What is the revenue growth of Lyft\",\n \"toolName\": \"lyft_10k\"\n },\n {\n \"subQuestion\": \"What is the EBITDA of Lyft\",\n \"toolName\": \"lyft_10k\"\n }\n]\n```\n\n# Example 2\n<Tools>\n```json\n{\n \"bill_gates_idea\": \"Get what Bill Gates idea from.\"\n}\n```\n\n<User Question>\nWhat did Bill Gates steal from?\n\n<Output>\n",
|
||||
"role": "user"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"messages": [
|
||||
{
|
||||
"content": "Context information is below.\n---------------------\nBill Gates stole from Apple. Steve Jobs stole from Xerox.\n---------------------\nGiven the context information and not prior knowledge, answer the query.\nQuery: What is Bill Gates' idea\nAnswer:",
|
||||
"role": "user"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_2",
|
||||
"messages": [
|
||||
{
|
||||
"content": "Context information is below.\n---------------------\nSub question: What is Bill Gates' idea\nResponse: Bill Gates' idea was to steal from Apple.\n---------------------\nGiven the context information and not prior knowledge, answer the query.\nQuery: What did Bill Gates steal from?\nAnswer:",
|
||||
"role": "user"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"llmEventEnd": [
|
||||
{
|
||||
"id": "PRESERVE_0",
|
||||
"response": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "```json\n[\n {\n \"subQuestion\": \"What is Bill Gates' idea\",\n \"toolName\": \"bill_gates_idea\"\n }\n]\n```"
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": "stop"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 290,
|
||||
"completion_tokens": 35,
|
||||
"total_tokens": 325
|
||||
},
|
||||
"system_fingerprint": "HIDDEN"
|
||||
},
|
||||
"message": {
|
||||
"content": "```json\n[\n {\n \"subQuestion\": \"What is Bill Gates' idea\",\n \"toolName\": \"bill_gates_idea\"\n }\n]\n```",
|
||||
"role": "assistant",
|
||||
"options": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_1",
|
||||
"response": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "Bill Gates' idea was to steal from Apple."
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": "stop"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 53,
|
||||
"completion_tokens": 10,
|
||||
"total_tokens": 63
|
||||
},
|
||||
"system_fingerprint": "HIDDEN"
|
||||
},
|
||||
"message": {
|
||||
"content": "Bill Gates' idea was to steal from Apple.",
|
||||
"role": "assistant",
|
||||
"options": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PRESERVE_2",
|
||||
"response": {
|
||||
"raw": {
|
||||
"id": "HIDDEN",
|
||||
"object": "chat.completion",
|
||||
"created": 114514,
|
||||
"model": "gpt-3.5-turbo-0125",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "Bill Gates stole from Apple."
|
||||
},
|
||||
"logprobs": null,
|
||||
"finish_reason": "stop"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 62,
|
||||
"completion_tokens": 6,
|
||||
"total_tokens": 68
|
||||
},
|
||||
"system_fingerprint": "HIDDEN"
|
||||
},
|
||||
"message": {
|
||||
"content": "Bill Gates stole from Apple.",
|
||||
"role": "assistant",
|
||||
"options": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"llmEventStream": []
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
import {
|
||||
Settings,
|
||||
type LLMEndEvent,
|
||||
type LLMStartEvent,
|
||||
type LLMStreamEvent,
|
||||
} from "llamaindex";
|
||||
import { readFile, writeFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { type test } from "node:test";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
type MockStorage = {
|
||||
llmEventStart: LLMStartEvent["detail"]["payload"][];
|
||||
llmEventEnd: LLMEndEvent["detail"]["payload"][];
|
||||
llmEventStream: LLMStreamEvent["detail"]["payload"][];
|
||||
};
|
||||
|
||||
export const llmCompleteMockStorage: MockStorage = {
|
||||
llmEventStart: [],
|
||||
llmEventEnd: [],
|
||||
llmEventStream: [],
|
||||
};
|
||||
|
||||
export const testRootDir = fileURLToPath(new URL(".", import.meta.url));
|
||||
|
||||
export async function mockLLMEvent(
|
||||
t: Parameters<NonNullable<Parameters<typeof test>[0]>>[0],
|
||||
snapshotName: string,
|
||||
) {
|
||||
const idMap = new Map<string, string>();
|
||||
let counter = 0;
|
||||
const newLLMCompleteMockStorage: MockStorage = {
|
||||
llmEventStart: [],
|
||||
llmEventEnd: [],
|
||||
llmEventStream: [],
|
||||
};
|
||||
|
||||
function captureLLMStart(event: LLMStartEvent) {
|
||||
idMap.set(event.detail.payload.id, `PRESERVE_${counter++}`);
|
||||
newLLMCompleteMockStorage.llmEventStart.push({
|
||||
...event.detail.payload,
|
||||
// @ts-expect-error id is not UUID, but it is fine for testing
|
||||
id: idMap.get(event.detail.payload.id)!,
|
||||
});
|
||||
}
|
||||
|
||||
function captureLLMEnd(event: LLMEndEvent) {
|
||||
newLLMCompleteMockStorage.llmEventEnd.push({
|
||||
...event.detail.payload,
|
||||
// @ts-expect-error id is not UUID, but it is fine for testing
|
||||
id: idMap.get(event.detail.payload.id)!,
|
||||
});
|
||||
}
|
||||
|
||||
function captureLLMStream(event: LLMStreamEvent) {
|
||||
newLLMCompleteMockStorage.llmEventStream.push({
|
||||
...event.detail.payload,
|
||||
// @ts-expect-error id is not UUID, but it is fine for testing
|
||||
id: idMap.get(event.detail.payload.id)!,
|
||||
});
|
||||
}
|
||||
|
||||
await readFile(join(testRootDir, "snapshot", `${snapshotName}.snap`), {
|
||||
encoding: "utf-8",
|
||||
})
|
||||
.then((data) => {
|
||||
const result = JSON.parse(data) as MockStorage;
|
||||
result["llmEventEnd"].forEach((event) => {
|
||||
llmCompleteMockStorage.llmEventEnd.push(event);
|
||||
});
|
||||
result["llmEventStart"].forEach((event) => {
|
||||
llmCompleteMockStorage.llmEventStart.push(event);
|
||||
});
|
||||
result["llmEventStream"].forEach((event) => {
|
||||
llmCompleteMockStorage.llmEventStream.push(event);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.code === "ENOENT") {
|
||||
console.warn("Snapshot file not found, will create a new one");
|
||||
return;
|
||||
}
|
||||
});
|
||||
Settings.callbackManager.on("llm-start", captureLLMStart);
|
||||
Settings.callbackManager.on("llm-end", captureLLMEnd);
|
||||
Settings.callbackManager.on("llm-stream", captureLLMStream);
|
||||
|
||||
t.after(async () => {
|
||||
Settings.callbackManager.off("llm-stream", captureLLMStream);
|
||||
Settings.callbackManager.off("llm-end", captureLLMEnd);
|
||||
Settings.callbackManager.off("llm-start", captureLLMStart);
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
if (process.env.UPDATE_SNAPSHOT === "1") {
|
||||
const data = JSON.stringify(newLLMCompleteMockStorage, null, 2)
|
||||
.replace(/"id": "(?!PRESERVE_).*"/g, '"id": "HIDDEN"')
|
||||
.replace(/"created": \d+/g, `"created": 114514`)
|
||||
.replace(
|
||||
/"system_fingerprint": ".*"/g,
|
||||
'"system_fingerprint": "HIDDEN"',
|
||||
)
|
||||
.replace(/"tool_call_id": ".*"/g, '"tool_call_id": "HIDDEN"');
|
||||
await writeFile(
|
||||
join(testRootDir, "snapshot", `${snapshotName}.snap`),
|
||||
data,
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
newLLMCompleteMockStorage.llmEventEnd.length !==
|
||||
llmCompleteMockStorage.llmEventEnd.length
|
||||
) {
|
||||
throw new Error("New LLMEndEvent does not match, please update snapshot");
|
||||
}
|
||||
if (
|
||||
newLLMCompleteMockStorage.llmEventStart.length !==
|
||||
llmCompleteMockStorage.llmEventStart.length
|
||||
) {
|
||||
throw new Error(
|
||||
"New LLMStartEvent does not match, please update snapshot",
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
newLLMCompleteMockStorage.llmEventStream.length !==
|
||||
llmCompleteMockStorage.llmEventStream.length
|
||||
) {
|
||||
throw new Error(
|
||||
"New LLMStreamEvent does not match, please update snapshot",
|
||||
);
|
||||
}
|
||||
});
|
||||
// cleanup
|
||||
t.after(() => {
|
||||
llmCompleteMockStorage.llmEventEnd = [];
|
||||
llmCompleteMockStorage.llmEventStart = [];
|
||||
llmCompleteMockStorage.llmEventStream = [];
|
||||
});
|
||||
}
|
||||
@@ -5,7 +5,8 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"e2e": "node --import tsx --import ./mock-register.js --test ./node/*.e2e.ts",
|
||||
"e2e:nomock": "node --import tsx --test ./node/*.e2e.ts"
|
||||
"e2e:nomock": "node --import tsx --test ./node/*.e2e.ts",
|
||||
"e2e:updatesnap": "UPDATE_SNAPSHOT=1 node --import tsx --test ./node/*.e2e.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^8.4.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "llamaindex",
|
||||
"version": "0.2.5",
|
||||
"version": "0.2.8",
|
||||
"expectedMinorVersion": "2",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
@@ -12,18 +12,19 @@
|
||||
"@llamaindex/cloud": "0.0.5",
|
||||
"@llamaindex/env": "workspace:*",
|
||||
"@mistralai/mistralai": "^0.1.3",
|
||||
"@notionhq/client": "^2.2.14",
|
||||
"@notionhq/client": "^2.2.15",
|
||||
"@pinecone-database/pinecone": "^2.2.0",
|
||||
"@qdrant/js-client-rest": "^1.8.2",
|
||||
"@types/lodash": "^4.17.0",
|
||||
"@types/node": "^18.19.31",
|
||||
"@types/node": "^20.12.7",
|
||||
"@types/papaparse": "^5.3.14",
|
||||
"@types/pg": "^8.11.5",
|
||||
"@xenova/transformers": "^2.16.1",
|
||||
"@zilliz/milvus2-sdk-node": "^2.3.5",
|
||||
"ajv": "^8.12.0",
|
||||
"assemblyai": "^4.3.4",
|
||||
"chromadb": "~1.7.3",
|
||||
"cohere-ai": "^7.9.2",
|
||||
"cohere-ai": "^7.9.3",
|
||||
"js-tiktoken": "^1.0.10",
|
||||
"lodash": "^4.17.21",
|
||||
"magic-bytes.js": "^1.10.0",
|
||||
@@ -50,7 +51,7 @@
|
||||
"concurrently": "^8.2.2",
|
||||
"glob": "^10.3.12",
|
||||
"madge": "^6.1.0",
|
||||
"typescript": "^5.4.4"
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Settings } from "../../Settings.js";
|
||||
import type { ChatMessage } from "../../llm/index.js";
|
||||
import { OpenAI } from "../../llm/index.js";
|
||||
import type { BaseMemory } from "../../memory/types.js";
|
||||
import type { ObjectRetriever } from "../../objects/base.js";
|
||||
import type { BaseTool } from "../../types.js";
|
||||
import { AgentRunner } from "../runner/base.js";
|
||||
@@ -9,7 +10,7 @@ import { OpenAIAgentWorker } from "./worker.js";
|
||||
type OpenAIAgentParams = {
|
||||
tools?: BaseTool[];
|
||||
llm?: OpenAI;
|
||||
memory?: any;
|
||||
memory?: BaseMemory;
|
||||
prefixMessages?: ChatMessage[];
|
||||
maxFunctionCalls?: number;
|
||||
defaultToolChoice?: string;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { randomUUID } from "@llamaindex/env";
|
||||
import { pipeline, randomUUID } from "@llamaindex/env";
|
||||
import type { ChatCompletionToolChoiceOption } from "openai/resources/chat/completions";
|
||||
import { Response } from "../../Response.js";
|
||||
import { Settings } from "../../Settings.js";
|
||||
@@ -14,12 +14,9 @@ import {
|
||||
type ChatResponseChunk,
|
||||
type LLMChatParamsBase,
|
||||
type OpenAIAdditionalChatOptions,
|
||||
type OpenAIAdditionalMessageOptions,
|
||||
} from "../../llm/index.js";
|
||||
import {
|
||||
extractText,
|
||||
streamConverter,
|
||||
streamReducer,
|
||||
} from "../../llm/utils.js";
|
||||
import { extractText } from "../../llm/utils.js";
|
||||
import { ChatMemoryBuffer } from "../../memory/ChatMemoryBuffer.js";
|
||||
import type { ObjectRetriever } from "../../objects/base.js";
|
||||
import type { ToolOutput } from "../../tools/types.js";
|
||||
@@ -49,7 +46,7 @@ async function callFunction(
|
||||
|
||||
// Call tool
|
||||
// Use default error message
|
||||
const output = await callToolWithErrorHandling(tool, argumentDict, null);
|
||||
const output = await callToolWithErrorHandling(tool, argumentDict);
|
||||
|
||||
if (Settings.debug) {
|
||||
console.log(`Got output ${output}`);
|
||||
@@ -181,40 +178,70 @@ export class OpenAIAgentWorker
|
||||
stream: true,
|
||||
...llmChatParams,
|
||||
});
|
||||
// read first chunk from stream to find out if we need to call tools
|
||||
const iterator = stream[Symbol.asyncIterator]();
|
||||
let { value } = await iterator.next();
|
||||
let content = value.delta;
|
||||
const hasToolCalls = value.options?.toolCalls.length > 0;
|
||||
|
||||
const responseChunkStream = new ReadableStream<
|
||||
ChatResponseChunk<OpenAIAdditionalMessageOptions>
|
||||
>({
|
||||
async start(controller) {
|
||||
for await (const chunk of stream) {
|
||||
controller.enqueue(chunk);
|
||||
}
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
const [pipStream, finalStream] = responseChunkStream.tee();
|
||||
const reader = pipStream.getReader();
|
||||
const { value } = await reader.read();
|
||||
reader.releaseLock();
|
||||
if (value === undefined) {
|
||||
throw new Error("first chunk value is undefined, this should not happen");
|
||||
}
|
||||
// check if first chunk has tool calls, if so, this is a function call
|
||||
// otherwise, it's a regular message
|
||||
const hasToolCalls: boolean =
|
||||
!!value.options?.toolCalls?.length &&
|
||||
value.options?.toolCalls?.length > 0;
|
||||
|
||||
if (hasToolCalls) {
|
||||
// consume stream until we have all the tool calls and return a non-streamed response
|
||||
for await (value of stream) {
|
||||
content += value.delta;
|
||||
}
|
||||
return this._processMessage(task, {
|
||||
content,
|
||||
content: await pipeline(finalStream, async (iterator) => {
|
||||
let content = "";
|
||||
for await (const value of iterator) {
|
||||
content += value.delta;
|
||||
}
|
||||
return content;
|
||||
}),
|
||||
role: "assistant",
|
||||
options: value.options,
|
||||
});
|
||||
} else {
|
||||
const [responseStream, chunkStream] = finalStream.tee();
|
||||
let content = "";
|
||||
return new StreamingAgentChatResponse(
|
||||
responseStream.pipeThrough<Response>({
|
||||
readable: new ReadableStream({
|
||||
async start(controller) {
|
||||
for await (const chunk of chunkStream) {
|
||||
controller.enqueue(new Response(chunk.delta));
|
||||
}
|
||||
controller.close();
|
||||
},
|
||||
}),
|
||||
writable: new WritableStream({
|
||||
write(chunk) {
|
||||
content += chunk.delta;
|
||||
},
|
||||
close() {
|
||||
task.extraState.newMemory.put({
|
||||
content,
|
||||
role: "assistant",
|
||||
});
|
||||
},
|
||||
}),
|
||||
}),
|
||||
task.extraState.sources,
|
||||
);
|
||||
}
|
||||
|
||||
const newStream = streamConverter.bind(this)(
|
||||
streamReducer({
|
||||
stream,
|
||||
initialValue: content,
|
||||
reducer: (accumulator, part) => (accumulator += part.delta),
|
||||
finished: (accumulator) => {
|
||||
task.extraState.newMemory.put({
|
||||
content: accumulator,
|
||||
role: "assistant",
|
||||
});
|
||||
},
|
||||
}),
|
||||
(r: ChatResponseChunk) => new Response(r.delta),
|
||||
);
|
||||
|
||||
return new StreamingAgentChatResponse(newStream, task.extraState.sources);
|
||||
}
|
||||
|
||||
private async _getAgentResponse(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { ChatMessage, LLM } from "../../llm/index.js";
|
||||
import type { BaseMemory } from "../../memory/types.js";
|
||||
import type { ObjectRetriever } from "../../objects/base.js";
|
||||
import type { BaseTool } from "../../types.js";
|
||||
import { AgentRunner } from "../runner/base.js";
|
||||
@@ -7,7 +8,7 @@ import { ReActAgentWorker } from "./worker.js";
|
||||
type ReActAgentParams = {
|
||||
tools: BaseTool[];
|
||||
llm?: LLM;
|
||||
memory?: any;
|
||||
memory?: BaseMemory;
|
||||
prefixMessages?: ChatMessage[];
|
||||
maxInteractions?: number;
|
||||
defaultToolChoice?: string;
|
||||
|
||||
@@ -194,7 +194,7 @@ export class ReActAgentWorker implements AgentWorker<ChatParams> {
|
||||
|
||||
const tool = toolsDict[actionReasoningStep.action];
|
||||
|
||||
const toolOutput = await tool?.call?.(actionReasoningStep.actionInput);
|
||||
const toolOutput = await tool.call!(actionReasoningStep.actionInput);
|
||||
|
||||
task.extraState.sources.push(
|
||||
new ToolOutput(
|
||||
|
||||
@@ -161,7 +161,7 @@ export class AgentRunner extends BaseAgentRunner {
|
||||
const task = this.state.getTask(taskId);
|
||||
const curStep = step || this.state.getStepQueue(taskId).shift();
|
||||
|
||||
let curStepOutput;
|
||||
let curStepOutput: TaskStepOutput;
|
||||
|
||||
if (!curStep) {
|
||||
throw new Error(`No step found for task ${taskId}`);
|
||||
|
||||
@@ -4,6 +4,7 @@ import type {
|
||||
StreamingAgentChatResponse,
|
||||
} from "../engines/chat/index.js";
|
||||
|
||||
import type { BaseMemory } from "../memory/types.js";
|
||||
import type { QueryEngineParamsNonStreaming } from "../types.js";
|
||||
|
||||
export interface AgentWorker<ExtraParams extends object = object> {
|
||||
@@ -72,7 +73,7 @@ export abstract class BaseAgent implements BaseChatEngine, BaseQueryEngine {
|
||||
type TaskParams = {
|
||||
taskId: string;
|
||||
input: string;
|
||||
memory: any;
|
||||
memory: BaseMemory;
|
||||
extraState: Record<string, any>;
|
||||
};
|
||||
|
||||
@@ -84,7 +85,7 @@ export class Task {
|
||||
taskId: string;
|
||||
input: string;
|
||||
|
||||
memory: any;
|
||||
memory: BaseMemory;
|
||||
extraState: Record<string, any>;
|
||||
|
||||
constructor({ taskId, input, memory, extraState }: TaskParams) {
|
||||
|
||||
@@ -5,7 +5,11 @@ import {
|
||||
EventCaller,
|
||||
getEventCaller,
|
||||
} from "../internal/context/EventCaller.js";
|
||||
import type { LLMEndEvent, LLMStartEvent } from "../llm/types.js";
|
||||
import type {
|
||||
LLMEndEvent,
|
||||
LLMStartEvent,
|
||||
LLMStreamEvent,
|
||||
} from "../llm/types.js";
|
||||
|
||||
export class LlamaIndexCustomEvent<T = any> extends CustomEvent<T> {
|
||||
reason: EventCaller | null;
|
||||
@@ -44,6 +48,7 @@ export interface LlamaIndexEventMaps {
|
||||
stream: CustomEvent<StreamCallbackResponse>;
|
||||
"llm-start": LLMStartEvent;
|
||||
"llm-end": LLMEndEvent;
|
||||
"llm-stream": LLMStreamEvent;
|
||||
}
|
||||
|
||||
//#region @deprecated remove in the next major version
|
||||
|
||||
@@ -366,7 +366,7 @@ export class Portkey extends BaseLLM {
|
||||
|
||||
idx_counter++;
|
||||
|
||||
yield { delta: part.choices[0].delta?.content ?? "" };
|
||||
yield { raw: part, delta: part.choices[0].delta?.content ?? "" };
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -212,7 +212,10 @@ export class Anthropic extends BaseLLM {
|
||||
if (typeof content !== "string") continue;
|
||||
|
||||
idx_counter++;
|
||||
yield { delta: content };
|
||||
yield {
|
||||
raw: part,
|
||||
delta: content,
|
||||
};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ export abstract class BaseLLM<
|
||||
});
|
||||
return streamConverter(stream, (chunk) => {
|
||||
return {
|
||||
raw: null,
|
||||
text: chunk.delta,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -137,6 +137,7 @@ export class MistralAI extends BaseLLM {
|
||||
idx_counter++;
|
||||
|
||||
yield {
|
||||
raw: part,
|
||||
delta: part.choices[0].delta.content ?? "",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,11 +14,13 @@ import type {
|
||||
|
||||
const messageAccessor = (data: any): ChatResponseChunk => {
|
||||
return {
|
||||
raw: data,
|
||||
delta: data.message.content,
|
||||
};
|
||||
};
|
||||
|
||||
const completionAccessor = (data: any): CompletionResponse => {
|
||||
return { text: data.response };
|
||||
return { text: data.response, raw: null };
|
||||
};
|
||||
|
||||
// https://github.com/jmorganca/ollama
|
||||
|
||||
@@ -391,6 +391,8 @@ export class OpenAI extends BaseLLM<
|
||||
for await (const part of stream) {
|
||||
if (!part.choices.length) continue;
|
||||
const choice = part.choices[0];
|
||||
// skip parts that don't have any content
|
||||
if (!(choice.delta.content || choice.delta.tool_calls)) continue;
|
||||
updateToolCalls(toolCalls, choice.delta.tool_calls);
|
||||
|
||||
const isDone: boolean = choice.finish_reason !== null;
|
||||
@@ -402,6 +404,7 @@ export class OpenAI extends BaseLLM<
|
||||
});
|
||||
|
||||
yield {
|
||||
raw: part,
|
||||
// add tool calls to final chunk
|
||||
options: toolCalls.length > 0 ? { toolCalls: toolCalls } : {},
|
||||
delta: choice.delta.content ?? "",
|
||||
@@ -444,8 +447,11 @@ function updateToolCalls(
|
||||
return toolCall;
|
||||
}
|
||||
if (toolCallDeltas) {
|
||||
toolCallDeltas?.forEach((toolCall, i) => {
|
||||
toolCalls[i] = augmentToolCall(toolCalls[i], toolCall);
|
||||
toolCallDeltas?.forEach((toolCall) => {
|
||||
toolCalls[toolCall.index] = augmentToolCall(
|
||||
toolCalls[toolCall.index],
|
||||
toolCall,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,13 @@ export type LLMEndEvent = LLMBaseEvent<
|
||||
response: ChatResponse;
|
||||
}
|
||||
>;
|
||||
export type LLMStreamEvent = LLMBaseEvent<
|
||||
"llm-stream",
|
||||
{
|
||||
id: UUID;
|
||||
chunk: ChatResponseChunk;
|
||||
}
|
||||
>;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -126,8 +133,10 @@ export interface ChatResponse<
|
||||
message: ChatMessage<AdditionalMessageOptions>;
|
||||
/**
|
||||
* Raw response from the LLM
|
||||
*
|
||||
* If LLM response an iterable of chunks, this will be an array of those chunks
|
||||
*/
|
||||
raw: object;
|
||||
raw: object | null;
|
||||
}
|
||||
|
||||
export type ChatResponseChunk<
|
||||
@@ -138,17 +147,24 @@ export type ChatResponseChunk<
|
||||
> =
|
||||
AdditionalMessageOptions extends Record<string, unknown>
|
||||
? {
|
||||
raw: object | null;
|
||||
delta: string;
|
||||
options?: AdditionalMessageOptions;
|
||||
}
|
||||
: {
|
||||
raw: object | null;
|
||||
delta: string;
|
||||
options: AdditionalMessageOptions;
|
||||
};
|
||||
|
||||
export interface CompletionResponse {
|
||||
text: string;
|
||||
raw?: Record<string, any>;
|
||||
/**
|
||||
* Raw response from the LLM
|
||||
*
|
||||
* It's possible that this is `null` if the LLM response an iterable of chunks
|
||||
*/
|
||||
raw: object | null;
|
||||
}
|
||||
|
||||
export type LLMMetadata = {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { AsyncLocalStorage, randomUUID } from "@llamaindex/env";
|
||||
import { getCallbackManager } from "../internal/settings/CallbackManager.js";
|
||||
import type {
|
||||
ChatResponse,
|
||||
ChatResponseChunk,
|
||||
LLM,
|
||||
LLMChat,
|
||||
MessageContent,
|
||||
@@ -83,13 +84,14 @@ export function wrapLLMEvent(
|
||||
[Symbol.asyncIterator]: response[Symbol.asyncIterator].bind(response),
|
||||
};
|
||||
response[Symbol.asyncIterator] = async function* () {
|
||||
const finalResponse: ChatResponse = {
|
||||
raw: response,
|
||||
const finalResponse = {
|
||||
raw: [] as ChatResponseChunk[],
|
||||
message: {
|
||||
content: "",
|
||||
role: "assistant",
|
||||
options: {},
|
||||
},
|
||||
};
|
||||
} satisfies ChatResponse;
|
||||
let firstOne = false;
|
||||
for await (const chunk of originalAsyncIterator) {
|
||||
if (!firstOne) {
|
||||
@@ -98,6 +100,19 @@ export function wrapLLMEvent(
|
||||
} else {
|
||||
finalResponse.message.content += chunk.delta;
|
||||
}
|
||||
if (chunk.options) {
|
||||
finalResponse.message.options = {
|
||||
...finalResponse.message.options,
|
||||
...chunk.options,
|
||||
};
|
||||
}
|
||||
getCallbackManager().dispatchEvent("llm-stream", {
|
||||
payload: {
|
||||
id,
|
||||
chunk,
|
||||
},
|
||||
});
|
||||
finalResponse.raw.push(chunk);
|
||||
yield chunk;
|
||||
}
|
||||
snapshot(() => {
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
import type { JSONSchemaType } from "ajv";
|
||||
import type { BaseQueryEngine, BaseTool, ToolMetadata } from "../types.js";
|
||||
|
||||
export type QueryEngineToolParams = {
|
||||
queryEngine: BaseQueryEngine;
|
||||
metadata: ToolMetadata;
|
||||
};
|
||||
|
||||
type QueryEngineCallParams = {
|
||||
query: string;
|
||||
};
|
||||
|
||||
const DEFAULT_NAME = "query_engine_tool";
|
||||
const DEFAULT_DESCRIPTION =
|
||||
"Useful for running a natural language query against a knowledge base and get back a natural language response.";
|
||||
const DEFAULT_PARAMETERS = {
|
||||
|
||||
const DEFAULT_PARAMETERS: JSONSchemaType<QueryEngineParam> = {
|
||||
type: "object",
|
||||
properties: {
|
||||
query: {
|
||||
@@ -23,9 +16,18 @@ const DEFAULT_PARAMETERS = {
|
||||
required: ["query"],
|
||||
};
|
||||
|
||||
export class QueryEngineTool implements BaseTool {
|
||||
export type QueryEngineToolParams = {
|
||||
queryEngine: BaseQueryEngine;
|
||||
metadata: ToolMetadata<JSONSchemaType<QueryEngineParam>>;
|
||||
};
|
||||
|
||||
export type QueryEngineParam = {
|
||||
query: string;
|
||||
};
|
||||
|
||||
export class QueryEngineTool implements BaseTool<QueryEngineParam> {
|
||||
private queryEngine: BaseQueryEngine;
|
||||
metadata: ToolMetadata;
|
||||
metadata: ToolMetadata<JSONSchemaType<QueryEngineParam>>;
|
||||
|
||||
constructor({ queryEngine, metadata }: QueryEngineToolParams) {
|
||||
this.queryEngine = queryEngine;
|
||||
@@ -36,18 +38,8 @@ export class QueryEngineTool implements BaseTool {
|
||||
};
|
||||
}
|
||||
|
||||
async call(...args: QueryEngineCallParams[]): Promise<any> {
|
||||
let queryStr: string;
|
||||
|
||||
if (args && args.length > 0) {
|
||||
queryStr = String(args[0].query);
|
||||
} else {
|
||||
throw new Error(
|
||||
"Cannot call query engine without specifying `input` parameter.",
|
||||
);
|
||||
}
|
||||
|
||||
const response = await this.queryEngine.query({ query: queryStr });
|
||||
async call({ query }: QueryEngineParam) {
|
||||
const response = await this.queryEngine.query({ query });
|
||||
|
||||
return response.response;
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import type { BaseTool } from "../types.js";
|
||||
import { WikipediaTool } from "./WikipediaTool.js";
|
||||
|
||||
enum Tools {
|
||||
Wikipedia = "wikipedia.WikipediaToolSpec",
|
||||
}
|
||||
|
||||
type ToolConfig = { [key in Tools]: Record<string, any> };
|
||||
|
||||
export class ToolFactory {
|
||||
private static async createTool(
|
||||
key: Tools,
|
||||
options: Record<string, any>,
|
||||
): Promise<BaseTool> {
|
||||
if (key === Tools.Wikipedia) {
|
||||
const tool = new WikipediaTool();
|
||||
return tool;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Sorry! Tool ${key} is not supported yet. Options: ${options}`,
|
||||
);
|
||||
}
|
||||
|
||||
public static async createTools(config: ToolConfig): Promise<BaseTool[]> {
|
||||
const tools: BaseTool[] = [];
|
||||
for (const [key, value] of Object.entries(config as ToolConfig)) {
|
||||
const tool = await ToolFactory.createTool(key as Tools, value);
|
||||
tools.push(tool);
|
||||
}
|
||||
return tools;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { WikipediaTool } from "./WikipediaTool.js";
|
||||
|
||||
export namespace ToolsFactory {
|
||||
type ToolsMap = {
|
||||
[Tools.Wikipedia]: typeof WikipediaTool;
|
||||
};
|
||||
|
||||
export enum Tools {
|
||||
Wikipedia = "wikipedia.WikipediaToolSpec",
|
||||
}
|
||||
|
||||
export async function createTool<Tool extends Tools>(
|
||||
key: Tool,
|
||||
...params: ConstructorParameters<ToolsMap[Tool]>
|
||||
): Promise<InstanceType<ToolsMap[Tool]>> {
|
||||
if (key === Tools.Wikipedia) {
|
||||
return new WikipediaTool(...params) as InstanceType<ToolsMap[Tool]>;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Sorry! Tool ${key} is not supported yet. Options: ${params}`,
|
||||
);
|
||||
}
|
||||
|
||||
export async function createTools<const Tool extends Tools>(record: {
|
||||
[key in Tool]: ConstructorParameters<ToolsMap[Tool]>[1] extends any // backward compatibility for `create-llama` script // if parameters are an array, use them as is
|
||||
? ConstructorParameters<ToolsMap[Tool]>[0]
|
||||
: ConstructorParameters<ToolsMap[Tool]>;
|
||||
}): Promise<InstanceType<ToolsMap[Tool]>[]> {
|
||||
const tools: InstanceType<ToolsMap[Tool]>[] = [];
|
||||
for (const key in record) {
|
||||
const params = record[key];
|
||||
tools.push(
|
||||
await createTool(
|
||||
key,
|
||||
// @ts-expect-error
|
||||
Array.isArray(params) ? params : [params],
|
||||
),
|
||||
);
|
||||
}
|
||||
return tools;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,17 @@
|
||||
import type { JSONSchemaType } from "ajv";
|
||||
import { default as wiki } from "wikipedia";
|
||||
import type { BaseTool, ToolMetadata } from "../types.js";
|
||||
|
||||
export type WikipediaToolParams = {
|
||||
metadata?: ToolMetadata;
|
||||
};
|
||||
|
||||
type WikipediaCallParams = {
|
||||
type WikipediaParameter = {
|
||||
query: string;
|
||||
lang?: string;
|
||||
};
|
||||
|
||||
const DEFAULT_META_DATA: ToolMetadata = {
|
||||
export type WikipediaToolParams = {
|
||||
metadata?: ToolMetadata<JSONSchemaType<WikipediaParameter>>;
|
||||
};
|
||||
|
||||
const DEFAULT_META_DATA: ToolMetadata<JSONSchemaType<WikipediaParameter>> = {
|
||||
name: "wikipedia_tool",
|
||||
description: "A tool that uses a query engine to search Wikipedia.",
|
||||
parameters: {
|
||||
@@ -20,14 +21,19 @@ const DEFAULT_META_DATA: ToolMetadata = {
|
||||
type: "string",
|
||||
description: "The query to search for",
|
||||
},
|
||||
lang: {
|
||||
type: "string",
|
||||
description: "The language to search in",
|
||||
nullable: true,
|
||||
},
|
||||
},
|
||||
required: ["query"],
|
||||
},
|
||||
};
|
||||
|
||||
export class WikipediaTool implements BaseTool {
|
||||
export class WikipediaTool implements BaseTool<WikipediaParameter> {
|
||||
private readonly DEFAULT_LANG = "en";
|
||||
metadata: ToolMetadata;
|
||||
metadata: ToolMetadata<JSONSchemaType<WikipediaParameter>>;
|
||||
|
||||
constructor(params?: WikipediaToolParams) {
|
||||
this.metadata = params?.metadata || DEFAULT_META_DATA;
|
||||
@@ -46,7 +52,7 @@ export class WikipediaTool implements BaseTool {
|
||||
async call({
|
||||
query,
|
||||
lang = this.DEFAULT_LANG,
|
||||
}: WikipediaCallParams): Promise<string> {
|
||||
}: WikipediaParameter): Promise<string> {
|
||||
const searchResult = await wiki.default.search(query);
|
||||
if (searchResult.results.length === 0) return "No search results.";
|
||||
return await this.loadData(searchResult.results[0].title, lang);
|
||||
|
||||
@@ -1,32 +1,30 @@
|
||||
import type { JSONSchemaType } from "ajv";
|
||||
import type { BaseTool, ToolMetadata } from "../types.js";
|
||||
|
||||
type Metadata = {
|
||||
name: string;
|
||||
description: string;
|
||||
parameters: ToolMetadata["parameters"];
|
||||
};
|
||||
export class FunctionTool<T, R extends string | Promise<string>>
|
||||
implements BaseTool<T>
|
||||
{
|
||||
constructor(
|
||||
private readonly _fn: (input: T) => R,
|
||||
private readonly _metadata: ToolMetadata<JSONSchemaType<T>>,
|
||||
) {}
|
||||
|
||||
export class FunctionTool<T = any> implements BaseTool {
|
||||
private _fn: (...args: any[]) => any;
|
||||
private _metadata: ToolMetadata;
|
||||
|
||||
constructor(fn: (...args: any[]) => any, metadata: Metadata) {
|
||||
this._fn = fn;
|
||||
this._metadata = metadata as ToolMetadata;
|
||||
static from<T>(
|
||||
fn: (input: T) => string | Promise<string>,
|
||||
schema: ToolMetadata<JSONSchemaType<T>>,
|
||||
): FunctionTool<T, string | Promise<string>>;
|
||||
static from<T, R extends string | Promise<string>>(
|
||||
fn: (input: T) => R,
|
||||
schema: ToolMetadata<JSONSchemaType<T>>,
|
||||
): FunctionTool<T, R> {
|
||||
return new FunctionTool(fn, schema);
|
||||
}
|
||||
|
||||
static fromDefaults<T = any>(
|
||||
fn: (...args: any[]) => any,
|
||||
metadata?: Metadata,
|
||||
): FunctionTool<T> {
|
||||
return new FunctionTool(fn, metadata!);
|
||||
get metadata(): BaseTool<T>["metadata"] {
|
||||
return this._metadata as BaseTool<T>["metadata"];
|
||||
}
|
||||
|
||||
get metadata(): ToolMetadata {
|
||||
return this._metadata;
|
||||
}
|
||||
|
||||
async call(...args: any[]): Promise<any> {
|
||||
return this._fn(...args);
|
||||
call(input: T) {
|
||||
return this._fn(input);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
export * from "./QueryEngineTool.js";
|
||||
export * from "./ToolFactory.js";
|
||||
export * from "./WikipediaTool.js";
|
||||
export * from "./functionTool.js";
|
||||
export * from "./types.js";
|
||||
|
||||
@@ -1,30 +1,24 @@
|
||||
import type { BaseTool } from "../types.js";
|
||||
import { ToolOutput } from "./types.js";
|
||||
|
||||
/**
|
||||
* Call tool with error handling.
|
||||
* @param tool: tool
|
||||
* @param inputDict: input dict
|
||||
* @param errorMessage: error message
|
||||
* @param raiseError: raise error
|
||||
* @returns: tool output
|
||||
*/
|
||||
export async function callToolWithErrorHandling(
|
||||
tool: BaseTool,
|
||||
inputDict: { [key: string]: any },
|
||||
errorMessage: string | null = null,
|
||||
raiseError: boolean = false,
|
||||
): Promise<ToolOutput> {
|
||||
if (!tool.call) {
|
||||
return new ToolOutput(
|
||||
"Error: Tool does not have a call function.",
|
||||
tool.metadata.name,
|
||||
{ kwargs: inputDict },
|
||||
null,
|
||||
);
|
||||
}
|
||||
try {
|
||||
const value = await tool.call?.(inputDict);
|
||||
const value = await tool.call(inputDict);
|
||||
return new ToolOutput(value, tool.metadata.name, inputDict, value);
|
||||
} catch (e) {
|
||||
if (raiseError) {
|
||||
throw e;
|
||||
}
|
||||
errorMessage = errorMessage || `Error: ${e}`;
|
||||
return new ToolOutput(
|
||||
errorMessage,
|
||||
`Error: ${e}`,
|
||||
tool.metadata.name,
|
||||
{ kwargs: inputDict },
|
||||
e,
|
||||
|
||||
+36
-16
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* Top level types to avoid circular dependencies
|
||||
*/
|
||||
import { type JSONSchemaType } from "ajv";
|
||||
import type { Response } from "./Response.js";
|
||||
|
||||
/**
|
||||
@@ -30,14 +31,46 @@ export interface BaseQueryEngine {
|
||||
query(params: QueryEngineParamsNonStreaming): Promise<Response>;
|
||||
}
|
||||
|
||||
type Known =
|
||||
| { [key: string]: Known }
|
||||
| [Known, ...Known[]]
|
||||
| Known[]
|
||||
| number
|
||||
| string
|
||||
| boolean
|
||||
| null;
|
||||
|
||||
export type ToolMetadata<
|
||||
Parameters extends Record<string, unknown> = Record<string, unknown>,
|
||||
> = {
|
||||
description: string;
|
||||
name: string;
|
||||
/**
|
||||
* OpenAI uses JSON Schema to describe the parameters that a tool can take.
|
||||
* @link https://json-schema.org/understanding-json-schema
|
||||
*/
|
||||
parameters?: Parameters;
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple Tool interface. Likely to change.
|
||||
*/
|
||||
export interface BaseTool {
|
||||
call?: (...args: any[]) => any;
|
||||
metadata: ToolMetadata;
|
||||
export interface BaseTool<Input = any> {
|
||||
/**
|
||||
* This could be undefined if the implementation is not provided,
|
||||
* which might be the case when communicating with a llm.
|
||||
*
|
||||
* @return string - the output of the tool, should be string in any case for LLM input.
|
||||
*/
|
||||
call?: (input: Input) => string | Promise<string>;
|
||||
metadata: // if user input any, we cannot check the schema
|
||||
Input extends Known ? ToolMetadata<JSONSchemaType<Input>> : ToolMetadata;
|
||||
}
|
||||
|
||||
export type ToolWithCall<Input = unknown> = Omit<BaseTool<Input>, "call"> & {
|
||||
call: NonNullable<Pick<BaseTool<Input>, "call">["call"]>;
|
||||
};
|
||||
|
||||
/**
|
||||
* An OutputParser is used to extract structured data from the raw output of the LLM.
|
||||
*/
|
||||
@@ -55,19 +88,6 @@ export interface StructuredOutput<T> {
|
||||
parsedOutput: T;
|
||||
}
|
||||
|
||||
export type ToolParameters = {
|
||||
type: string | "object";
|
||||
properties: Record<string, { type: string; description?: string }>;
|
||||
required?: string[];
|
||||
};
|
||||
|
||||
export interface ToolMetadata {
|
||||
description: string;
|
||||
name: string;
|
||||
parameters?: ToolParameters;
|
||||
argsKwargs?: Record<string, any>;
|
||||
}
|
||||
|
||||
export type ToolMetadataOnlyDescription = Pick<ToolMetadata, "description">;
|
||||
|
||||
export class QueryBundle {
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
import { Settings } from "llamaindex";
|
||||
import { OpenAIAgent } from "llamaindex/agent/index";
|
||||
import { OpenAI } from "llamaindex/llm/index";
|
||||
import { FunctionTool } from "llamaindex/tools/index";
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { mockLlmToolCallGeneration } from "../utility/mockOpenAI.js";
|
||||
|
||||
// Define a function to sum two numbers
|
||||
function sumNumbers({ a, b }: { a: number; b: number }): number {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
const sumJSON = {
|
||||
type: "object",
|
||||
properties: {
|
||||
a: {
|
||||
type: "number",
|
||||
description: "The first number",
|
||||
},
|
||||
b: {
|
||||
type: "number",
|
||||
description: "The second number",
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
};
|
||||
|
||||
describe("OpenAIAgent", () => {
|
||||
let openaiAgent: OpenAIAgent;
|
||||
|
||||
beforeEach(() => {
|
||||
const languageModel = new OpenAI({
|
||||
model: "gpt-3.5-turbo",
|
||||
});
|
||||
|
||||
Settings.llm = languageModel;
|
||||
|
||||
mockLlmToolCallGeneration({
|
||||
languageModel,
|
||||
});
|
||||
|
||||
const sumFunctionTool = new FunctionTool(sumNumbers, {
|
||||
name: "sumNumbers",
|
||||
description: "Use this function to sum two numbers",
|
||||
parameters: sumJSON,
|
||||
});
|
||||
|
||||
openaiAgent = new OpenAIAgent({
|
||||
tools: [sumFunctionTool],
|
||||
llm: languageModel,
|
||||
});
|
||||
});
|
||||
|
||||
it("should be able to chat with agent", async () => {
|
||||
const response = await openaiAgent.chat({
|
||||
message: "how much is 1 + 1?",
|
||||
});
|
||||
|
||||
expect(String(response)).toEqual("The sum is 2");
|
||||
});
|
||||
});
|
||||
@@ -17,7 +17,7 @@ describe("ObjectIndex", () => {
|
||||
});
|
||||
|
||||
test("test_object_with_tools", async () => {
|
||||
const tool1 = new FunctionTool((x: any) => x, {
|
||||
const tool1 = new FunctionTool(({ x }: { x: string }) => x, {
|
||||
name: "test_tool",
|
||||
description: "test tool",
|
||||
parameters: {
|
||||
@@ -27,10 +27,11 @@ describe("ObjectIndex", () => {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["x"],
|
||||
},
|
||||
});
|
||||
|
||||
const tool2 = new FunctionTool((x: any) => x, {
|
||||
const tool2 = new FunctionTool(({ x }: { x: string }) => x, {
|
||||
name: "test_tool_2",
|
||||
description: "test tool 2",
|
||||
parameters: {
|
||||
@@ -40,6 +41,7 @@ describe("ObjectIndex", () => {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["x"],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -62,7 +64,7 @@ describe("ObjectIndex", () => {
|
||||
});
|
||||
|
||||
test("add a new object", async () => {
|
||||
const tool1 = new FunctionTool((x: any) => x, {
|
||||
const tool1 = new FunctionTool(({ x }: { x: string }) => x, {
|
||||
name: "test_tool",
|
||||
description: "test tool",
|
||||
parameters: {
|
||||
@@ -72,10 +74,11 @@ describe("ObjectIndex", () => {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["x"],
|
||||
},
|
||||
});
|
||||
|
||||
const tool2 = new FunctionTool((x: any) => x, {
|
||||
const tool2 = new FunctionTool(({ x }: { x: string }) => x, {
|
||||
name: "test_tool_2",
|
||||
description: "test tool 2",
|
||||
parameters: {
|
||||
@@ -85,6 +88,7 @@ describe("ObjectIndex", () => {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["x"],
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { ToolsFactory } from "llamaindex/tools/ToolsFactory";
|
||||
import { WikipediaTool } from "llamaindex/tools/WikipediaTool";
|
||||
import { assertType, describe, test } from "vitest";
|
||||
|
||||
describe("ToolsFactory", async () => {
|
||||
test("createTool", async () => {
|
||||
await ToolsFactory.createTool(ToolsFactory.Tools.Wikipedia, {
|
||||
metadata: {
|
||||
name: "wikipedia_tool",
|
||||
description: "A tool that uses a query engine to search Wikipedia.",
|
||||
},
|
||||
});
|
||||
});
|
||||
test("createTools", async () => {
|
||||
await ToolsFactory.createTools({
|
||||
[ToolsFactory.Tools.Wikipedia]: {
|
||||
metadata: {
|
||||
name: "wikipedia_tool",
|
||||
description: "A tool that uses a query engine to search Wikipedia.",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
test("type", () => {
|
||||
assertType<
|
||||
(
|
||||
key: ToolsFactory.Tools.Wikipedia,
|
||||
params: ConstructorParameters<typeof WikipediaTool>[0],
|
||||
) => Promise<WikipediaTool>
|
||||
>(ToolsFactory.createTool<ToolsFactory.Tools.Wikipedia>);
|
||||
});
|
||||
});
|
||||
@@ -1,46 +0,0 @@
|
||||
import { FunctionTool, ToolOutput } from "llamaindex/tools/index";
|
||||
import { callToolWithErrorHandling } from "llamaindex/tools/utils";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
function sumNumbers({ a, b }: { a: number; b: number }): number {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
const sumJSON = {
|
||||
type: "object",
|
||||
properties: {
|
||||
a: {
|
||||
type: "number",
|
||||
description: "The first number",
|
||||
},
|
||||
b: {
|
||||
type: "number",
|
||||
description: "The second number",
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
};
|
||||
|
||||
describe("Tools", () => {
|
||||
it("should be able to call a tool with a common JSON", async () => {
|
||||
const tool = new FunctionTool(sumNumbers, {
|
||||
name: "sumNumbers",
|
||||
description: "Use this function to sum two numbers",
|
||||
parameters: sumJSON,
|
||||
});
|
||||
|
||||
const response = await callToolWithErrorHandling(tool, {
|
||||
a: 1,
|
||||
b: 2,
|
||||
});
|
||||
|
||||
expect(response).toEqual(
|
||||
new ToolOutput(
|
||||
response.content,
|
||||
tool.metadata.name,
|
||||
{ a: 1, b: 2 },
|
||||
response.content,
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
# @llamaindex/edge
|
||||
|
||||
## 0.2.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @llamaindex/env@0.0.7
|
||||
@@ -1,5 +1,11 @@
|
||||
# test-edge-runtime
|
||||
|
||||
## 0.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @llamaindex/edge@0.2.7
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "test-edge-runtime",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/edge",
|
||||
"version": "0.2.5",
|
||||
"version": "0.2.8",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
@@ -11,18 +11,19 @@
|
||||
"@llamaindex/cloud": "0.0.5",
|
||||
"@llamaindex/env": "workspace:*",
|
||||
"@mistralai/mistralai": "^0.1.3",
|
||||
"@notionhq/client": "^2.2.14",
|
||||
"@notionhq/client": "^2.2.15",
|
||||
"@pinecone-database/pinecone": "^2.2.0",
|
||||
"@qdrant/js-client-rest": "^1.8.2",
|
||||
"@types/lodash": "^4.17.0",
|
||||
"@types/node": "^18.19.31",
|
||||
"@types/node": "^20.12.7",
|
||||
"@types/papaparse": "^5.3.14",
|
||||
"@types/pg": "^8.11.5",
|
||||
"@xenova/transformers": "^2.16.1",
|
||||
"@zilliz/milvus2-sdk-node": "^2.3.5",
|
||||
"ajv": "^8.12.0",
|
||||
"assemblyai": "^4.3.4",
|
||||
"chromadb": "~1.7.3",
|
||||
"cohere-ai": "^7.9.2",
|
||||
"cohere-ai": "^7.9.3",
|
||||
"js-tiktoken": "^1.0.10",
|
||||
"lodash": "^4.17.21",
|
||||
"magic-bytes.js": "^1.10.0",
|
||||
|
||||
Vendored
+6
@@ -1,5 +1,11 @@
|
||||
# @llamaindex/env
|
||||
|
||||
## 0.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Add polyfill for pipeline
|
||||
|
||||
## 0.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
Vendored
+6
-4
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/env",
|
||||
"description": "environment wrapper",
|
||||
"version": "0.0.6",
|
||||
"version": "0.0.7",
|
||||
"type": "module",
|
||||
"types": "dist/type/index.d.ts",
|
||||
"main": "dist/cjs/index.js",
|
||||
@@ -56,16 +56,18 @@
|
||||
"@aws-crypto/sha256-js": "^5.2.0",
|
||||
"@swc/cli": "^0.3.9",
|
||||
"@swc/core": "^1.4.2",
|
||||
"concurrently": "^8.2.2",
|
||||
"pathe": "^1.1.2",
|
||||
"concurrently": "^8.2.2"
|
||||
"readable-stream": "^4.5.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/lodash": "^4.14.202",
|
||||
"@types/node": "^20.11.20",
|
||||
"@types/node": "^20.12.7",
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@aws-crypto/sha256-js": "^5.2.0",
|
||||
"pathe": "^1.1.2"
|
||||
"pathe": "^1.1.2",
|
||||
"readable-stream": "^4.5.2"
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+3
-1
@@ -1,8 +1,10 @@
|
||||
import { Sha256 } from "@aws-crypto/sha256-js";
|
||||
import pathe from "pathe";
|
||||
import { InMemoryFileSystem, type CompleteFileSystem } from "./type.js";
|
||||
// @ts-expect-error
|
||||
import { pipeline } from "readable-stream";
|
||||
|
||||
export { pathe as path };
|
||||
export { pathe as path, pipeline };
|
||||
|
||||
export interface SHA256 {
|
||||
update(data: string | Uint8Array): void;
|
||||
|
||||
Vendored
+2
-1
@@ -3,6 +3,7 @@ import { createHash, randomUUID } from "node:crypto";
|
||||
import fs from "node:fs/promises";
|
||||
import { EOL } from "node:os";
|
||||
import path from "node:path";
|
||||
import { pipeline } from "node:stream/promises";
|
||||
import type { SHA256 } from "./index.polyfill.js";
|
||||
import type { CompleteFileSystem } from "./type.js";
|
||||
|
||||
@@ -36,4 +37,4 @@ export const defaultFS: CompleteFileSystem = {
|
||||
|
||||
export type * from "./type.js";
|
||||
export { AsyncLocalStorage, CustomEvent, getEnv } from "./utils.js";
|
||||
export { EOL, ok, path, randomUUID };
|
||||
export { EOL, ok, path, pipeline, randomUUID };
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# @llamaindex/experimental
|
||||
|
||||
## 0.0.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- llamaindex@0.2.8
|
||||
|
||||
## 0.0.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [96f8f40]
|
||||
- llamaindex@0.2.7
|
||||
|
||||
## 0.0.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a3b4409]
|
||||
- llamaindex@0.2.6
|
||||
|
||||
## 0.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"llamaindex": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.19.10",
|
||||
"@types/node": "^20.12.7",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.3"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/experimental",
|
||||
"description": "Experimental package for LlamaIndexTS",
|
||||
"version": "0.0.8",
|
||||
"version": "0.0.11",
|
||||
"type": "module",
|
||||
"types": "dist/type/index.d.ts",
|
||||
"main": "dist/cjs/index.js",
|
||||
@@ -63,7 +63,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/lodash": "^4.14.202",
|
||||
"@types/node": "^20.11.20",
|
||||
"@types/node": "^20.12.7",
|
||||
"jsonpath": "^1.1.1",
|
||||
"llamaindex": "workspace:*",
|
||||
"lodash": "^4.17.21"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@types/node": "^18.19.14",
|
||||
"@types/node": "^20.12.7",
|
||||
"@assemblyscript/loader": "^0.19.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
Generated
+239
-235
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user