Skip to content

Commit

Permalink
Base tests. Default GPT-4. Fix assistant create.
Browse files Browse the repository at this point in the history
  • Loading branch information
metaskills committed Apr 23, 2024
1 parent 524269c commit 2695de3
Show file tree
Hide file tree
Showing 12 changed files with 188 additions and 14 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ OPENAI_API_KEY=sk-...
Now you can run the following commands:

```bash
npm install
npm run test
./bin/setup
./bin/test
```
1 change: 1 addition & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

* Remove the Assistant#messages. Is even `Message` needed?
* Create a GitHub Publish Action
* Add Contributors

4 changes: 4 additions & 0 deletions bin/setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh
set -e

npm install
6 changes: 6 additions & 0 deletions bin/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh
set -e

export NODE_OPTIONS='--no-warnings --experimental-vm-modules'

npx jest --runInBand $1
14 changes: 12 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@
"version": "0.0.1",
"description": "An opinionated panel of experts implementation using OpenAI's Assistants API",
"type": "module",
"main": "index.js",
"main": "./src/index.js",
"exports": {
".": "./src/index.js",
"./thread": "./src/thread.js",
"./assistant": "./src/assistant.js",
"./tool": "./src/tool.js"
},
"scripts": {
"test": "NODE_OPTIONS='--no-warnings --experimental-vm-modules' jest"
"test": "./bin/test"
},
"author": "Ken COllins",
"license": "MIT",
Expand All @@ -17,5 +23,9 @@
"babel-jest": "^29.7.0",
"jest": "^29.7.0",
"jest-environment-node": "^29.7.0"
},
"repository": {
"type": "git",
"url": "https://github.com/metaskills/experts"
}
}
13 changes: 8 additions & 5 deletions src/experts/assistant.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { Message } from "./messages.js";
import { Run } from "./run.js";

class Assistant {
static async create() {
const asst = new this();
static async create(agentName, description, instructions, options = {}) {
const asst = new this(agentName, description, instructions, options);
await asst.init();
return asst;
}
Expand All @@ -23,10 +23,11 @@ class Assistant {
this.llm = options.llm !== undefined ? options.llm : true;
if (this.llm) {
this.id = options.id;
this.temperature =
options.temperature !== undefined ? options.temperature : 0.1;
this.model = options.model || "gpt-3.5-turbo";
this.model = options.model || "gpt-4-turbo";
this.messages = [];
this.temperature =
options.temperature !== undefined ? options.temperature : 1.0;
this.top_p = options.top_p !== undefined ? options.top_p : 1.0;
this.assistantsTools = {};
this.assistantsToolsOutputs = [];
this.tools = [];
Expand Down Expand Up @@ -143,6 +144,8 @@ class Assistant {
name: this.agentName,
description: this.description,
instructions: this.instructions,
temperature: this.temperature,
top_p: this.top_p,
tools: this.tools,
});
debug(`💁‍♂️ Created ${this.agentName} assistant ${assistant.id}...`);
Expand Down
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { Thread } from "./experts/thread.js";
export { Assistant } from "./experts/assistant.js";
export { Tool } from "./experts/tool.js";
67 changes: 67 additions & 0 deletions test/experts/assistant.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {
helperThreadID,
helperDeleteAllAssistants,
helperFindAssistant,
} from "../helpers.js";
import { Assistant } from "../../src/experts/assistant.js";

const NAME = "Experts.js (Test)";

beforeEach(async () => {
await helperDeleteAllAssistants();
});

afterEach(async () => {
await helperDeleteAllAssistants();
});

test("can ask the assistant a question using a thread id", async () => {
const assistant = await Assistant.create(
NAME,
"echo",
"echo the same text back to the user"
);
const threadID = await helperThreadID();
const output = await assistant.ask("hello 123", threadID);
expect(output).toBe("hello 123");
});

test("can override defaults such as temperature and top_p", async () => {
const assistant = await Assistant.create(
NAME,
"test-description",
"test-instructions",
{ temperature: 0.5, top_p: 0.5 }
);
expect(assistant.temperature).toBe(0.5);
expect(assistant.top_p).toBe(0.5);
});

test("create new assistant using name, description, and instruction defaults", async () => {
// None exists before creation.
const assistantNone = await helperFindAssistant(NAME);
expect(assistantNone).toBeUndefined();
const assistant = await Assistant.create(
NAME,
"test-description",
"test-instructions"
);
const backendAssistant = await helperFindAssistant(NAME);
// Assistant
expect(assistant.agentName).toBe(NAME);
expect(assistant.description).toBe("test-description");
expect(assistant.instructions).toBe("test-instructions");
expect(assistant.llm).toBe(true);
expect(assistant.model).toBe("gpt-4-turbo");
expect(assistant.temperature).toBe(1.0);
expect(assistant.id).toMatch(/^asst_/);
expect(assistant.id).toBe(backendAssistant.id);
// Backend
expect(backendAssistant).toBeDefined();
expect(backendAssistant.name).toBe(NAME);
expect(backendAssistant.description).toBe("test-description");
expect(backendAssistant.instructions).toBe("test-instructions");
expect(backendAssistant.model).toBe("gpt-4-turbo");
expect(backendAssistant.temperature).toBe(1.0);
expect(backendAssistant.id).toMatch(/^asst_/);
});
5 changes: 0 additions & 5 deletions test/experts/openai.test.js

This file was deleted.

42 changes: 42 additions & 0 deletions test/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { openai } from "../src/openai.js";

const helperThreadID = async () => {
const thread = await openai.beta.threads.create();
return thread.id;
};

const helperFindAllAssistants = async () => {
const assistants = await openai.beta.assistants.list({ limit: 100 });
return assistants.data.filter((a) => a.name?.startsWith("Experts.js"));
};

const helperDeleteAllAssistants = async () => {
const assistants = await helperFindAllAssistants();
for (const assistant of assistants) {
try {
await openai.beta.assistants.del(assistant.id);
} catch (error) {}
}
};

const helperFindAssistant = async (name) => {
const assistant = (
await openai.beta.assistants.list({ limit: 100 })
).data.find((a) => a.name === name);
return assistant;
};

const helperDeleteAssistant = async (name) => {
const assistant = await helperFindAssistant(name);
if (assistant !== undefined) {
await openai.beta.assistants.del(assistant.id);
}
};

export {
helperThreadID,
helperFindAllAssistants,
helperDeleteAllAssistants,
helperFindAssistant,
helperDeleteAssistant,
};
36 changes: 36 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { helperDeleteAllAssistants } from "./helpers.js";
import { Thread, Assistant, Tool } from "../src/index.js";

const NAME = "Experts.js (Test)";

beforeEach(async () => {
await helperDeleteAllAssistants();
});

afterEach(async () => {
await helperDeleteAllAssistants();
});

test("can import Thread", async () => {
const thread = await Thread.create();
expect(thread.id).toMatch(/^thread_/);
});

test("can import Assistant", async () => {
const assistant = await Assistant.create(
NAME,
"test-description",
"test-instructions"
);
expect(assistant.id).toMatch(/^asst_/);
});

test("can import Tool", async () => {
const tool = await Tool.create(
NAME,
"test-description",
"test-instructions",
{ llm: false }
);
expect(tool.isTool).toBe(true);
});
7 changes: 7 additions & 0 deletions test/openai.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { openai } from "../src/openai.js";

test("exports an openai client", () => {
expect(openai).toBeInstanceOf(Object);
expect(openai.beta).toBeInstanceOf(Object);
expect(openai.beta.threads).toBeInstanceOf(Object);
});

0 comments on commit 2695de3

Please sign in to comment.