Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: options.messages for prompt() #49

Merged
merged 10 commits into from
Sep 3, 2024
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