mirror of
https://github.com/run-llama/LlamaIndexTS.git
synced 2026-07-07 00:31:11 -04:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 051b4ddfa2 | |||
| 61103b677b | |||
| e69cac672a | |||
| 94246a3ca8 | |||
| b440a008e5 | |||
| 46227f2a70 | |||
| 77f0298f6f |
@@ -1,5 +1,19 @@
|
||||
# docs
|
||||
|
||||
## 0.0.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [61103b6]
|
||||
- llamaindex@0.3.2
|
||||
|
||||
## 0.0.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [46227f2]
|
||||
- llamaindex@0.3.1
|
||||
|
||||
## 0.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -72,12 +72,8 @@ export class MyAgent extends AgentRunner<MyLLM> {
|
||||
// create store is a function to create a store for each task, by default it only includes `messages` and `toolOutputs`
|
||||
createStore = AgentRunner.defaultCreateStore;
|
||||
|
||||
static taskHandler: TaskHandler<Anthropic> = async (step) => {
|
||||
const { input } = step;
|
||||
static taskHandler: TaskHandler<Anthropic> = async (step, enqueueOutput) => {
|
||||
const { llm, stream } = step.context;
|
||||
if (input) {
|
||||
step.context.store.messages = [...step.context.store.messages, input];
|
||||
}
|
||||
// initialize the input
|
||||
const response = await llm.chat({
|
||||
stream,
|
||||
@@ -90,27 +86,21 @@ export class MyAgent extends AgentRunner<MyLLM> {
|
||||
];
|
||||
// your logic here to decide whether to continue the task
|
||||
const shouldContinue = Math.random(); /* <-- replace with your logic here */
|
||||
enqueueOutput({
|
||||
taskStep: step,
|
||||
output: response,
|
||||
isLast: !shouldContinue,
|
||||
});
|
||||
if (shouldContinue) {
|
||||
const content = await someHeavyFunctionCall();
|
||||
// if you want to continue the task, you can insert your new context for the next task step
|
||||
step.context.store.messages = [
|
||||
...step.context.store.messages,
|
||||
{
|
||||
content: "INSERT MY NEW DATA",
|
||||
content,
|
||||
role: "user",
|
||||
},
|
||||
];
|
||||
return {
|
||||
taskStep: step,
|
||||
output: response,
|
||||
isLast: false,
|
||||
};
|
||||
} else {
|
||||
// if you want to end the task, you can return the response with `isLast: true`
|
||||
return {
|
||||
taskStep: step,
|
||||
output: response,
|
||||
isLast: true,
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -263,6 +253,9 @@ const sumNumbers = FunctionTool.from<Input>(
|
||||
In addition to Node.js, LlamaIndexTS now offers enhanced support for Next.js, Deno, and Cloudflare Workers, making it
|
||||
more versatile across different platforms.
|
||||
|
||||
For now, you can install llamaindex and directly import it into your existing Next.js, Deno or Cloudflare Worker project
|
||||
**without any extra configuration**.
|
||||
|
||||
#### [Deno](https://deno.com/)
|
||||
|
||||
You can use LlamaIndexTS in Deno by installation through JSR:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docs",
|
||||
"version": "0.0.8",
|
||||
"version": "0.0.10",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import { ChatResponseChunk, FunctionTool, OpenAIAgent } from "llamaindex";
|
||||
import { ReadableStream } from "node:stream/web";
|
||||
|
||||
const functionTool = FunctionTool.from(
|
||||
() => {
|
||||
console.log("Getting user id...");
|
||||
return crypto.randomUUID();
|
||||
},
|
||||
{
|
||||
name: "get_user_id",
|
||||
description: "Get a random user id",
|
||||
},
|
||||
);
|
||||
|
||||
const functionTool2 = FunctionTool.from(
|
||||
({ userId }: { userId: string }) => {
|
||||
console.log("Getting user info...", userId);
|
||||
return `Name: Alex; Address: 1234 Main St, CA; User ID: ${userId}`;
|
||||
},
|
||||
{
|
||||
name: "get_user_info",
|
||||
description: "Get user info",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
userId: {
|
||||
type: "string",
|
||||
description: "The user id",
|
||||
},
|
||||
},
|
||||
required: ["userId"],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const functionTool3 = FunctionTool.from(
|
||||
({ address }: { address: string }) => {
|
||||
console.log("Getting weather...", address);
|
||||
return `${address} is in a sunny location!`;
|
||||
},
|
||||
{
|
||||
name: "get_weather",
|
||||
description: "Get the current weather for a location",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
address: {
|
||||
type: "string",
|
||||
description: "The address",
|
||||
},
|
||||
},
|
||||
required: ["address"],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
async function main() {
|
||||
// Create an OpenAIAgent with the function tools
|
||||
const agent = new OpenAIAgent({
|
||||
tools: [functionTool, functionTool2, functionTool3],
|
||||
});
|
||||
|
||||
const task = await agent.createTask(
|
||||
"What is my current address weather based on my profile?",
|
||||
true,
|
||||
);
|
||||
|
||||
for await (const stepOutput of task) {
|
||||
const stream = stepOutput.output as ReadableStream<ChatResponseChunk>;
|
||||
if (stepOutput.isLast) {
|
||||
for await (const chunk of stream) {
|
||||
process.stdout.write(chunk.delta);
|
||||
}
|
||||
process.stdout.write("\n");
|
||||
} else {
|
||||
// handing function call
|
||||
console.log("handling function call...");
|
||||
for await (const chunk of stream) {
|
||||
console.log("debug:", JSON.stringify(chunk.raw));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main().then(() => {
|
||||
console.log("Done");
|
||||
});
|
||||
@@ -1,97 +0,0 @@
|
||||
import { FunctionTool, OpenAIAgent } from "llamaindex";
|
||||
import { ReadableStream } from "node:stream/web";
|
||||
|
||||
// Define a function to sum two numbers
|
||||
function sumNumbers({ a, b }: { a: number; b: number }) {
|
||||
return `${a + b}`;
|
||||
}
|
||||
|
||||
// Define a function to divide two numbers
|
||||
function divideNumbers({ a, b }: { a: number; b: number }) {
|
||||
return `${a / b}`;
|
||||
}
|
||||
|
||||
// Define the parameters of the sum function as a JSON schema
|
||||
const sumJSON = {
|
||||
type: "object",
|
||||
properties: {
|
||||
a: {
|
||||
type: "number",
|
||||
description: "The first number",
|
||||
},
|
||||
b: {
|
||||
type: "number",
|
||||
description: "The second number",
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
} as const;
|
||||
|
||||
const divideJSON = {
|
||||
type: "object",
|
||||
properties: {
|
||||
a: {
|
||||
type: "number",
|
||||
description: "The dividend",
|
||||
},
|
||||
b: {
|
||||
type: "number",
|
||||
description: "The divisor",
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
} as const;
|
||||
|
||||
async function main() {
|
||||
// Create a function tool from the sum function
|
||||
const functionTool = new FunctionTool(sumNumbers, {
|
||||
name: "sumNumbers",
|
||||
description: "Use this function to sum two numbers",
|
||||
parameters: sumJSON,
|
||||
});
|
||||
|
||||
// Create a function tool from the divide function
|
||||
const functionTool2 = new FunctionTool(divideNumbers, {
|
||||
name: "divideNumbers",
|
||||
description: "Use this function to divide two numbers",
|
||||
parameters: divideJSON,
|
||||
});
|
||||
|
||||
// Create an OpenAIAgent with the function tools
|
||||
const agent = new OpenAIAgent({
|
||||
tools: [functionTool, functionTool2],
|
||||
});
|
||||
|
||||
// Create a task to sum and divide numbers
|
||||
const task = await agent.createTask("How much is 5 + 5? then divide by 2");
|
||||
|
||||
let count = 0;
|
||||
|
||||
for await (const stepOutput of task) {
|
||||
console.log(`Runnning step ${count++}`);
|
||||
console.log(`======== OUTPUT ==========`);
|
||||
const output = stepOutput.output;
|
||||
if (output instanceof ReadableStream) {
|
||||
for await (const chunk of output) {
|
||||
process.stdout.write(chunk.delta);
|
||||
}
|
||||
} else {
|
||||
console.log(output);
|
||||
}
|
||||
console.log(`==========================`);
|
||||
|
||||
if (stepOutput.isLast) {
|
||||
if (stepOutput.output instanceof ReadableStream) {
|
||||
for await (const chunk of stepOutput.output) {
|
||||
process.stdout.write(chunk.delta);
|
||||
}
|
||||
} else {
|
||||
console.log(stepOutput.output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main().then(() => {
|
||||
console.log("Done");
|
||||
});
|
||||
@@ -1,5 +1,17 @@
|
||||
# llamaindex
|
||||
|
||||
## 0.3.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 61103b6: fix: streaming for `Agent.createTask` API
|
||||
|
||||
## 0.3.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 46227f2: fix: build error on next.js nodejs runtime
|
||||
|
||||
## 0.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# @llamaindex/core-e2e
|
||||
|
||||
## 0.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 61103b6: fix: streaming for `Agent.createTask` API
|
||||
@@ -1,5 +1,19 @@
|
||||
# @llamaindex/cloudflare-worker-agent-test
|
||||
|
||||
## 0.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [61103b6]
|
||||
- llamaindex@0.3.2
|
||||
|
||||
## 0.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [46227f2]
|
||||
- llamaindex@0.3.1
|
||||
|
||||
## 0.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/cloudflare-worker-agent-test",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.3",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# @llamaindex/next-agent-test
|
||||
|
||||
## 0.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [61103b6]
|
||||
- llamaindex@0.3.2
|
||||
|
||||
## 0.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [46227f2]
|
||||
- llamaindex@0.3.1
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/next-agent-test",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.3",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import "llamaindex";
|
||||
|
||||
export default function Page() {
|
||||
return "hello world!";
|
||||
}
|
||||
@@ -1,5 +1,12 @@
|
||||
# test-edge-runtime
|
||||
|
||||
## 0.1.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [46227f2]
|
||||
- @llamaindex/edge@0.3.1
|
||||
|
||||
## 0.1.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/nextjs-edge-runtime-test",
|
||||
"version": "0.1.5",
|
||||
"version": "0.1.6",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# @llamaindex/waku-query-engine-test
|
||||
|
||||
## 0.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [61103b6]
|
||||
- llamaindex@0.3.2
|
||||
|
||||
## 0.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [46227f2]
|
||||
- llamaindex@0.3.1
|
||||
|
||||
## 0.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/waku-query-engine-test",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.3",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/core-e2e",
|
||||
"private": true,
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.3",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"e2e": "node --import tsx --import ./mock-register.js --test ./node/*.e2e.ts",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/core",
|
||||
"version": "0.2.3",
|
||||
"version": "0.3.2",
|
||||
"exports": "./src/index.ts",
|
||||
"imports": {
|
||||
"@llamaindex/env": "jsr:@llamaindex/env@0.0.6"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "llamaindex",
|
||||
"version": "0.3.0",
|
||||
"version": "0.3.2",
|
||||
"expectedMinorVersion": "3",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
||||
@@ -67,12 +67,8 @@ export class AnthropicAgent extends AgentRunner<Anthropic> {
|
||||
return super.chat(params);
|
||||
}
|
||||
|
||||
static taskHandler: TaskHandler<Anthropic> = async (step) => {
|
||||
const { input } = step;
|
||||
static taskHandler: TaskHandler<Anthropic> = async (step, enqueueOutput) => {
|
||||
const { llm, getTools, stream } = step.context;
|
||||
if (input) {
|
||||
step.context.store.messages = [...step.context.store.messages, input];
|
||||
}
|
||||
const lastMessage = step.context.store.messages.at(-1)!.content;
|
||||
const tools = await getTools(lastMessage);
|
||||
if (stream === true) {
|
||||
@@ -88,6 +84,11 @@ export class AnthropicAgent extends AgentRunner<Anthropic> {
|
||||
response.message,
|
||||
];
|
||||
const options = response.message.options ?? {};
|
||||
enqueueOutput({
|
||||
taskStep: step,
|
||||
output: response,
|
||||
isLast: !("toolCall" in options),
|
||||
});
|
||||
if ("toolCall" in options) {
|
||||
const { toolCall } = options;
|
||||
const targetTool = tools.find(
|
||||
@@ -95,30 +96,20 @@ export class AnthropicAgent extends AgentRunner<Anthropic> {
|
||||
);
|
||||
const toolOutput = await callTool(targetTool, toolCall);
|
||||
step.context.store.toolOutputs.push(toolOutput);
|
||||
return {
|
||||
taskStep: step,
|
||||
output: {
|
||||
raw: response.raw,
|
||||
message: {
|
||||
content: stringifyJSONToMessageContent(toolOutput.output),
|
||||
role: "user",
|
||||
options: {
|
||||
toolResult: {
|
||||
result: toolOutput.output,
|
||||
isError: toolOutput.isError,
|
||||
id: toolCall.id,
|
||||
},
|
||||
step.context.store.messages = [
|
||||
...step.context.store.messages,
|
||||
{
|
||||
content: stringifyJSONToMessageContent(toolOutput.output),
|
||||
role: "user",
|
||||
options: {
|
||||
toolResult: {
|
||||
result: toolOutput.output,
|
||||
isError: toolOutput.isError,
|
||||
id: toolCall.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
isLast: false,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
taskStep: step,
|
||||
output: response,
|
||||
isLast: true,
|
||||
};
|
||||
];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,14 +27,10 @@ import type {
|
||||
TaskStep,
|
||||
TaskStepOutput,
|
||||
} from "./types.js";
|
||||
import { consumeAsyncIterable } from "./utils.js";
|
||||
|
||||
export const MAX_TOOL_CALLS = 10;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export async function* createTaskImpl<
|
||||
export function createTaskOutputStream<
|
||||
Model extends LLM,
|
||||
Store extends object = {},
|
||||
AdditionalMessageOptions extends object = Model extends LLM<
|
||||
@@ -46,65 +42,60 @@ export async function* createTaskImpl<
|
||||
>(
|
||||
handler: TaskHandler<Model, Store, AdditionalMessageOptions>,
|
||||
context: AgentTaskContext<Model, Store, AdditionalMessageOptions>,
|
||||
_input: ChatMessage<AdditionalMessageOptions>,
|
||||
): AsyncGenerator<TaskStepOutput<Model, Store, AdditionalMessageOptions>> {
|
||||
let isFirst = true;
|
||||
let isDone = false;
|
||||
let input: ChatMessage<AdditionalMessageOptions> | null = _input;
|
||||
let prevStep: TaskStep<Model, Store, AdditionalMessageOptions> | null = null;
|
||||
while (!isDone) {
|
||||
const step: TaskStep<Model, Store, AdditionalMessageOptions> = {
|
||||
id: randomUUID(),
|
||||
input,
|
||||
context,
|
||||
prevStep,
|
||||
nextSteps: new Set(),
|
||||
};
|
||||
if (prevStep) {
|
||||
prevStep.nextSteps.add(step);
|
||||
}
|
||||
const prevToolCallCount = step.context.toolCallCount;
|
||||
if (!step.context.shouldContinue(step)) {
|
||||
throw new Error("Tool call count exceeded limit");
|
||||
}
|
||||
if (isFirst) {
|
||||
): ReadableStream<TaskStepOutput<Model, Store, AdditionalMessageOptions>> {
|
||||
const steps: TaskStep<Model, Store, AdditionalMessageOptions>[] = [];
|
||||
return new ReadableStream<
|
||||
TaskStepOutput<Model, Store, AdditionalMessageOptions>
|
||||
>({
|
||||
pull: async (controller) => {
|
||||
const step: TaskStep<Model, Store, AdditionalMessageOptions> = {
|
||||
id: randomUUID(),
|
||||
context,
|
||||
prevStep: null,
|
||||
nextSteps: new Set(),
|
||||
};
|
||||
if (steps.length > 0) {
|
||||
step.prevStep = steps[steps.length - 1];
|
||||
}
|
||||
const taskOutputs: TaskStepOutput<
|
||||
Model,
|
||||
Store,
|
||||
AdditionalMessageOptions
|
||||
>[] = [];
|
||||
steps.push(step);
|
||||
const enqueueOutput = (
|
||||
output: TaskStepOutput<Model, Store, AdditionalMessageOptions>,
|
||||
) => {
|
||||
taskOutputs.push(output);
|
||||
controller.enqueue(output);
|
||||
};
|
||||
getCallbackManager().dispatchEvent("agent-start", {
|
||||
payload: {
|
||||
startStep: step,
|
||||
},
|
||||
});
|
||||
isFirst = false;
|
||||
}
|
||||
const taskOutput = await handler(step);
|
||||
const { isLast, output, taskStep } = taskOutput;
|
||||
// do not consume last output
|
||||
if (!isLast) {
|
||||
if (output) {
|
||||
input = isAsyncIterable(output)
|
||||
? await consumeAsyncIterable(output)
|
||||
: output.message;
|
||||
} else {
|
||||
input = null;
|
||||
}
|
||||
}
|
||||
context = {
|
||||
...taskStep.context,
|
||||
store: {
|
||||
...taskStep.context.store,
|
||||
},
|
||||
toolCallCount: prevToolCallCount + 1,
|
||||
};
|
||||
if (isLast) {
|
||||
isDone = true;
|
||||
getCallbackManager().dispatchEvent("agent-end", {
|
||||
payload: {
|
||||
endStep: step,
|
||||
|
||||
await handler(step, enqueueOutput);
|
||||
// fixme: support multi-thread when there are multiple outputs
|
||||
// todo: for now we pretend there is only one task output
|
||||
const { isLast, taskStep } = taskOutputs[0];
|
||||
context = {
|
||||
...taskStep.context,
|
||||
store: {
|
||||
...taskStep.context.store,
|
||||
},
|
||||
});
|
||||
}
|
||||
prevStep = taskStep;
|
||||
yield taskOutput;
|
||||
}
|
||||
toolCallCount: 1,
|
||||
};
|
||||
if (isLast) {
|
||||
getCallbackManager().dispatchEvent("agent-end", {
|
||||
payload: {
|
||||
endStep: step,
|
||||
},
|
||||
});
|
||||
controller.close();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export type AgentStreamChatResponse<Options extends object> = {
|
||||
@@ -170,15 +161,16 @@ export abstract class AgentWorker<
|
||||
query: string,
|
||||
context: AgentTaskContext<AI, Store, AdditionalMessageOptions>,
|
||||
): ReadableStream<TaskStepOutput<AI, Store, AdditionalMessageOptions>> {
|
||||
const taskGenerator = createTaskImpl(this.taskHandler, context, {
|
||||
context.store.messages.push({
|
||||
role: "user",
|
||||
content: query,
|
||||
});
|
||||
const taskOutputStream = createTaskOutputStream(this.taskHandler, context);
|
||||
return new ReadableStream<
|
||||
TaskStepOutput<AI, Store, AdditionalMessageOptions>
|
||||
>({
|
||||
start: async (controller) => {
|
||||
for await (const stepOutput of taskGenerator) {
|
||||
for await (const stepOutput of taskOutputStream) {
|
||||
this.#taskSet.add(stepOutput.taskStep);
|
||||
controller.enqueue(stepOutput);
|
||||
if (stepOutput.isLast) {
|
||||
|
||||
@@ -51,12 +51,8 @@ export class OpenAIAgent extends AgentRunner<OpenAI> {
|
||||
|
||||
createStore = AgentRunner.defaultCreateStore;
|
||||
|
||||
static taskHandler: TaskHandler<OpenAI> = async (step) => {
|
||||
const { input } = step;
|
||||
static taskHandler: TaskHandler<OpenAI> = async (step, enqueueOutput) => {
|
||||
const { llm, stream, getTools } = step.context;
|
||||
if (input) {
|
||||
step.context.store.messages = [...step.context.store.messages, input];
|
||||
}
|
||||
const lastMessage = step.context.store.messages.at(-1)!.content;
|
||||
const tools = await getTools(lastMessage);
|
||||
const response = await llm.chat({
|
||||
@@ -71,6 +67,11 @@ export class OpenAIAgent extends AgentRunner<OpenAI> {
|
||||
response.message,
|
||||
];
|
||||
const options = response.message.options ?? {};
|
||||
enqueueOutput({
|
||||
taskStep: step,
|
||||
output: response,
|
||||
isLast: !("toolCall" in options),
|
||||
});
|
||||
if ("toolCall" in options) {
|
||||
const { toolCall } = options;
|
||||
const targetTool = tools.find(
|
||||
@@ -78,30 +79,20 @@ export class OpenAIAgent extends AgentRunner<OpenAI> {
|
||||
);
|
||||
const toolOutput = await callTool(targetTool, toolCall);
|
||||
step.context.store.toolOutputs.push(toolOutput);
|
||||
return {
|
||||
taskStep: step,
|
||||
output: {
|
||||
raw: response.raw,
|
||||
message: {
|
||||
content: stringifyJSONToMessageContent(toolOutput.output),
|
||||
role: "user",
|
||||
options: {
|
||||
toolResult: {
|
||||
result: toolOutput.output,
|
||||
isError: toolOutput.isError,
|
||||
id: toolCall.id,
|
||||
},
|
||||
step.context.store.messages = [
|
||||
...step.context.store.messages,
|
||||
{
|
||||
role: "user" as const,
|
||||
content: stringifyJSONToMessageContent(toolOutput.output),
|
||||
options: {
|
||||
toolResult: {
|
||||
result: toolOutput.output,
|
||||
isError: toolOutput.isError,
|
||||
id: toolCall.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
isLast: false,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
taskStep: step,
|
||||
output: response,
|
||||
isLast: true,
|
||||
};
|
||||
];
|
||||
}
|
||||
} else {
|
||||
const responseChunkStream = new ReadableStream<
|
||||
@@ -126,6 +117,11 @@ export class OpenAIAgent extends AgentRunner<OpenAI> {
|
||||
// check if first chunk has tool calls, if so, this is a function call
|
||||
// otherwise, it's a regular message
|
||||
const hasToolCall = !!(value.options && "toolCall" in value.options);
|
||||
enqueueOutput({
|
||||
taskStep: step,
|
||||
output: finalStream,
|
||||
isLast: !hasToolCall,
|
||||
});
|
||||
|
||||
if (hasToolCall) {
|
||||
// you need to consume the response to get the full toolCalls
|
||||
@@ -175,17 +171,6 @@ export class OpenAIAgent extends AgentRunner<OpenAI> {
|
||||
];
|
||||
step.context.store.toolOutputs.push(toolOutput);
|
||||
}
|
||||
return {
|
||||
taskStep: step,
|
||||
output: null,
|
||||
isLast: false,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
taskStep: step,
|
||||
output: finalStream,
|
||||
isLast: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -349,12 +349,11 @@ export class ReActAgent extends AgentRunner<LLM, ReACTAgentStore> {
|
||||
};
|
||||
}
|
||||
|
||||
static taskHandler: TaskHandler<LLM, ReACTAgentStore> = async (step) => {
|
||||
static taskHandler: TaskHandler<LLM, ReACTAgentStore> = async (
|
||||
step,
|
||||
enqueueOutput,
|
||||
) => {
|
||||
const { llm, stream, getTools } = step.context;
|
||||
const input = step.input;
|
||||
if (input) {
|
||||
step.context.store.messages.push(input);
|
||||
}
|
||||
const lastMessage = step.context.store.messages.at(-1)!.content;
|
||||
const tools = await getTools(lastMessage);
|
||||
const messages = await chatFormatter(
|
||||
@@ -369,33 +368,25 @@ export class ReActAgent extends AgentRunner<LLM, ReACTAgentStore> {
|
||||
});
|
||||
const reason = await reACTOutputParser(response);
|
||||
step.context.store.reasons = [...step.context.store.reasons, reason];
|
||||
if (reason.type === "response") {
|
||||
return {
|
||||
isLast: true,
|
||||
output: response,
|
||||
taskStep: step,
|
||||
};
|
||||
} else {
|
||||
if (reason.type === "action") {
|
||||
const tool = tools.find((tool) => tool.metadata.name === reason.action);
|
||||
const toolOutput = await callTool(tool, {
|
||||
id: randomUUID(),
|
||||
input: reason.input,
|
||||
name: reason.action,
|
||||
});
|
||||
step.context.store.reasons = [
|
||||
...step.context.store.reasons,
|
||||
{
|
||||
type: "observation",
|
||||
observation: toolOutput.output,
|
||||
},
|
||||
];
|
||||
}
|
||||
return {
|
||||
isLast: false,
|
||||
output: null,
|
||||
taskStep: step,
|
||||
};
|
||||
enqueueOutput({
|
||||
taskStep: step,
|
||||
output: response,
|
||||
isLast: reason.type === "response",
|
||||
});
|
||||
if (reason.type === "action") {
|
||||
const tool = tools.find((tool) => tool.metadata.name === reason.action);
|
||||
const toolOutput = await callTool(tool, {
|
||||
id: randomUUID(),
|
||||
input: reason.input,
|
||||
name: reason.action,
|
||||
});
|
||||
step.context.store.reasons = [
|
||||
...step.context.store.reasons,
|
||||
{
|
||||
type: "observation",
|
||||
observation: toolOutput.output,
|
||||
},
|
||||
];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ export type TaskStep<
|
||||
: never,
|
||||
> = {
|
||||
id: UUID;
|
||||
input: ChatMessage<AdditionalMessageOptions> | null;
|
||||
context: AgentTaskContext<Model, Store, AdditionalMessageOptions>;
|
||||
|
||||
// linked list
|
||||
@@ -62,22 +61,14 @@ export type TaskStepOutput<
|
||||
>
|
||||
? AdditionalMessageOptions
|
||||
: never,
|
||||
> =
|
||||
| {
|
||||
taskStep: TaskStep<Model, Store, AdditionalMessageOptions>;
|
||||
output:
|
||||
| null
|
||||
| ChatResponse<AdditionalMessageOptions>
|
||||
| ReadableStream<ChatResponseChunk<AdditionalMessageOptions>>;
|
||||
isLast: false;
|
||||
}
|
||||
| {
|
||||
taskStep: TaskStep<Model, Store, AdditionalMessageOptions>;
|
||||
output:
|
||||
| ChatResponse<AdditionalMessageOptions>
|
||||
| ReadableStream<ChatResponseChunk<AdditionalMessageOptions>>;
|
||||
isLast: true;
|
||||
};
|
||||
> = {
|
||||
taskStep: TaskStep<Model, Store, AdditionalMessageOptions>;
|
||||
// output shows the response to the user
|
||||
output:
|
||||
| ChatResponse<AdditionalMessageOptions>
|
||||
| ReadableStream<ChatResponseChunk<AdditionalMessageOptions>>;
|
||||
isLast: boolean;
|
||||
};
|
||||
|
||||
export type TaskHandler<
|
||||
Model extends LLM,
|
||||
@@ -90,7 +81,10 @@ export type TaskHandler<
|
||||
: never,
|
||||
> = (
|
||||
step: TaskStep<Model, Store, AdditionalMessageOptions>,
|
||||
) => Promise<TaskStepOutput<Model, Store, AdditionalMessageOptions>>;
|
||||
enqueueOutput: (
|
||||
taskOutput: TaskStepOutput<Model, Store, AdditionalMessageOptions>,
|
||||
) => void,
|
||||
) => Promise<void>;
|
||||
|
||||
export type AgentStartEvent = BaseEvent<{
|
||||
startStep: TaskStep;
|
||||
|
||||
@@ -3,7 +3,10 @@ import type { ImageType } from "../Node.js";
|
||||
import { MultiModalEmbedding } from "./MultiModalEmbedding.js";
|
||||
|
||||
async function readImage(input: ImageType) {
|
||||
const { RawImage } = await import("@xenova/transformers");
|
||||
const { RawImage } = await import(
|
||||
/* webpackIgnore: true */
|
||||
"@xenova/transformers"
|
||||
);
|
||||
if (input instanceof Blob) {
|
||||
return await RawImage.fromBlob(input);
|
||||
} else if (_.isString(input) || input instanceof URL) {
|
||||
@@ -29,7 +32,10 @@ export class ClipEmbedding extends MultiModalEmbedding {
|
||||
|
||||
async getTokenizer() {
|
||||
if (!this.tokenizer) {
|
||||
const { AutoTokenizer } = await import("@xenova/transformers");
|
||||
const { AutoTokenizer } = await import(
|
||||
/* webpackIgnore: true */
|
||||
"@xenova/transformers"
|
||||
);
|
||||
this.tokenizer = await AutoTokenizer.from_pretrained(this.modelType);
|
||||
}
|
||||
return this.tokenizer;
|
||||
@@ -37,7 +43,10 @@ export class ClipEmbedding extends MultiModalEmbedding {
|
||||
|
||||
async getProcessor() {
|
||||
if (!this.processor) {
|
||||
const { AutoProcessor } = await import("@xenova/transformers");
|
||||
const { AutoProcessor } = await import(
|
||||
/* webpackIgnore: true */
|
||||
"@xenova/transformers"
|
||||
);
|
||||
this.processor = await AutoProcessor.from_pretrained(this.modelType);
|
||||
}
|
||||
return this.processor;
|
||||
@@ -46,6 +55,7 @@ export class ClipEmbedding extends MultiModalEmbedding {
|
||||
async getVisionModel() {
|
||||
if (!this.visionModel) {
|
||||
const { CLIPVisionModelWithProjection } = await import(
|
||||
/* webpackIgnore: true */
|
||||
"@xenova/transformers"
|
||||
);
|
||||
this.visionModel = await CLIPVisionModelWithProjection.from_pretrained(
|
||||
@@ -59,6 +69,7 @@ export class ClipEmbedding extends MultiModalEmbedding {
|
||||
async getTextModel() {
|
||||
if (!this.textModel) {
|
||||
const { CLIPTextModelWithProjection } = await import(
|
||||
/* webpackIgnore: true */
|
||||
"@xenova/transformers"
|
||||
);
|
||||
this.textModel = await CLIPTextModelWithProjection.from_pretrained(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { BaseNode, Metadata } from "../Node.js";
|
||||
import { TextNode } from "../Node.js";
|
||||
import type { BaseRetriever } from "../Retriever.js";
|
||||
import type { VectorStoreIndex } from "../indices/index.js";
|
||||
import type { VectorStoreIndex } from "../indices/vectorStore/index.js";
|
||||
import type { MessageContent } from "../llm/index.js";
|
||||
import { extractText } from "../llm/utils.js";
|
||||
import type { BaseTool } from "../types.js";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/edge",
|
||||
"version": "0.3.0",
|
||||
"version": "0.3.2",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/env",
|
||||
"version": "0.0.6",
|
||||
"version": "0.1.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./type": "./src/type.ts"
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# @llamaindex/experimental
|
||||
|
||||
## 0.0.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [61103b6]
|
||||
- llamaindex@0.3.2
|
||||
|
||||
## 0.0.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [46227f2]
|
||||
- llamaindex@0.3.1
|
||||
|
||||
## 0.0.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/experimental",
|
||||
"description": "Experimental package for LlamaIndexTS",
|
||||
"version": "0.0.17",
|
||||
"version": "0.0.19",
|
||||
"type": "module",
|
||||
"types": "dist/type/index.d.ts",
|
||||
"main": "dist/cjs/index.js",
|
||||
|
||||
@@ -26,6 +26,23 @@ if (minorVersion !== expectedMinorVersion) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const packages = ["core", "env"];
|
||||
for (const pkg of packages) {
|
||||
const packageJson = JSON.parse(
|
||||
fs.readFileSync(`./packages/${pkg}/package.json`, "utf8"),
|
||||
);
|
||||
const jsrJson = JSON.parse(
|
||||
fs.readFileSync(`./packages/${pkg}/jsr.json`, "utf8"),
|
||||
);
|
||||
|
||||
jsrJson.version = packageJson.version;
|
||||
|
||||
fs.writeFileSync(
|
||||
`./packages/${pkg}/jsr.json`,
|
||||
JSON.stringify(jsrJson, null, 2) + "\n",
|
||||
);
|
||||
}
|
||||
|
||||
console.log("Current expected minor version is: " + expectedMinorVersion);
|
||||
console.log("Minor version is: " + minorVersion);
|
||||
console.log("Good to go!");
|
||||
|
||||
Reference in New Issue
Block a user