From ca5d3c0ab073e7b9997e35f07bc2fdc191df336a Mon Sep 17 00:00:00 2001 From: sam hoang Date: Sun, 19 Jan 2025 15:19:21 +0700 Subject: [PATCH] feat(openai-compatible): tune UI UX custom model info --- .../src/components/settings/ApiOptions.tsx | 578 ++++++++++++------ 1 file changed, 400 insertions(+), 178 deletions(-) diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index a9ec8d5..083c35b 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -1,4 +1,4 @@ -import { Checkbox, Dropdown } from "vscrui" +import { Checkbox, Dropdown, Pane } from "vscrui" import type { DropdownOption } from "vscrui" import { VSCodeLink, VSCodeRadio, VSCodeRadioGroup, VSCodeTextField } from "@vscode/webview-ui-toolkit/react" import { Fragment, memo, useCallback, useEffect, useMemo, useState } from "react" @@ -559,203 +559,425 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = /> )} - {/* Model Info Configuration */}
-
- Model Configuration + }} + /> + + handleInputChange("openAiCusModelInfo")({ + target: { value: openAiModelInfoSaneDefaults }, + }), + }, + ]}> +

Configure the capabilities and pricing for your custom OpenAI-compatible model

-
- {/* Capabilities Section */} -
-
- { - const value = parseInt(e.target.value) - handleInputChange("openAiCusModelInfo")({ - target: { - value: { - ...(apiConfiguration?.openAiCusModelInfo || - openAiModelInfoSaneDefaults), - maxTokens: isNaN(value) ? undefined : value, - }, - }, - }) - }} - placeholder="e.g. 4096"> - Max Output Tokens - - - { - const parsed = parseInt(e.target.value) - handleInputChange("openAiCusModelInfo")({ - target: { - value: { - ...(apiConfiguration?.openAiCusModelInfo || - openAiModelInfoSaneDefaults), - contextWindow: - e.target.value === "" - ? undefined - : isNaN(parsed) - ? openAiModelInfoSaneDefaults.contextWindow - : parsed, - }, - }, - }) - }} - placeholder="e.g. 128000"> - Context Window Size - - -
- { - handleInputChange("openAiCusModelInfo")({ - target: { - value: { - ...(apiConfiguration?.openAiCusModelInfo || - openAiModelInfoSaneDefaults), - supportsImages: checked, - }, - }, - }) - }}> - Supports Images - - - { - handleInputChange("openAiCusModelInfo")({ - target: { - value: { - ...(apiConfiguration?.openAiCusModelInfo || - openAiModelInfoSaneDefaults), - supportsComputerUse: checked, - }, - }, - }) - }}> - Supports Computer Use - -
-
-
- - {/* Pricing Section */} -
- - Pricing (USD per million tokens) - -
- {/* Input/Output Prices */} -
- { - const parsed = parseFloat(e.target.value) - handleInputChange("openAiCusModelInfo")({ - target: { - value: { - ...(apiConfiguration?.openAiCusModelInfo ?? - openAiModelInfoSaneDefaults), - inputPrice: - e.target.value === "" - ? undefined - : isNaN(parsed) - ? openAiModelInfoSaneDefaults.inputPrice - : parsed, + + Model Capabilities + +
+
+ { + const value = apiConfiguration?.openAiCusModelInfo?.maxTokens + if (!value) return "var(--vscode-input-border)" + return value > 0 + ? "var(--vscode-charts-green)" + : "var(--vscode-errorForeground)" + })(), + }} + title="Maximum number of tokens the model can generate in a single response" + onChange={(e: any) => { + const value = parseInt(e.target.value) + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + maxTokens: isNaN(value) ? undefined : value, + }, }, - }, - }) - }} - placeholder="e.g. 0.0001"> - Input Price - + }) + }} + placeholder="e.g. 4096"> + Max Output Tokens + +
+ + + Maximum number of tokens the model can generate in a response. Higher + values allow longer outputs but may increase costs. + +
+
- { - const parsed = parseFloat(e.target.value) - handleInputChange("openAiCusModelInfo")({ - target: { - value: { - ...(apiConfiguration?.openAiCusModelInfo || - openAiModelInfoSaneDefaults), - outputPrice: - e.target.value === "" - ? undefined - : isNaN(parsed) - ? openAiModelInfoSaneDefaults.outputPrice - : parsed, +
+ { + const value = apiConfiguration?.openAiCusModelInfo?.contextWindow + if (!value) return "var(--vscode-input-border)" + return value > 0 + ? "var(--vscode-charts-green)" + : "var(--vscode-errorForeground)" + })(), + }} + title="Total number of tokens (input + output) the model can process in a single request" + onChange={(e: any) => { + const parsed = parseInt(e.target.value) + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + contextWindow: + e.target.value === "" + ? undefined + : isNaN(parsed) + ? openAiModelInfoSaneDefaults.contextWindow + : parsed, + }, }, - }, - }) - }} - placeholder="e.g. 0.0002"> - Output Price - + }) + }} + placeholder="e.g. 128000"> + Context Window Size + +
+ + + Total tokens (input + output) the model can process. Larger windows + allow processing more content but may increase memory usage. + +
+
+ +
+ + Model Features + + +
+
+
+ { + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + supportsImages: checked, + }, + }, + }) + }}> + Image Support + + +
+

+ Allows the model to analyze and understand images, essential for + visual code assistance +

+
+ +
+
+ { + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + supportsComputerUse: checked, + }, + }, + }) + }}> + Computer Interaction + + +
+

+ Enables the model to execute commands and modify files for automated + assistance +

+
+
+
+
+
+ + {/* Pricing Section */} +
+
+ + Model Pricing + + + Configure token-based pricing in USD per million tokens + +
+ +
+
+ { + const value = apiConfiguration?.openAiCusModelInfo?.inputPrice + if (!value && value !== 0) return "var(--vscode-input-border)" + return value >= 0 + ? "var(--vscode-charts-green)" + : "var(--vscode-errorForeground)" + })(), + }} + onChange={(e: any) => { + const parsed = parseFloat(e.target.value) + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo ?? + openAiModelInfoSaneDefaults), + inputPrice: + e.target.value === "" + ? undefined + : isNaN(parsed) + ? openAiModelInfoSaneDefaults.inputPrice + : parsed, + }, + }, + }) + }} + placeholder="e.g. 0.0001"> +
+ Input Price + +
+
+
+ +
+ { + const value = apiConfiguration?.openAiCusModelInfo?.outputPrice + if (!value && value !== 0) return "var(--vscode-input-border)" + return value >= 0 + ? "var(--vscode-charts-green)" + : "var(--vscode-errorForeground)" + })(), + }} + onChange={(e: any) => { + const parsed = parseFloat(e.target.value) + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + outputPrice: + e.target.value === "" + ? undefined + : isNaN(parsed) + ? openAiModelInfoSaneDefaults.outputPrice + : parsed, + }, + }, + }) + }} + placeholder="e.g. 0.0002"> +
+ Output Price + +
+
+
-
+
- {/* TODO: model info here */} + {/* end Model Info Configuration */}