Skip to content

Commit

Permalink
feat: options.messages for prompt() (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
gr2m authored Sep 3, 2024
1 parent 6cd9abf commit bb4e12c
Show file tree
Hide file tree
Showing 5 changed files with 366 additions and 165 deletions.
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,34 @@ const { message } = await prompt("What is the capital of France?", {
console.log(message.content);
```
⚠️ Not all of the arguments below are implemented yet.
In order to pass a history of messages, pass them as `options.messages`:
```js
const { message } = await prompt("What about Spain?", {
model: "gpt-4",
token: process.env.TOKEN,
messages: [
{ role: "user", content: "What is the capital of France?" },
{ role: "assistant", content: "The capital of France is Paris." },
],
});
```
Alternatively, skip the `message` argument and pass all messages as `options.messages`:
```js
const { message } = await prompt({
model: "gpt-4",
token: process.env.TOKEN,
messages: [
{ role: "user", content: "What is the capital of France?" },
{ role: "assistant", content: "The capital of France is Paris." },
{ role: "user", content: "What about Spain?" },
],
});
```
⚠️ Not all of the arguments below are implemented yet. See [#5](https://github.com/copilot-extensions/preview-sdk.js/issues/5) sub issues for progress.
```js
await prompt({
Expand Down
50 changes: 34 additions & 16 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,7 @@ type ResponseEvent<T extends ResponseEventType = "text"> =

type CopilotAckResponseEventData = {
choices: [{
delta: {
content: "", role: "assistant"
}
delta: InteropMessage<"assistant">
}]
}

Expand All @@ -92,9 +90,7 @@ type CopilotDoneResponseEventData = {

type CopilotTextResponseEventData = {
choices: [{
delta: {
content: string, role: "assistant"
}
delta: InteropMessage<"assistant">
}]
}
type CopilotConfirmationResponseEventData = {
Expand Down Expand Up @@ -134,7 +130,7 @@ interface CopilotReference {

export interface CopilotRequestPayload {
copilot_thread_id: string
messages: Message[]
messages: CopilotMessage[]
stop: any
top_p: number
temperature: number
Expand All @@ -146,14 +142,10 @@ export interface CopilotRequestPayload {
}

export interface OpenAICompatibilityPayload {
messages: {
role: string
name?: string
content: string
}[]
messages: InteropMessage[]
}

export interface Message {
export interface CopilotMessage {
role: string
content: string
copilot_references: MessageCopilotReference[]
Expand All @@ -167,6 +159,14 @@ export interface Message {
"type": "function"
}[]
name?: string
[key: string]: unknown
}

export interface InteropMessage<TRole extends string = string> {
role: TRole
content: string
name?: string
[key: string]: unknown
}

export interface MessageCopilotReference {
Expand Down Expand Up @@ -254,10 +254,23 @@ export interface GetUserConfirmationInterface {

// prompt

/** model names supported by Copilot API */
/**
* model names supported by Copilot API
*
* Based on https://api.githubcopilot.com/models from 2024-09-02
*/
export type ModelName =
| "gpt-4"
| "gpt-3.5-turbo"
| "gpt-3.5-turbo-0613"
| "gpt-4"
| "gpt-4-0613"
| "gpt-4-o-preview"
| "gpt-4o"
| "gpt-4o-2024-05-13"
| "text-embedding-3-small"
| "text-embedding-3-small-inference"
| "text-embedding-ada-002"
| "text-embedding-ada-002-index"

export interface PromptFunction {
type: "function"
Expand All @@ -274,18 +287,23 @@ export type PromptOptions = {
model: ModelName
token: string
tools?: PromptFunction[]
messages?: InteropMessage[]
request?: {
fetch?: Function
}
}

export type PromptResult = {
requestId: string
message: Message
message: CopilotMessage
}

// https://stackoverflow.com/a/69328045
type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }

interface PromptInterface {
(userPrompt: string, options: PromptOptions): Promise<PromptResult>;
(options: WithRequired<PromptOptions, "messages">): Promise<PromptResult>;
}

// exported methods
Expand Down
38 changes: 29 additions & 9 deletions index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
getUserMessage,
getUserConfirmation,
type VerificationPublicKey,
type InteropMessage,
CopilotRequestPayload,
prompt,
} from "./index.js";
Expand Down Expand Up @@ -79,11 +80,10 @@ export function createAckEventTest() {
expectType<() => string>(event.toString);
expectType<string>(event.toString());


expectType<{
choices: [{
delta: {
content: "", role: "assistant"
}
delta: InteropMessage<"assistant">
}]
}>(event.data);

Expand All @@ -98,9 +98,7 @@ export function createTextEventTest() {

expectType<{
choices: [{
delta: {
content: string, role: "assistant"
}
delta: InteropMessage<"assistant">
}]
}>(event.data);

Expand Down Expand Up @@ -243,6 +241,7 @@ export function transformPayloadForOpenAICompatibilityTest(payload: CopilotReque
content: string;
role: string;
name?: string
[key: string]: unknown
}[]
}
>(result);
Expand Down Expand Up @@ -307,12 +306,33 @@ export async function promptWithToolsTest() {
function: {
name: "",
description: "",
parameters: {

},
parameters: {},
strict: true,
}
}
]
})
}

export async function promptWithMessageAndMessages() {
await prompt("What about Spain?", {
model: "gpt-4",
token: 'secret',
messages: [
{ role: "user", content: "What is the capital of France?" },
{ role: "assistant", content: "The capital of France is Paris." },
],
});
}

export async function promptWithoutMessageButMessages() {
await prompt({
model: "gpt-4",
token: 'secret',
messages: [
{ role: "user", content: "What is the capital of France?" },
{ role: "assistant", content: "The capital of France is Paris." },
{ role: "user", content: "What about Spain?" },
],
});
}
43 changes: 27 additions & 16 deletions lib/prompt.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,32 @@

/** @type {import('..').PromptInterface} */
export async function prompt(userPrompt, promptOptions) {
const promptFetch = promptOptions.request?.fetch || fetch;
const options = typeof userPrompt === "string" ? promptOptions : userPrompt;

const systemMessage = promptOptions.tools
const promptFetch = options.request?.fetch || fetch;

const systemMessage = options.tools
? "You are a helpful assistant. Use the supplied tools to assist the user."
: "You are a helpful assistant.";

const messages = [
{
role: "system",
content: systemMessage,
},
];

if (options.messages) {
messages.push(...options.messages);
}

if (typeof userPrompt === "string") {
messages.push({
role: "user",
content: userPrompt,
});
}

const response = await promptFetch(
"https://api.githubcopilot.com/chat/completions",
{
Expand All @@ -16,22 +36,13 @@ export async function prompt(userPrompt, promptOptions) {
accept: "application/json",
"content-type": "application/json; charset=UTF-8",
"user-agent": "copilot-extensions/preview-sdk.js",
authorization: `Bearer ${promptOptions.token}`,
authorization: `Bearer ${options.token}`,
},
body: JSON.stringify({
messages: [
{
role: "system",
content: systemMessage,
},
{
role: "user",
content: userPrompt,
},
],
model: promptOptions.model,
toolChoice: promptOptions.tools ? "auto" : undefined,
tools: promptOptions.tools,
messages: messages,
model: options.model,
toolChoice: options.tools ? "auto" : undefined,
tools: options.tools,
}),
}
);
Expand Down
Loading

0 comments on commit bb4e12c

Please sign in to comment.