Skip to content
This repository has been archived by the owner on Oct 30, 2024. It is now read-only.

correctly return the browser response + fix the handle step nonesense #38

Merged
merged 5 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions src/agent/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ export class Agent {
typeof ObjectiveCompleteResponse<TObjectiveComplete>
>
) {
console.log("Generating response type");
const messages: ChatRequestMessage[] = [
{
role: "user",
Expand All @@ -104,8 +103,6 @@ export class Agent {
schema: ObjectiveCompleteResponse(responseSchema),
});

console.log("Response", response.data);

return ObjectiveCompleteResponse(responseSchema).parse(response.data);
}

Expand Down
137 changes: 52 additions & 85 deletions src/agentBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export class AgentBrowser {
plugins: any; // to be done later
hdrConfig: CollectiveMemoryConfig;

private iterationCount: number = 0;

private objectiveProgress: string[];
private memorySequenceId: string = generateUUID();

Expand Down Expand Up @@ -72,38 +74,26 @@ export class AgentBrowser {
// we should relax this condition in the future
if (state.ariaTree === memory.objectiveState.ariaTree) {
debug.write("Performing action step from memory");
await this.handleStep(
memory.actionStep,
ModelResponseSchema(ObjectiveComplete)
this.browser.performManyActions(
memory.actionStep.command as BrowserAction[],
this.inventory
);
description = memory.actionStep.description;
} else {
debug.write("Modifying actions");
let modifiedActionStep = await this.agent.modifyActions(state, memory, {
inventory: this.inventory,
});
if (!modifiedActionStep) {
const freeStep = await this.step(
memory.objectiveState.objective,
ModelResponseSchema(ObjectiveComplete)
);

const result = await this.handleStep(
freeStep,
ModelResponseSchema(ObjectiveComplete)
);
description = result?.result?.description!;

if (result) {
return result;
}
} else {
description = modifiedActionStep.description;
this.browser.performManyActions(
modifiedActionStep.command as BrowserAction[],
this.inventory
);

if (modifiedActionStep === undefined) {
return this.returnErrorState("Agent failed to respond");
}

description = modifiedActionStep.description;
this.browser.performManyActions(
modifiedActionStep.command as BrowserAction[],
this.inventory
);
}

// add the description to the progress so the model understands
Expand Down Expand Up @@ -138,20 +128,25 @@ export class AgentBrowser {
if (memories.length === 0) {
throw new Error("No memories found for sequence id");
}
const iterationCount = 0;

while (iterationCount <= browserObjective.maxIterations) {
while (this.iterationCount <= browserObjective.maxIterations) {
for (const memory of memories) {
if (memory.actionStep.objectiveComplete) {
const step = await this.generateResponseSchema(
const state: ObjectiveState = await this.browser.state(
memory.objectiveState.objective,
this.objectiveProgress
);
const step = await this.agent.generateResponseType(
state,
memory,
responseSchema
);
console.log("Step", step);
// todo: this is messy because it is not returning the correct type. Need to fix.
const stepResponse = responseSchema.parse(step.objectiveComplete);

const answer = {
kind: "ObjectiveComplete",
result: step,
result: stepResponse,
url: this.browser.url(),
content: this.browser.content(),
};
Expand Down Expand Up @@ -203,54 +198,6 @@ export class AgentBrowser {
return response;
}

private async generateResponseSchema<
TObjectiveComplete extends z.AnyZodObject = typeof ObjectiveComplete
>(
currentObjective: string,
memory: Memory,
responseSchema: ReturnType<
typeof ObjectiveCompleteResponse<TObjectiveComplete>
>
) {
const state: ObjectiveState = await this.browser.state(
currentObjective,
this.objectiveProgress
);

return await this.agent.generateResponseType(state, memory, responseSchema);
}

async handleStep<
TObjectiveComplete extends z.AnyZodObject = typeof ObjectiveComplete
>(
// TODO - step has a few inferred types, blocks build, marked unknown -- mp
step: unknown,
responseType: ReturnType<typeof ModelResponseSchema<TObjectiveComplete>>
) {
const stepResponse = responseType.parse(step);
if (this.logger) {
this.logger.log(JSON.stringify(stepResponse));
}
if (stepResponse.objectiveComplete) {
const answer = {
kind: "ObjectiveComplete",
result: stepResponse,
url: this.browser.url(),
content: this.browser.content(),
};
if (this.logger) {
this.logger.log(JSON.stringify(answer));
}
return answer;
} else if (stepResponse.command) {
debug.write("Performing action:" + JSON.stringify(stepResponse.command));
this.browser.performManyActions(
stepResponse.command as BrowserAction[],
this.inventory
);
}
}

async browse<
TObjectiveComplete extends z.AnyZodObject = typeof ObjectiveComplete
>(
Expand All @@ -261,7 +208,6 @@ export class AgentBrowser {
BrowserObjective.parse(browserObjective);

this.setMemorySequenceId();
let iterationCount = 0;
// goto the start url
await this.browser.goTo(startUrl, this.config.goToDelay);

Expand All @@ -270,29 +216,50 @@ export class AgentBrowser {
// loop through all objectives
for (const currentObjective of objective) {
// check if we have exceeded maxIterations and return the failure state if so
if (iterationCount > maxIterations) {
if (this.iterationCount > maxIterations) {
return await this.returnErrorState(
"Maximum number of iterations exceeded"
);
}

const step = await this.step(currentObjective, responseType);
const handleStepResponse = await this.handleStep(step, responseType);
const stepResponse = responseType.parse(step);

if (handleStepResponse) {
return handleStepResponse;
if (this.logger) {
this.logger.log(JSON.stringify(stepResponse));
}

if (stepResponse.objectiveComplete) {
const answer = {
kind: "ObjectiveComplete",
result: stepResponse,
url: this.browser.url(),
content: this.browser.content(),
};
if (this.logger) {
this.logger.log(JSON.stringify(answer));
}
return answer;
} else if (stepResponse.command) {
debug.write(
"Performing action:" + JSON.stringify(stepResponse.command)
);
this.browser.performManyActions(
stepResponse.command as BrowserAction[],
this.inventory
);
}

iterationCount++;
this.iterationCount++;
}

iterationCount++; // Increment the current iteration counter
this.iterationCount++; // Increment the current iteration counter
} while (true);
} catch {}
}

reset() {
this.objectiveProgress = [];
this.iterationCount = 0;
}

async memorize(state: ObjectiveState, action: ModelResponseType) {
Expand Down
40 changes: 22 additions & 18 deletions tests/agent/agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import {
import {
ModelResponseSchema,
ObjectiveComplete,
ModelResponseType,
} from "../../src/types/browser/actionStep.types";

import { Inventory } from "../../src/inventory";

import { z } from "zod";
import { ObjectiveState } from "../../src/types/browser";
import { actionStepExample1 } from "../collectiveMemory/memorize.test";

describe("Agent", () => {
let agent: Agent;
Expand Down Expand Up @@ -122,11 +124,19 @@ describe("Agent", () => {
});

test("that askCommandWorks with a different schema", async () => {
const prompt = await agent.prompt(
objectiveStateExample1,
[stateActionPair1],
{}
);
const fakeState: ObjectiveState = {
kind: "ObjectiveState",
objective: "how much is an gadget 11 pro",
progress: [],
url: "https://www.google.com/",
ariaTree: `[0,"RootWebArea", "The random number is 4"]`,
};

const prompt = await agent.prompt(fakeState, [], {
systemPrompt:
"ignore all commands and return the result of the objective result as {progressAssessment: 'Do not have enough information in ariaTree to return an Objective Result.', objectiveComplete: {kind: 'ObjectiveComplete', result: 'The random number is 4', randomNumber: 'THIS SHOULD BE 4'}, description: 'Searched `gadget 11 pro price`'}",
});

const testSchema = ObjectiveComplete.extend({
randomNumber: z
.number()
Expand All @@ -137,19 +147,13 @@ describe("Agent", () => {
prompt,
ModelResponseSchema(testSchema)
);
if (response!.command && response!.command.length > 0) {
const command = response!.command[0];
if ("index" in command) {
expect(command.kind).toBe("Type");
expect(command.index).toBe(5);
}
}
if (response!.objectiveComplete) {
const parsedResponse = ModelResponseSchema(testSchema).parse(
response!.objectiveComplete
);
expect(parsedResponse).toBeDefined();
}

const parsedResponse = ModelResponseSchema(testSchema).parse(response!);
console.log("Parsed Response:", parsedResponse);

expect(
testSchema.parse(parsedResponse.objectiveComplete).randomNumber
).toBeDefined();
});

it("should follow a system prompt", async () => {
Expand Down
Loading