Skip to content

Commit

Permalink
allow completion execution
Browse files Browse the repository at this point in the history
  • Loading branch information
drriguz committed Jan 10, 2024
1 parent 196a485 commit adeab9c
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 16 deletions.
4 changes: 3 additions & 1 deletion src/PromptEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export class PromptEditor implements vscode.CustomTextEditorProvider {
switch (e.type) {
case "sync":
this.updateTextDocument(document, e.text);
case "error":
vscode.window.showErrorMessage(e.text);
default:
break;
}
Expand Down Expand Up @@ -106,7 +108,7 @@ export class PromptEditor implements vscode.CustomTextEditorProvider {
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Security-Policy" content="default-src 'none';img-src ${
webview.cspSource
} blob:; connect-src https://us-central1-aiplatform.googleapis.com; style-src ${
} blob:; connect-src https://us-central1-aiplatform.googleapis.com https://api.openai.com; style-src ${
webview.cspSource
} 'nonce-${nonce}' ; font-src ${
webview.cspSource
Expand Down
21 changes: 15 additions & 6 deletions webview-ui/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import { ChatPrompt, CompletionPrompt } from "prompt-schema";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import "./App.css";
import "./codicon.css";
import ChatEditor from "./components/ChatEditor";
import CompletionEditor from "./components/CompletionEditor";
import Error from "./components/Error";
import Loading from "./components/Loading";
import Sidebar from "./components/Sidebar";
import { PromptExecutionDelegate } from "./providers/Executor";
import Result from "./providers/Result";
import { syncPrompt } from "./utilities/Message";
import { loadPrompt } from "./utilities/PromptLoader";
import { vscode } from "./utilities/vscode";

function App() {
const [prompt, setPrompt] = useState<ChatPrompt | CompletionPrompt | null>(null);
const [errors, setErrors] = useState<string[]>([]);
const [activeTab, setActiveTab] = useState("");
const [variableBinding, setVariableBinding] = useState({});
const [openAIKey, setOpenAIKey] = useState(null);

const onPromptChanged = (newPrompt: ChatPrompt | CompletionPrompt) => {
vscode.postMessage({
type: "sync",
text: JSON.stringify(newPrompt, null, 2),
});
syncPrompt(newPrompt);
setPrompt(newPrompt);
};

Expand All @@ -41,6 +41,14 @@ function App() {
}
};

const executePrompt = useCallback(
(prompt: CompletionPrompt): Promise<Result> => {
const deleagate = new PromptExecutionDelegate(openAIKey || "");
return deleagate.executeCompletion(prompt);
},
[openAIKey]
);

useEffect(() => {
window.addEventListener("message", messageListener);
return () => {
Expand Down Expand Up @@ -71,6 +79,7 @@ function App() {
)}
{mode == "completion" && (
<CompletionEditor
executePrompt={executePrompt}
prompt={prompt as CompletionPrompt}
onPromptChanged={onPromptChanged}
activeTab={activeTab}
Expand Down
2 changes: 1 addition & 1 deletion webview-ui/src/components/ChatEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ function ChatEditor({
onMessageDeleted={onMessageDeleted}
onMessageInserted={onMessageInserted}
/>
<VSCodeButton className="button">Submit</VSCodeButton>
<VSCodeButton className="button mt-10">Submit</VSCodeButton>
</div>
<VSCodePanels activeid={activeTab} onChange={onTabChange}>
<VSCodePanelTab id="tab-result">RESULT</VSCodePanelTab>
Expand Down
44 changes: 38 additions & 6 deletions webview-ui/src/components/CompletionEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import {
VSCodePanelTab,
VSCodePanelView,
VSCodePanels,
VSCodeProgressRing,
VSCodeTextArea,
} from "@vscode/webview-ui-toolkit/react";
import { CompletionPrompt } from "prompt-schema";
import { useState } from "react";
import Result from "../providers/Result";
import { showError } from "../utilities/Message";
import { parseVariables } from "../utilities/PromptHelper";
import Variables, { VariableBinding } from "./Variables";

Expand All @@ -15,6 +19,7 @@ interface CompletionEditorProps {
activeTab?: string;
onTabActive: (id: string) => void;
onVariableBinded: (name: string, value: string) => void;
executePrompt: (prompt: CompletionPrompt) => Promise<Result>;
}

function CompletionEditor({
Expand All @@ -23,7 +28,12 @@ function CompletionEditor({
activeTab,
onTabActive,
onVariableBinded,
executePrompt,
}: CompletionEditorProps) {
const [executing, setExecuting] = useState<boolean>(false);
const [error, setError] = useState<null | string>(null);
const [result, setResult] = useState<null | Result>(null);

const variables = parseVariables(prompt.prompt).map((v) => new VariableBinding(v, ""));
const onTextChanged = (text: string) => {
if (text != prompt.prompt) {
Expand All @@ -34,26 +44,48 @@ function CompletionEditor({
const onTabChange = (e: any) => {
if (e.detail && e.detail.id) onTabActive(e.detail.id);
};

const onSubmit = async () => {
if (prompt.prompt === "") {
showError("Please input prompt");
return;
}
try {
setExecuting(true);
const result = await executePrompt(prompt);
} catch (err) {
setError(`${err}`);
} finally {
setExecuting(false);
}
};

return (
<div className="flex-grow flex-column pl-10 pr-10">
<div className="flex flex-column">
<div className="title flex flex-row align-center">
<span className="label fill">Prompt</span>
</div>
<div className="flex flex-column mt-10">
<VSCodeTextArea
className="input mb-10"
resize="vertical"
rows={10}
value={prompt.prompt}
onChange={(e) => onTextChanged((e.target as HTMLInputElement).value)}
placeholder="Enter your prompt here"></VSCodeTextArea>
<VSCodeButton className="button">Submit</VSCodeButton>
<div className="flex">
<VSCodeButton
className="button fixed-100"
disabled={executing}
onClick={onSubmit}>
Submit
</VSCodeButton>
{executing && <VSCodeProgressRing />}
</div>
</div>
<VSCodePanels activeid={activeTab} onChange={onTabChange}>
<VSCodePanelTab id="tab-result">RESULT</VSCodePanelTab>
<VSCodePanelTab id="tab-variables">VARIABLES</VSCodePanelTab>
<VSCodePanelView id="view-result" className="no-padding">
<p>No result yet, click submit to execute the prompt.</p>
{!error && !result && <p>No result yet, click submit to execute the prompt.</p>}
{error && <p className="danger pre-line">{error}</p>}
</VSCodePanelView>
<VSCodePanelView id="view-variables" className="no-padding">
<Variables
Expand Down
1 change: 0 additions & 1 deletion webview-ui/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ function Sidebar({ prompt, onPromptChanged }: SidebarProps) {
const mode = getMode(type);

const parameterProps = buildParameterProps(model, prompt.parameters || []);
console.log(parameterProps);

const onTypeChanged = (selectedMode: string) => {
if (selectedMode != mode) {
Expand Down
19 changes: 18 additions & 1 deletion webview-ui/src/providers/Executor.ts
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
export interface PromptExecutor {}
import { CompletionPrompt } from "prompt-schema";
import { OpenAIExecutor } from "./OpenAI";
import Result from "./Result";

export interface PromptExecutor {
executeCompletion(prompt: CompletionPrompt): Promise<Result>;
}

export class PromptExecutionDelegate implements PromptExecutor {
private openAiExecutor: OpenAIExecutor;
constructor(private openAIApiKey: string) {
this.openAiExecutor = new OpenAIExecutor(openAIApiKey);
}

async executeCompletion(prompt: CompletionPrompt): Promise<Result> {
return this.openAiExecutor.executeCompletion(prompt);
}
}
43 changes: 43 additions & 0 deletions webview-ui/src/providers/OpenAI.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { CompletionPrompt } from "prompt-schema";
import { InterfaceType, ModelType, ParameterType } from "./Common";
import { PromptExecutor } from "./Executor";
import Result from "./Result";

const DEFAULT_SYSTEM: ParameterType = {
name: "system",
Expand Down Expand Up @@ -110,3 +113,43 @@ export const GPT3_5_MODELS: ModelType[] = [
"Currently points to gpt-3.5-turbo-0613. Will point to gpt-3.5-turbo-1106 starting Dec 11, 2023. ",
},
];

class CompletionRequest {
constructor(
public model: string,
public prompt: string,
public max_tokens?: number,
public temperature?: number,
public top_p?: number,
public n?: number,
public logprobs?: number,
public suffix?: string,
public stop?: string,
public presence_penalty?: number,
public frequency_penalty?: number
) {}
}

export class OpenAIExecutor implements PromptExecutor {
constructor(private apiKey: string) {}
async executeCompletion(prompt: CompletionPrompt): Promise<Result> {
const request = new CompletionRequest(prompt.engine, prompt.prompt);
return fetch("https://api.openai.com/v1/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${this.apiKey}`,
},
body: JSON.stringify(request),
})
.then((response) => {
if (!response.ok) {
return response.json().then((errorBody: any) => {
throw new Error(`HTTP ${response.status}:\n${errorBody.error.message}`);
});
}
return response.json();
})
.then((data) => Result.fromJSON(data));
}
}
21 changes: 21 additions & 0 deletions webview-ui/src/providers/Result.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* see:
* https://platform.openai.com/docs/api-reference
* https://learn.microsoft.com/en-us/azure/ai-services/openai/reference
*/

export class Choice {
constructor(public text: string, public index: number, public finishReason: string) {}
}

export default class Result {
constructor(public id: string, public created: number, public choices: Choice[]) {}
static fromJSON(json: any): Result {
const choices = json.choices.map(
(choiceJSON: any) =>
new Choice(choiceJSON.text, choiceJSON.index, choiceJSON.finishReason)
);

return new Result(json.id, json.created, choices);
}
}
16 changes: 16 additions & 0 deletions webview-ui/src/utilities/Message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ChatPrompt, CompletionPrompt } from "prompt-schema";
import { vscode } from "./vscode";

export function syncPrompt(newPrompt: ChatPrompt | CompletionPrompt) {
vscode.postMessage({
type: "sync",
text: JSON.stringify(newPrompt, null, 2),
});
}

export function showError(info: string) {
vscode.postMessage({
type: "error",
text: info,
});
}

0 comments on commit adeab9c

Please sign in to comment.