Skip to content

Commit

Permalink
Make the sampling temperature configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
damnever committed Aug 8, 2023
1 parent a8f25b2 commit 60b07e5
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 42 deletions.
28 changes: 18 additions & 10 deletions Config.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@
"popclip version": 4096,
"javascript file": "main.js",
"options": [
{
"identifier": "basicOptions",
"label": "❤ OpenAI API Options",
"type": "heading",
"description": "Options for OpenAI chat completions API. Azure base URL: https://{resource-name}.openai.azure.com/openai/deployments/{deployment-id}",
},
{
"identifier": "apiType",
"label": "API Type",
"type": "multiple",
"description": "The type of API or services being used.",
"default value": "openai",
"values": [
"openai",
Expand All @@ -22,30 +27,33 @@
},
{
"identifier": "apiBase",
"label": "API Base",
"label": "API Base URL",
"type": "string",
"description": "The base URL for chat completions API(/chat/completions).(Azure: https://{your-resource-name}.openai.azure.com/openai/deployments/{deployment-id})",
"default value": "https://api.openai.com/v1"
},
{
"identifier": "apiKey",
"label": "API Key",
"type": "string",
"description": "The API Key for authentication.",
},
{
"identifier": "model",
"label": "Model",
"type": "string",
"default value": "gpt-3.5-turbo"
},
{
"identifier": "apiVersion",
"label": "API Version (Azure)",
"label": "API Version (Azure only)",
"type": "string",
"description": "The API version to use, which follows the YYYY-MM-DD format. Azure only.",
"default value": "2023-07-01-preview"
},
{
"identifier": "model",
"label": "Model",
"identifier": "temperature",
"label": "Sampling Temperature",
"type": "string",
"description": "The model to use with the chat completions API(/chat/completions), required by openai.",
"default value": "gpt-3.5-turbo"
"description": ">=0, <=2. Higher values will result in a more random output, and vice versa.",
"default value": "1"
},
{
"identifier": "opinionedActions",
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
build:
rm -f ./main.js ChatGPTx.popclipextz
tsc main.ts || exit 0
tsc || exit 0
pushd .. && zip -r ChatGPTx.popclipextz ChatGPTx.popclipext -x *.git* && mv ChatGPTx.popclipextz ChatGPTx.popclipext && popd
67 changes: 36 additions & 31 deletions main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import axios from "axios";

// Doc: https://pilotmoon.github.io/PopClip-Extensions/interfaces/Input.html
// Ref: https://pilotmoon.github.io/PopClip-Extensions/interfaces/PopClip.html
// Source: https://github.com/pilotmoon/PopClip-Extensions/blob/master/popclip.d.ts

interface PasteboardContent {
'public.utf8-plain-text'?: string
'public.html'?: string
Expand All @@ -19,7 +20,6 @@ interface Input {
xhtml: string
}

// Ref: https://pilotmoon.github.io/PopClip-Extensions/interfaces/Context.html
interface Context {
hasFormatting: boolean
canPaste: boolean
Expand Down Expand Up @@ -48,6 +48,7 @@ interface Options {
apiKey: string
apiVersion: string
model: string
temperature: string

reviseEnabled: boolean
revisePrimaryLanguage: string
Expand All @@ -61,7 +62,6 @@ interface Options {
// prompts: string
}

// Ref: https://pilotmoon.github.io/PopClip-Extensions/interfaces/PopClip.html
interface PopClip {
context: Context
modifiers: Modifiers
Expand All @@ -72,11 +72,20 @@ interface PopClip {
pasteText(text: string, options?: { restore?: boolean }): void
}

// Ref: https://platform.openai.com/docs/api-reference/chat/create

interface Message {
role: "user" | "system" | "assistant"
content: string
}

interface APIRequestData {
model: string
messages: Array<Message>
temperature?: number
top_p?: number
}

interface APIResponse {
data: {
choices: [{
Expand All @@ -90,8 +99,8 @@ type AllowedOneTimeActions = "revise" | "polish" | "translate"
type AllowedActions = "chat" | AllowedOneTimeActions

abstract class ChatGPTAction {
abstract beforeRequest(popclip: PopClip, input: Input, options: Options, action: AllowedActions): boolean
abstract makeRequestData(popclip: PopClip, input: Input, options: Options, action: AllowedActions): object | null
abstract beforeRequest(popclip: PopClip, input: Input, options: Options, action: AllowedActions): { allow: boolean, reason?: string }
abstract makeRequestData(popclip: PopClip, input: Input, options: Options, action: AllowedActions): APIRequestData | null
processResponse(popclip: PopClip, resp: APIResponse): string {
return resp.data.choices[0].message.content.trim()
}
Expand Down Expand Up @@ -148,8 +157,6 @@ class ChatAction extends ChatGPTAction {
this.chatHistories = new Map()
}



private getChatHistory(appIdentifier: string): ChatHistory {
let chat = this.chatHistories.get(appIdentifier)
if (!chat) {
Expand All @@ -167,16 +174,16 @@ class ChatAction extends ChatGPTAction {
}
}

beforeRequest(popclip: PopClip, input: Input, options: Options, action: AllowedActions): boolean {
beforeRequest(popclip: PopClip, input: Input, options: Options, action: AllowedActions): { allow: boolean, reason?: string } {
if (popclip.modifiers.shift) {
this.chatHistories.delete(popclip.context.appIdentifier)
popclip.showText(`${popclip.context.appName}'s chat history has been cleared`)
return false
const text = `${popclip.context.appName}(${popclip.context.appIdentifier})'s chat history has been cleared`
return { allow: false, reason: text }
}
return true
return { allow: true }
}

makeRequestData(popclip: PopClip, input: Input, options: Options, action: AllowedActions): object | null {
makeRequestData(popclip: PopClip, input: Input, options: Options, action: AllowedActions): APIRequestData | null {
if (action !== "chat") {
return null
}
Expand All @@ -185,6 +192,7 @@ class ChatAction extends ChatGPTAction {
return {
model: options.model,
messages: chat.messages,
temperature: Number(options.temperature),
}
}

Expand Down Expand Up @@ -212,21 +220,16 @@ class OneTimeAction extends ChatGPTAction {
}
}

beforeRequest(popclip: PopClip, input: Input, options: Options, action: AllowedActions): boolean {
return options[`${action}Enabled`]
beforeRequest(popclip: PopClip, input: Input, options: Options, action: AllowedActions): { allow: boolean, reason?: string } {
return { allow: options[`${action}Enabled`] }
}

makeRequestData(popclip: PopClip, input: Input, options: Options, action: AllowedActions): object | null {
makeRequestData(popclip: PopClip, input: Input, options: Options, action: AllowedActions): APIRequestData | null {
if (action === "chat") {
return null
}

// FIXME: why does this conditional/ternary operator not work?
// const language = popclip.modifiers.shift ? options[`${action}PrimaryLanguage`] : options[`${action}SecondaryLanguage`]
let language = options[`${action}PrimaryLanguage`]
if (popclip.modifiers.shift) {
language = options[`${action}SecondaryLanguage`]
}
const language = popclip.modifiers.shift ? options[`${action}SecondaryLanguage`] : options[`${action}PrimaryLanguage`]
const prompt = this.getPrompt(action as AllowedOneTimeActions, language)
return {
model: options.model,
Expand All @@ -236,9 +239,10 @@ class OneTimeAction extends ChatGPTAction {
role: "user", content: `${prompt}
The input text being used for this task is enclosed within triple quotation marks below the next line:
"""${input.text}"""`
"""${input.text}"""`,
},
],
temperature: Number(options.temperature),
}
}
}
Expand Down Expand Up @@ -284,7 +288,12 @@ async function doAction(popclip: PopClip, input: Input, options: Options, action
doCleanup()

const actionImpl = chatGPTActions.get(action)!
if (!actionImpl.beforeRequest(popclip, input, options, action)) {
const guard = actionImpl.beforeRequest(popclip, input, options, action)
if (!guard.allow) {
if (guard.reason) {
popclip.showText(guard.reason)
popclip.showSuccess()
}
return
}

Expand Down Expand Up @@ -322,28 +331,24 @@ export const actions = [
title: "ChatGPTx: do what you want (click with shift(⇧) to force clear the history for this app)",
// icon: "symbol:arrow.up.message.fill", // icon: "iconify:uil:edit",
requirements: ["text"],
capture_html: true,
code: async (input: Input, options: Options) => doAction(popclip, input, options, "chat"),
code: async (input: Input, options: Options, context: Context) => doAction(popclip, input, options, "chat"),
},
{
title: "ChatGPTx: revise text (click with shift(⇧) to use the secondary language)",
icon: "symbol:r.square.fill", // icon: "iconify:uil:edit",
requirements: ["text", "option-reviseEnabled=1"],
capture_html: true,
code: async (input: Input, options: Options) => doAction(popclip, input, options, "revise"),
code: async (input: Input, options: Options, context: Context) => doAction(popclip, input, options, "revise"),
},
{
title: "ChatGPTx: polish text (click with shift(⇧) to use the secondary language)",
icon: "symbol:p.square.fill", // icon: "iconify:lucide:stars",
requirements: ["text", "option-polishEnabled=1"],
capture_html: true,
code: async (input: Input, options: Options) => doAction(popclip, input, options, "polish"),
code: async (input: Input, options: Options, context: Context) => doAction(popclip, input, options, "polish"),
},
{
title: "ChatGPTx: translate text (click with shift(⇧) to use the secondary language)",
icon: "symbol:t.square.fill", // icon: "iconify:system-uicons:translate",
requirements: ["text", "option-translateEnabled=1"],
capture_html: true,
code: async (input: Input, options: Options) => doAction(popclip, input, options, "translate"),
code: async (input: Input, options: Options, context: Context) => doAction(popclip, input, options, "translate"),
},
]
26 changes: 26 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"compilerOptions": {
"strict": true,
"noImplicitAny": false,
// note es2018 requires macOS 10.14
// once we drop support for high sierra this can be bumped for cleaner js code
// (note es2018 is required for async generators)
"target": "es2017",
"lib": [
"es2021"
],
// we can specify esnext lib due to polyfills in popclip
"skipLibCheck": true,
"module": "commonjs",
"esModuleInterop": false,
"moduleResolution": "node",
},
"include": [
"./main.ts",
],
"ts-standard": {
"ignore": [
"**/*.js"
]
},
}

0 comments on commit 60b07e5

Please sign in to comment.