Skip to content

Commit

Permalink
Merge pull request #52 from polywrap/add-markdown-logging-to-cli
Browse files Browse the repository at this point in the history
feat: add markdown logging to CLI
  • Loading branch information
dOrgJelli authored Aug 21, 2023
2 parents feaf154 + f37cbc3 commit 4991ef5
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 70 deletions.
15 changes: 10 additions & 5 deletions apps/browser/src/pages/Dojo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ function Dojo() {
return;
}
setDojoError(undefined);
const logger = new EvoCore.Logger([
new EvoCore.ConsoleLogger()
], {
promptUser: () => Promise.resolve("N/A"),
logUserPrompt: () => {}
});
const scriptsWorkspace = new EvoCore.InMemoryWorkspace();
const scripts = new EvoCore.Scripts(
scriptsWorkspace
Expand All @@ -58,17 +64,16 @@ function Dojo() {
env.OPENAI_API_KEY,
env.GPT_MODEL,
env.CONTEXT_WINDOW_TOKENS,
env.MAX_RESPONSE_TOKENS
env.MAX_RESPONSE_TOKENS,
logger
);
const userWorkspace = new EvoCore.InMemoryWorkspace();
const chat = new EvoCore.Chat(
userWorkspace,
llm,
cl100k_base
cl100k_base,
logger
);
const logger = new EvoCore.Logger([
new EvoCore.ConsoleLogger()
]);

setEvo(new EvoCore.Evo(
userWorkspace,
Expand Down
10 changes: 8 additions & 2 deletions apps/cli/src/__tests__/runners/script-js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {
JsEngine_Module,
Scripts,
Workspace,
shimCode
shimCode,
Logger,
ConsoleLogger
} from "@evo-ninja/core";
import fs from "fs";
import path from "path-browserify";
Expand Down Expand Up @@ -44,7 +46,11 @@ export async function runScriptJs(
}
}

const client = new WrapClient(workspace);
const logger = new Logger([new ConsoleLogger()], {
promptUser: () => Promise.resolve("N/A"),
logUserPrompt: () => {}
});
const client = new WrapClient(workspace, logger);

const result = await JsEngine_Module.evalWithGlobals({
src: shimCode(script.code),
Expand Down
61 changes: 41 additions & 20 deletions apps/cli/src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { FileSystemWorkspace, FileLogger } from "./sys";

import { Evo, Scripts, Env, OpenAI, Chat, Logger, ConsoleLogger } from "@evo-ninja/core";
import {
Evo,
Scripts,
Env,
OpenAI,
Chat,
ConsoleLogger,
Logger
} from "@evo-ninja/core";
import dotenv from "dotenv";
import readline from "readline";
import path from "path";
Expand All @@ -20,44 +28,55 @@ const prompt = (query: string) => new Promise<string>(
);

export async function cli(): Promise<void> {

const rootDir = path.join(__dirname, "../../../");

const env = new Env(
process.env as Record<string, string>
);

// Generate a unique log file
const date = new Date();
const logFile = `chat_${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()}_${date.getHours()}-${date.getMinutes()}-${date.getSeconds()}.md`;
const logWorkspace = new FileSystemWorkspace(
path.join(rootDir, "chats")
);
const fileLogger = new FileLogger(logWorkspace.toWorkspacePath(logFile));

// Create logger
const consoleLogger = new ConsoleLogger();
const logger = new Logger([
fileLogger,
consoleLogger
], {
promptUser: prompt,
logUserPrompt: (response: string) => {
fileLogger.info(`**User**: ${response}`);
}
})

const scriptsWorkspace = new FileSystemWorkspace(
path.join(rootDir, "scripts")
);
const scripts = new Scripts(
scriptsWorkspace,
"./"
);
const env = new Env(
process.env as Record<string, string>
);
const llm = new OpenAI(
env.OPENAI_API_KEY,
env.GPT_MODEL,
env.CONTEXT_WINDOW_TOKENS,
env.MAX_RESPONSE_TOKENS
env.MAX_RESPONSE_TOKENS,
logger
);
const userWorkspace = new FileSystemWorkspace(
path.join(rootDir, "workspace")
);
const chat = new Chat(
userWorkspace,
llm,
cl100k_base
);
// Generate a unique log file name
const date = new Date();
const logFile = `chat_${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()}_${date.getHours()}-${date.getMinutes()}-${date.getSeconds()}.md`;
const logWorkspace = new FileSystemWorkspace(
path.join(rootDir, "chats")
cl100k_base,
logger
);
// Create a console & file logger
const logger = new Logger([
new ConsoleLogger(),
new FileLogger(logWorkspace.toWorkspacePath(logFile))
])

// Create Evo
const evo = new Evo(
Expand All @@ -73,15 +92,17 @@ export async function cli(): Promise<void> {
let goal: string | undefined = process.argv[2];

if (!goal) {
goal = await prompt("Enter your goal: ");
goal = await logger.prompt("Enter your goal: ");
}

let iterator = evo.run(goal);

while(true) {
const response = await iterator.next();

response.value.message && console.log(response.value.message);
if (response.value) {
response.value.message && logger.info(response.value.message);
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/agents/agent-function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
OTHER_EXECUTE_FUNCTION_OUTPUT,
READ_GLOBAL_VAR_OUTPUT
} from "./prompts";
import { Workspace, } from "../sys";
import { Workspace, Logger } from "../sys";
import { Scripts } from "../Scripts";
import { WrapClient } from "../wrap";
import { LlmApi, Chat } from "../llm";
Expand All @@ -22,6 +22,7 @@ export interface AgentContext {
scripts: Scripts;
llm: LlmApi;
chat: Chat;
logger: Logger;
}

export interface AgentFunction {
Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/agents/evo/Evo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class Evo implements Agent {
) {
this.client = new WrapClient(
this.workspace,
this.logger
);

this.globals = {};
Expand All @@ -29,8 +30,8 @@ export class Evo implements Agent {
public async* run(goal: string): AsyncGenerator<StepOutput, RunResult, string | undefined> {
const createScriptWriter = (): ScriptWriter => {
const workspace = new InMemoryWorkspace();
const chat = new Chat(workspace, this.llm, this.chat.tokenizer);
return new ScriptWriter(workspace, this.scripts, this.llm, chat);
const chat = new Chat(workspace, this.llm, this.chat.tokenizer, this.logger);
return new ScriptWriter(workspace, this.scripts, this.llm, chat, this.logger);
};

try {
Expand All @@ -42,6 +43,7 @@ export class Evo implements Agent {
this.globals,
this.workspace,
this.scripts,
this.logger,
executeAgentFunction,
agentFunctions(createScriptWriter)
);
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/agents/evo/agent-functions/createScript.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ScriptWriter } from "../../script-writer";
import { AgentContext, AgentFunction } from "../../agent-function";
import chalk from "chalk";

export function createScript(createScriptWriter: () => ScriptWriter): AgentFunction {
return {
Expand Down Expand Up @@ -45,14 +44,14 @@ export function createScript(createScriptWriter: () => ScriptWriter): AgentFunct
// Create a fresh ScriptWriter agent
const writer = createScriptWriter();

console.log(chalk.yellow(`Creating script '${options.namespace}'...`));
context.logger.notice(`Creating script '${options.namespace}'...`);

let iterator = writer.run(options.namespace, options.description, options.arguments, options.developerNote);

while(true) {
const response = await iterator.next();

response.value.message && console.log(chalk.yellow(response.value.message));
response.value.message && context.logger.notice(response.value.message);

// TODO: we should not be communicating the ScriptWriter's completion
// via a special file in the workspace
Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/agents/evo/loop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AgentFunction, ExecuteAgentFunction } from "../agent-function";
import { LlmApi, LlmResponse, Chat } from "../../llm";
import { WrapClient } from "../../wrap";
import { Scripts } from "../../Scripts";
import { Workspace } from "../../sys";
import { Workspace, Logger } from "../../sys";

export async function* loop(
goal: string,
Expand All @@ -14,6 +14,7 @@ export async function* loop(
globals: Record<string, any>,
workspace: Workspace,
scripts: Scripts,
logger: Logger,
executeAgentFunction: ExecuteAgentFunction,
agentFunctions: AgentFunction[],
): AsyncGenerator<StepOutput, RunResult, string | undefined> {
Expand All @@ -39,7 +40,8 @@ export async function* loop(
workspace,
scripts,
llm,
chat
chat,
logger
},
agentFunctions
);
Expand Down
9 changes: 6 additions & 3 deletions packages/core/src/agents/script-writer/ScriptWriter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { executeAgentFunction } from "../agent-function";
import { WrapClient } from "../../wrap";
import { Scripts } from "../../Scripts";
import { LlmApi, Chat } from "../../llm";
import { Workspace } from "../../sys";
import { Workspace, Logger } from "../../sys";

export class ScriptWriter implements Agent {
private client: WrapClient;
Expand All @@ -15,10 +15,12 @@ export class ScriptWriter implements Agent {
public readonly workspace: Workspace,
private readonly scripts: Scripts,
private readonly llm: LlmApi,
private readonly chat: Chat
private readonly chat: Chat,
private readonly logger: Logger
) {
this.client = new WrapClient(
this.workspace,
this.logger
);

this.globals = {};
Expand All @@ -42,11 +44,12 @@ export class ScriptWriter implements Agent {
this.globals,
this.workspace,
this.scripts,
this.logger,
executeAgentFunction,
agentFunctions
);
} catch (err) {
console.error(err);
this.logger.error(err);
return RunResult.error( "Unrecoverable error encountered.");
}
}
Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/agents/script-writer/loop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AgentFunction, ExecuteAgentFunction } from "../agent-function";
import { LlmApi, LlmResponse, Chat } from "../../llm";
import { WrapClient } from "../../wrap";
import { Scripts } from "../../Scripts";
import { Workspace } from "../../sys";
import { Workspace, Logger } from "../../sys";

export async function* loop(
namespace: string,
Expand All @@ -17,6 +17,7 @@ export async function* loop(
globals: Record<string, any>,
workspace: Workspace,
scripts: Scripts,
logger: Logger,
executeAgentFunction: ExecuteAgentFunction,
agentFunctions: AgentFunction[],
): AsyncGenerator<StepOutput, RunResult, string | undefined> {
Expand All @@ -42,7 +43,8 @@ export async function* loop(
workspace,
scripts,
llm,
chat
chat,
logger
},
agentFunctions
);
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/llm/Chat.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { LlmApi, Tokenizer } from ".";
import { Workspace } from "../sys";
import { Workspace, Logger } from "../sys";

import {
ChatCompletionRequestMessageRoleEnum,
Expand Down Expand Up @@ -36,6 +36,7 @@ export class Chat {
private _workspace: Workspace,
private _llm: LlmApi,
private _tokenizer: Tokenizer,
private _logger: Logger,
private _msgsFile: string = ".msgs",
) {
this._maxContextTokens = this._llm.getMaxContextTokens();
Expand Down Expand Up @@ -130,7 +131,7 @@ export class Chat {
return;
}

console.error(`! Max Tokens Exceeded (${totalTokens()} / ${this._maxContextTokens})`);
this._logger.error(`! Max Tokens Exceeded (${totalTokens()} / ${this._maxContextTokens})`);

// Start with "temporary" messages
await this._summarize("temporary");
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/llm/OpenAI.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { LlmApi, LlmOptions, LlmResponse, Chat } from ".";
import { Logger } from "../";

import {
ChatCompletionRequestMessage,
Expand Down Expand Up @@ -28,6 +29,7 @@ export class OpenAI implements LlmApi {
private _defaultModel: string,
private _defaultMaxTokens: number,
private _defaultMaxResponseTokens: number,
private _logger: Logger,
private _maxRateLimitRetries: number = 5
) {
this._configuration = new Configuration({
Expand Down Expand Up @@ -80,7 +82,7 @@ export class OpenAI implements LlmApi {

// If a rate limit error is thrown
if (maybeOpenAiError.status === 429) {
console.warn("Warning: OpenAI rate limit exceeded, sleeping for 15 seconds.");
this._logger.notice("Warning: OpenAI rate limit exceeded, sleeping for 15 seconds.");

// Try again after a short sleep
await new Promise((resolve) => setTimeout(resolve, 15000));
Expand Down
Loading

0 comments on commit 4991ef5

Please sign in to comment.