From f6f08f774255bcb0640bbca67a6dc05cf9c0b3d9 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Mon, 9 Sep 2024 17:44:05 +0900 Subject: [PATCH 01/27] Add parameter tab component ui on config tab - Add border line on Playground.razor grid item for visualize layout --- .../Components/Pages/Playground.razor | 2 +- .../Components/UI/ParametersTabComponent.razor | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor index 4873e6c7..ff0fb72a 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor @@ -6,7 +6,7 @@ <FluentLayout> <FluentHeader Style="padding-top: 5px;"><h1>Azure OpenAI Proxy Playground</h1></FluentHeader> - <FluentGrid Spacing="3" AdaptiveRendering="true" Justify="JustifyContent.FlexStart"> + <FluentGrid Spacing="0" AdaptiveRendering="true" Justify="JustifyContent.FlexStart"> <FluentGridItem Class="config-grid" xs="12" sm="12" md="4" lg="4" xl="4" xxl="4"> <ConfigWindowComponent Id="config-window" OnSystemMessageChanged="SetSystemMessage" @rendermode="InteractiveServer" /> </FluentGridItem> diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor new file mode 100644 index 00000000..b2806d6a --- /dev/null +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -0,0 +1,8 @@ +<FluentLayout Id="@Id"> + +</FluentLayout> + +@code { + [Parameter] + public string? Id { get; set; } +} From 9c20518ad9341cb5a26b46a4a5c5f47e8236e58d Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Tue, 10 Sep 2024 00:38:24 +0900 Subject: [PATCH 02/27] Add label with tooltip component --- .../Components/UI/LabelWithTooltip.razor | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor new file mode 100644 index 00000000..6530d23e --- /dev/null +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor @@ -0,0 +1,26 @@ +<FluentLabel Typo="Typography.Body" Style="margin-left:10px"> + @LabelText + <FluentIcon Id=@anchorId Value="@(new Icons.Regular.Size12.Info())" /> + <FluentTooltip Anchor=@anchorId Position="TooltipPosition.End" MaxWidth="250px" UseTooltipService="false"> + @TooltipText + </FluentTooltip> +</FluentLabel> + +@code { + [Parameter, EditorRequired] + public string Id { get; set; } = string.Empty; + + [Parameter, EditorRequired] + public string LabelText { get; set; } = string.Empty; + + [Parameter, EditorRequired] + public string TooltipText { get; set; } = string.Empty; + + private string anchorId = string.Empty; + + protected override void OnParametersSet() + { + base.OnParametersSet(); + anchorId = $"{Id}-tooltip"; + } +} \ No newline at end of file From a70db0fad4ebb8e32b819a5615375ba9b5da8ea1 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Tue, 10 Sep 2024 03:39:21 +0900 Subject: [PATCH 03/27] Add slider with text field component --- .../Components/UI/SliderWithTextfield.razor | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor new file mode 100644 index 00000000..6810dfd4 --- /dev/null +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor @@ -0,0 +1,72 @@ +@typeparam TValue where TValue : System.Numerics.INumber<TValue> + +<FluentStack Orientation="Orientation.Horizontal"> + <FluentSlider Min="@Min" Max="@Max" Step="@Step" + @bind-Value=Value @bind-Value:after=AfterSliderChange + Style="width:85%;padding-left:5px;padding-top:15px" /> + <FluentTextField @bind-Value=textFieldValue @bind-Value:after=AfterTextFieldChange + Style="width:15%;padding-right:10px" /> +</FluentStack> + +@if (!hasNoError) +{ + <FluentCard Style="padding:10px;width:95%;margin:0 auto;border-color:red;background-color:ghostwhite;color:red"> + @errorText + </FluentCard> +} + +@code { + [Parameter, EditorRequired] + public TValue? Min { get; set; } = default; + + [Parameter, EditorRequired] + public TValue? Max { get; set; } = default; + + [Parameter, EditorRequired] + public TValue? Step { get; set; } = default; + + [Parameter] + public TValue? Value { get; set; } + + [Parameter] + public EventCallback<TValue> ValueChanged { get; set; } + + [Parameter] + public EventCallback OnChangeEvent { get; set; } + + public string? textFieldValue { get; set; } + + private bool hasNoError = true; + private string errorText = string.Empty; + + protected override void OnInitialized() + { + base.OnInitialized(); + textFieldValue = Value!.ToString(); + errorText = $"Only numbers between {Min} and {Max} are permitted"; + } + + private async Task AfterSliderChange() + { + hasNoError = true; + textFieldValue = Value!.ToString(); + + await ValueChanged.InvokeAsync(Value); + await OnChangeEvent.InvokeAsync(); + } + + private async Task AfterTextFieldChange() + { + hasNoError = TValue.TryParse(textFieldValue, null, out var parsed); + if (!hasNoError || parsed == null) + return; + + hasNoError = parsed >= Min! && parsed <= Max!; + if (!hasNoError) + return; + + this.Value = parsed; + await ValueChanged.InvokeAsync(Value); + await OnChangeEvent.InvokeAsync(); + } +} From 4661be787e5413d260fc8fdb21382f62293c386b Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Tue, 10 Sep 2024 11:59:11 +0900 Subject: [PATCH 04/27] Add parameter tab ui contents --- .../UI/ParametersTabComponent.razor | 73 ++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index b2806d6a..df5c1f56 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -1,8 +1,77 @@ -<FluentLayout Id="@Id"> +@using System.Linq +<FluentLayout Id="@Id"> + <LabelWithTooltip Id="slider-past-messages" + LabelText="Past messages included" + TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." /> + <SliderWithTextfield Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue /> + + <LabelWithTooltip Id="slider-max-response" + LabelText="Max response" + TooltipText="Set a limit on the number of tokens per model response. The API supports a maximum of MaxTokensPlaceholderDoNotTranslate tokens shared between the prompt (including system message, examples, message history, and user query) and the model's response. One token is roughly 4 characters for typical English text." /> + <SliderWithTextfield Min="1" Max="16000" Step="1" @bind-Value=@maxResponseValue /> + + <LabelWithTooltip Id="slider-temperature" + LabelText="Temperature" + TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." /> + <SliderWithTextfield Min="0" Max="1" Step="0.01" @bind-Value=@temperatureValue /> + + <LabelWithTooltip Id="slider-top-p" + LabelText="Top P" + TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." /> + <SliderWithTextfield Min="0" Max="1" Step="0.01" @bind-Value=@topPValue /> + + <LabelWithTooltip Id="complete-stop-sequence" + LabelText="Stop sequence" + TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." /> + + <FluentAutocomplete TOption="string" Multiple="true" AutoComplete="false" + ShowOverlayOnEmptyResults="false" + SelectValueOnTab="true" + MaximumOptionsSearch="1" + @bind-SelectedOptions=stopSequenceValue + OnOptionsSearch=OnSearchAsync + Style="width:95%;padding:5px 0px;margin: 0 auto"> + <OptionTemplate> + <FluentLabel>Create "@(context)"</FluentLabel> + </OptionTemplate> + </FluentAutocomplete> + + <LabelWithTooltip Id="slider-frequency-penalty" + LabelText="Frequency penalty" + TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." /> + <SliderWithTextfield Min="0" Max="2" Step="0.01" @bind-Value=@frequencyPenaltyValue /> + + <LabelWithTooltip Id="slider-presence-penalty" + LabelText="Presence penalty" + TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." /> + <SliderWithTextfield Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue /> </FluentLayout> @code { [Parameter] public string? Id { get; set; } -} + + private int pastMessagesValue = 10; + private int maxResponseValue = 800; + private double temperatureValue = 0.7; + private double topPValue = 0.95; + + private double frequencyPenaltyValue = 0; + private double presencePenaltyValue = 0; + + private IEnumerable<string> stopSequenceValue = new List<string>(); + private List<string> searchTextItems = new(); + + private Task OnSearchAsync(OptionsSearchEventArgs<string> e) + { + searchTextItems.Clear(); + if (string.IsNullOrEmpty(e.Text) || stopSequenceValue.Contains(e.Text)) + return Task.CompletedTask; + + searchTextItems.Add(e.Text); + e.Items = searchTextItems; + + return Task.CompletedTask; + } +} \ No newline at end of file From 36201f1892ce735dc7f24eec84c31809097d5308 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Tue, 10 Sep 2024 16:31:19 +0900 Subject: [PATCH 05/27] Move position css of child component to parent --- .../Components/UI/LabelWithTooltip.razor | 10 ++++-- .../UI/ParametersTabComponent.razor | 34 ++++++++++++------- .../Components/UI/SliderWithTextfield.razor | 13 ++++--- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor index 6530d23e..e2094444 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor @@ -1,7 +1,10 @@ -<FluentLabel Typo="Typography.Body" Style="margin-left:10px"> +<FluentLabel Typo="Typography.Body" Style=@Style> @LabelText <FluentIcon Id=@anchorId Value="@(new Icons.Regular.Size12.Info())" /> - <FluentTooltip Anchor=@anchorId Position="TooltipPosition.End" MaxWidth="250px" UseTooltipService="false"> + <FluentTooltip Anchor=@anchorId Position="TooltipPosition.End" + UseTooltipService="false" + MaxWidth="250px" + Style="line-break:anywhere"> @TooltipText </FluentTooltip> </FluentLabel> @@ -16,6 +19,9 @@ [Parameter, EditorRequired] public string TooltipText { get; set; } = string.Empty; + [Parameter] + public string? Style { get; set; } = null; + private string anchorId = string.Empty; protected override void OnParametersSet() diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index df5c1f56..0cafc547 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -3,27 +3,33 @@ <FluentLayout Id="@Id"> <LabelWithTooltip Id="slider-past-messages" LabelText="Past messages included" - TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." /> - <SliderWithTextfield Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue /> + TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." + Style="padding-left:10px;font-weight:bold" /> + + <SliderWithTextfield Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue Style="padding-left:5px;padding-right:10px;" /> <LabelWithTooltip Id="slider-max-response" LabelText="Max response" - TooltipText="Set a limit on the number of tokens per model response. The API supports a maximum of MaxTokensPlaceholderDoNotTranslate tokens shared between the prompt (including system message, examples, message history, and user query) and the model's response. One token is roughly 4 characters for typical English text." /> - <SliderWithTextfield Min="1" Max="16000" Step="1" @bind-Value=@maxResponseValue /> + TooltipText="Set a limit on the number of tokens per model response. The API supports a maximum of MaxTokensPlaceholderDoNotTranslate tokens shared between the prompt (including system message, examples, message history, and user query) and the model's response. One token is roughly 4 characters for typical English text." + Style="padding-left:10px;font-weight:bold" /> + <SliderWithTextfield Min="1" Max="16000" Step="1" @bind-Value=@maxResponseValue Style="padding-left:5px;padding-right:10px;" /> <LabelWithTooltip Id="slider-temperature" LabelText="Temperature" - TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." /> - <SliderWithTextfield Min="0" Max="1" Step="0.01" @bind-Value=@temperatureValue /> + TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." + Style="padding-left:10px;font-weight:bold" /> + <SliderWithTextfield Min="0" Max="1" Step="0.01" @bind-Value=@temperatureValue Style="padding-left:5px;padding-right:10px;" /> <LabelWithTooltip Id="slider-top-p" LabelText="Top P" - TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." /> - <SliderWithTextfield Min="0" Max="1" Step="0.01" @bind-Value=@topPValue /> + TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." + Style="padding-left:10px;font-weight:bold" /> + <SliderWithTextfield Min="0" Max="1" Step="0.01" @bind-Value=@topPValue Style="padding-left:5px;padding-right:10px;" /> <LabelWithTooltip Id="complete-stop-sequence" LabelText="Stop sequence" - TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." /> + TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." + Style="padding-left:10px;font-weight:bold" /> <FluentAutocomplete TOption="string" Multiple="true" AutoComplete="false" ShowOverlayOnEmptyResults="false" @@ -39,13 +45,15 @@ <LabelWithTooltip Id="slider-frequency-penalty" LabelText="Frequency penalty" - TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." /> - <SliderWithTextfield Min="0" Max="2" Step="0.01" @bind-Value=@frequencyPenaltyValue /> + TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." + Style="padding-left:10px;font-weight:bold" /> + <SliderWithTextfield Min="0" Max="2" Step="0.01" @bind-Value=@frequencyPenaltyValue Style="padding-left:5px;padding-right:10px;" /> <LabelWithTooltip Id="slider-presence-penalty" LabelText="Presence penalty" - TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." /> - <SliderWithTextfield Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue /> + TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." + Style="padding-left:10px;font-weight:bold" /> + <SliderWithTextfield Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue Style="padding-left:5px;padding-right:10px;" /> </FluentLayout> @code { diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor index 6810dfd4..af0c9a6e 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor @@ -1,18 +1,18 @@ @typeparam TValue where TValue : System.Numerics.INumber<TValue> -<FluentStack Orientation="Orientation.Horizontal"> +<FluentStack Orientation="Orientation.Horizontal" Style=@Style> <FluentSlider Min="@Min" Max="@Max" Step="@Step" @bind-Value=Value @bind-Value:after=AfterSliderChange - Style="width:85%;padding-left:5px;padding-top:15px" /> + Style="width:88%;padding-top:15px;" /> <FluentTextField @bind-Value=textFieldValue @bind-Value:after=AfterTextFieldChange - Style="width:15%;padding-right:10px" /> + Style="width:12%;padding-left:0px" /> </FluentStack> @if (!hasNoError) { - <FluentCard Style="padding:10px;width:95%;margin:0 auto;border-color:red;background-color:ghostwhite;color:red"> + <FluentCard Style="padding:10px;width:95%;margin:0 auto;border-color:crimson;background-color:lightcoral;color:black"> @errorText - </FluentCard> + </FluentCard> } @code { @@ -34,6 +34,9 @@ [Parameter] public EventCallback OnChangeEvent { get; set; } + [Parameter] + public string? Style { get; set; } = null; + public string? textFieldValue { get; set; } private bool hasNoError = true; From 6a8d82df1aaa936397449e430a99ec61187dfeca Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Tue, 10 Sep 2024 18:36:30 +0900 Subject: [PATCH 06/27] Comment and code style update --- .../Components/UI/LabelWithTooltip.razor | 3 +++ .../Components/UI/ParametersTabComponent.razor | 13 +++++++++++++ .../Components/UI/SliderWithTextfield.razor | 5 ++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor index e2094444..80980fad 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor @@ -1,5 +1,7 @@ <FluentLabel Typo="Typography.Body" Style=@Style> @LabelText + + @* Tooltip Image *@ <FluentIcon Id=@anchorId Value="@(new Icons.Regular.Size12.Info())" /> <FluentTooltip Anchor=@anchorId Position="TooltipPosition.End" UseTooltipService="false" @@ -7,6 +9,7 @@ Style="line-break:anywhere"> @TooltipText </FluentTooltip> + </FluentLabel> @code { diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index 0cafc547..d1a8e504 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -1,6 +1,8 @@ @using System.Linq <FluentLayout Id="@Id"> + + @* Past Messages Slider *@ <LabelWithTooltip Id="slider-past-messages" LabelText="Past messages included" TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." @@ -8,24 +10,30 @@ <SliderWithTextfield Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue Style="padding-left:5px;padding-right:10px;" /> + @* Max Response Slider *@ <LabelWithTooltip Id="slider-max-response" LabelText="Max response" TooltipText="Set a limit on the number of tokens per model response. The API supports a maximum of MaxTokensPlaceholderDoNotTranslate tokens shared between the prompt (including system message, examples, message history, and user query) and the model's response. One token is roughly 4 characters for typical English text." Style="padding-left:10px;font-weight:bold" /> + <SliderWithTextfield Min="1" Max="16000" Step="1" @bind-Value=@maxResponseValue Style="padding-left:5px;padding-right:10px;" /> + @* Temperature Slider *@ <LabelWithTooltip Id="slider-temperature" LabelText="Temperature" TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." Style="padding-left:10px;font-weight:bold" /> + <SliderWithTextfield Min="0" Max="1" Step="0.01" @bind-Value=@temperatureValue Style="padding-left:5px;padding-right:10px;" /> + @* Top P Slider *@ <LabelWithTooltip Id="slider-top-p" LabelText="Top P" TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." Style="padding-left:10px;font-weight:bold" /> <SliderWithTextfield Min="0" Max="1" Step="0.01" @bind-Value=@topPValue Style="padding-left:5px;padding-right:10px;" /> + @* Stop Sequence Auto Complete *@ <LabelWithTooltip Id="complete-stop-sequence" LabelText="Stop sequence" TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." @@ -43,17 +51,22 @@ </OptionTemplate> </FluentAutocomplete> + @* Frequency Penalty Slider *@ <LabelWithTooltip Id="slider-frequency-penalty" LabelText="Frequency penalty" TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." Style="padding-left:10px;font-weight:bold" /> + <SliderWithTextfield Min="0" Max="2" Step="0.01" @bind-Value=@frequencyPenaltyValue Style="padding-left:5px;padding-right:10px;" /> + @* Presence Penalty Slider *@ <LabelWithTooltip Id="slider-presence-penalty" LabelText="Presence penalty" TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." Style="padding-left:10px;font-weight:bold" /> + <SliderWithTextfield Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue Style="padding-left:5px;padding-right:10px;" /> + </FluentLayout> @code { diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor index af0c9a6e..f675c21a 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor @@ -1,18 +1,21 @@ @typeparam TValue where TValue : System.Numerics.INumber<TValue> <FluentStack Orientation="Orientation.Horizontal" Style=@Style> + <FluentSlider Min="@Min" Max="@Max" Step="@Step" @bind-Value=Value @bind-Value:after=AfterSliderChange Style="width:88%;padding-top:15px;" /> + <FluentTextField @bind-Value=textFieldValue @bind-Value:after=AfterTextFieldChange Style="width:12%;padding-left:0px" /> + </FluentStack> @if (!hasNoError) { <FluentCard Style="padding:10px;width:95%;margin:0 auto;border-color:crimson;background-color:lightcoral;color:black"> @errorText - </FluentCard> + </FluentCard> } @code { From 95039ebb16e2d88fd36ca95eb78238b8e8e03559 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Tue, 10 Sep 2024 19:18:02 +0900 Subject: [PATCH 07/27] Inherit fluent component base to derived component --- .../Components/UI/LabelWithTooltip.razor | 9 ++------- .../Components/UI/SliderWithTextfield.razor | 8 +++----- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor index 80980fad..b4e1c9af 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor @@ -1,4 +1,5 @@ -<FluentLabel Typo="Typography.Body" Style=@Style> +@inherits FluentComponentBase +<FluentLabel Typo="Typography.Body" Style=@Style> @LabelText @* Tooltip Image *@ @@ -13,18 +14,12 @@ </FluentLabel> @code { - [Parameter, EditorRequired] - public string Id { get; set; } = string.Empty; - [Parameter, EditorRequired] public string LabelText { get; set; } = string.Empty; [Parameter, EditorRequired] public string TooltipText { get; set; } = string.Empty; - [Parameter] - public string? Style { get; set; } = null; - private string anchorId = string.Empty; protected override void OnParametersSet() diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor index f675c21a..75f3e233 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor @@ -1,4 +1,5 @@ -@typeparam TValue where TValue : System.Numerics.INumber<TValue> +@inherits FluentComponentBase +@typeparam TValue where TValue : System.Numerics.INumber<TValue> <FluentStack Orientation="Orientation.Horizontal" Style=@Style> @@ -7,7 +8,7 @@ Style="width:88%;padding-top:15px;" /> <FluentTextField @bind-Value=textFieldValue @bind-Value:after=AfterTextFieldChange - Style="width:12%;padding-left:0px" /> + Style="width:12%;padding-left:0px;font-size:9px" /> </FluentStack> @@ -37,9 +38,6 @@ [Parameter] public EventCallback OnChangeEvent { get; set; } - [Parameter] - public string? Style { get; set; } = null; - public string? textFieldValue { get; set; } private bool hasNoError = true; From acb60479ee66c327a81f08585190d4d2e7460516 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Wed, 11 Sep 2024 01:08:41 +0900 Subject: [PATCH 08/27] Move inline styles to isolated css file --- .../Components/UI/LabelWithTooltip.razor | 10 ++--- .../UI/ParametersTabComponent.razor | 45 ++++++++++--------- .../UI/ParametersTabComponent.razor.css | 9 ++++ .../Components/UI/SliderWithTextfield.razor | 28 ++++++------ 4 files changed, 52 insertions(+), 40 deletions(-) create mode 100644 src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor index b4e1c9af..88756b1d 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor @@ -1,5 +1,6 @@ @inherits FluentComponentBase -<FluentLabel Typo="Typography.Body" Style=@Style> + +<div class=@Class> @LabelText @* Tooltip Image *@ @@ -10,8 +11,7 @@ Style="line-break:anywhere"> @TooltipText </FluentTooltip> - -</FluentLabel> +</div> @code { [Parameter, EditorRequired] @@ -22,9 +22,9 @@ private string anchorId = string.Empty; - protected override void OnParametersSet() + protected override void OnInitialized() { - base.OnParametersSet(); + base.OnInitialized(); anchorId = $"{Id}-tooltip"; } } \ No newline at end of file diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index d1a8e504..58cdfa06 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -1,43 +1,44 @@ @using System.Linq -<FluentLayout Id="@Id"> +<div id="@Id"> @* Past Messages Slider *@ <LabelWithTooltip Id="slider-past-messages" + Class="label-with-tooltip" LabelText="Past messages included" - TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." - Style="padding-left:10px;font-weight:bold" /> + TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." /> - <SliderWithTextfield Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue Style="padding-left:5px;padding-right:10px;" /> + <SliderWithTextfield Class="slider-with-text" Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue /> @* Max Response Slider *@ <LabelWithTooltip Id="slider-max-response" + Class="label-with-tooltip" LabelText="Max response" - TooltipText="Set a limit on the number of tokens per model response. The API supports a maximum of MaxTokensPlaceholderDoNotTranslate tokens shared between the prompt (including system message, examples, message history, and user query) and the model's response. One token is roughly 4 characters for typical English text." - Style="padding-left:10px;font-weight:bold" /> + TooltipText="Set a limit on the number of tokens per model response. The API supports a maximum of MaxTokensPlaceholderDoNotTranslate tokens shared between the prompt (including system message, examples, message history, and user query) and the model's response. One token is roughly 4 characters for typical English text." /> - <SliderWithTextfield Min="1" Max="16000" Step="1" @bind-Value=@maxResponseValue Style="padding-left:5px;padding-right:10px;" /> + <SliderWithTextfield Class="slider-with-text" Min="1" Max="16000" Step="1" @bind-Value=@maxResponseValue /> @* Temperature Slider *@ <LabelWithTooltip Id="slider-temperature" + Class="label-with-tooltip" LabelText="Temperature" - TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." - Style="padding-left:10px;font-weight:bold" /> + TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." /> - <SliderWithTextfield Min="0" Max="1" Step="0.01" @bind-Value=@temperatureValue Style="padding-left:5px;padding-right:10px;" /> + <SliderWithTextfield Class="slider-with-text" Min="0" Max="1" Step="0.01" @bind-Value=@temperatureValue /> @* Top P Slider *@ <LabelWithTooltip Id="slider-top-p" + Class="label-with-tooltip" LabelText="Top P" - TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." - Style="padding-left:10px;font-weight:bold" /> - <SliderWithTextfield Min="0" Max="1" Step="0.01" @bind-Value=@topPValue Style="padding-left:5px;padding-right:10px;" /> + TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." /> + + <SliderWithTextfield Class="slider-with-text" Min="0" Max="1" Step="0.01" @bind-Value=@topPValue /> @* Stop Sequence Auto Complete *@ <LabelWithTooltip Id="complete-stop-sequence" + Class="label-with-tooltip" LabelText="Stop sequence" - TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." - Style="padding-left:10px;font-weight:bold" /> + TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." /> <FluentAutocomplete TOption="string" Multiple="true" AutoComplete="false" ShowOverlayOnEmptyResults="false" @@ -53,21 +54,21 @@ @* Frequency Penalty Slider *@ <LabelWithTooltip Id="slider-frequency-penalty" + Class="label-with-tooltip" LabelText="Frequency penalty" - TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." - Style="padding-left:10px;font-weight:bold" /> + TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." /> - <SliderWithTextfield Min="0" Max="2" Step="0.01" @bind-Value=@frequencyPenaltyValue Style="padding-left:5px;padding-right:10px;" /> + <SliderWithTextfield Class="slider-with-text" Min="0" Max="2" Step="0.01" @bind-Value=@frequencyPenaltyValue /> @* Presence Penalty Slider *@ <LabelWithTooltip Id="slider-presence-penalty" + Class="label-with-tooltip" LabelText="Presence penalty" - TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." - Style="padding-left:10px;font-weight:bold" /> + TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." /> - <SliderWithTextfield Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue Style="padding-left:5px;padding-right:10px;" /> + <SliderWithTextfield Class="slider-with-text" Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue /> -</FluentLayout> +</div> @code { [Parameter] diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css new file mode 100644 index 00000000..acab3cf1 --- /dev/null +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css @@ -0,0 +1,9 @@ +::deep .label-with-tooltip { + padding-left: 10px; + font-weight: bold; +} + +::deep .slider-with-text { + padding-left: 5px; + padding-right: 10px; +} \ No newline at end of file diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor index 75f3e233..1506b605 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor @@ -1,23 +1,25 @@ @inherits FluentComponentBase @typeparam TValue where TValue : System.Numerics.INumber<TValue> -<FluentStack Orientation="Orientation.Horizontal" Style=@Style> +<div class=@Class> + <FluentStack Orientation="Orientation.Horizontal"> - <FluentSlider Min="@Min" Max="@Max" Step="@Step" - @bind-Value=Value @bind-Value:after=AfterSliderChange - Style="width:88%;padding-top:15px;" /> + <FluentSlider Min="@Min" Max="@Max" Step="@Step" + @bind-Value=Value @bind-Value:after=AfterSliderChange + Style="width:88%;padding-top:15px;" /> - <FluentTextField @bind-Value=textFieldValue @bind-Value:after=AfterTextFieldChange - Style="width:12%;padding-left:0px;font-size:9px" /> + <FluentTextField @bind-Value=textFieldValue @bind-Value:after=AfterTextFieldChange + Style="width:12%;font-size:9px" /> -</FluentStack> + </FluentStack> -@if (!hasNoError) -{ - <FluentCard Style="padding:10px;width:95%;margin:0 auto;border-color:crimson;background-color:lightcoral;color:black"> - @errorText - </FluentCard> -} + @if (!hasNoError) + { + <FluentCard Style="padding:10px;width:95%;margin:0 auto;border-color:crimson;background-color:lightcoral;color:black"> + @errorText + </FluentCard> + } +</div> @code { [Parameter, EditorRequired] From 6951bbf66da26626fffa390aacd67d3d65e42670 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Mon, 16 Sep 2024 14:33:53 +0900 Subject: [PATCH 09/27] Resolve merge conflict --- .../Components/Pages/Playground.razor | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor index ff0fb72a..aa9e0492 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor @@ -11,7 +11,8 @@ <ConfigWindowComponent Id="config-window" OnSystemMessageChanged="SetSystemMessage" @rendermode="InteractiveServer" /> </FluentGridItem> - <FluentGridItem Class="chat-grid" xs="12" sm="12" md="8" lg="8" xl="8" xxl="8" Style="height: 900px;"> + <FluentGridItem Class="chat-grid" xs="12" sm="12" md="8" lg="8" xl="8" xxl="8" + Style="height: 800px;border:1px solid lightgrey"> <ChatWindowComponent Id="chat-window" @rendermode="InteractiveServer" /> </FluentGridItem> </FluentGrid> From e65f4eca4d920428234a3c1a455fc6cc785e88be Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Mon, 16 Sep 2024 18:46:01 +0900 Subject: [PATCH 10/27] Resolve merge conflict --- .../Components/Pages/Playground.razor | 2 +- .../Components/UI/ConfigTabComponent.razor | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor index aa9e0492..2425fb7c 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor @@ -12,7 +12,7 @@ </FluentGridItem> <FluentGridItem Class="chat-grid" xs="12" sm="12" md="8" lg="8" xl="8" xxl="8" - Style="height: 800px;border:1px solid lightgrey"> + Style="border:1px solid lightgrey"> <ChatWindowComponent Id="chat-window" @rendermode="InteractiveServer" /> </FluentGridItem> </FluentGrid> diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigTabComponent.razor index fcfeafb7..afe64b81 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigTabComponent.razor @@ -4,7 +4,7 @@ <SystemMessageTabComponent Id="system-message-tab-component" OnSystemMessageChanged="SetSystemMessage" /> </FluentTab> <FluentTab Id="parameters-tab" Label="Parameters"> - This is "Parameters" tab. + <ParametersTabComponent /> </FluentTab> </FluentTabs> </FluentStack> From b14d8a3fef12fe86d2f320d3b666cc44212e775d Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Wed, 18 Sep 2024 06:34:04 +0900 Subject: [PATCH 11/27] Move label component to slider and list --- .../Components/UI/LabelWithTooltip.razor | 30 ----- .../UI/ParameterListComponent.razor | 56 ++++++++++ ...d.razor => ParameterSliderComponent.razor} | 49 ++++++--- .../UI/ParameterSliderComponent.razor.css | 26 +++++ .../UI/ParametersTabComponent.razor | 103 +++++++----------- .../UI/ParametersTabComponent.razor.css | 9 -- 6 files changed, 154 insertions(+), 119 deletions(-) delete mode 100644 src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor create mode 100644 src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor rename src/AzureOpenAIProxy.PlaygroundApp/Components/UI/{SliderWithTextfield.razor => ParameterSliderComponent.razor} (56%) create mode 100644 src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css delete mode 100644 src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor deleted file mode 100644 index 88756b1d..00000000 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/LabelWithTooltip.razor +++ /dev/null @@ -1,30 +0,0 @@ -@inherits FluentComponentBase - -<div class=@Class> - @LabelText - - @* Tooltip Image *@ - <FluentIcon Id=@anchorId Value="@(new Icons.Regular.Size12.Info())" /> - <FluentTooltip Anchor=@anchorId Position="TooltipPosition.End" - UseTooltipService="false" - MaxWidth="250px" - Style="line-break:anywhere"> - @TooltipText - </FluentTooltip> -</div> - -@code { - [Parameter, EditorRequired] - public string LabelText { get; set; } = string.Empty; - - [Parameter, EditorRequired] - public string TooltipText { get; set; } = string.Empty; - - private string anchorId = string.Empty; - - protected override void OnInitialized() - { - base.OnInitialized(); - anchorId = $"{Id}-tooltip"; - } -} \ No newline at end of file diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor new file mode 100644 index 00000000..184f0e71 --- /dev/null +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor @@ -0,0 +1,56 @@ +@inherits FluentComponentBase + +<div id="@Id"> + <label id=@($"{Id}-label") for=@($"{Id}-content") + style="display:inline-block;padding-left:5px;font-weight:bold;"> + @LabelText + + @* Tooltip Image *@ + <FluentIcon Id=@($"{Id}-anchor") Value="@(new Icons.Regular.Size12.Info())" /> + <FluentTooltip Id=@($"{Id}-tooltip") + Anchor=@($"{Id}-anchor") + Position="TooltipPosition.End" + UseTooltipService="false" + MaxWidth="250px" + Style="line-break:anywhere"> + @TooltipText + </FluentTooltip> + </label> + + <div id=@($"{Id}-content")> + <FluentAutocomplete TOption="string" Multiple="true" AutoComplete="false" + ShowOverlayOnEmptyResults="false" + SelectValueOnTab="true" + MaximumOptionsSearch="1" + @bind-SelectedOptions=stopSequenceValue + OnOptionsSearch=OnSearchAsync + Style="width:95%;padding:5px 0px;margin: 0 auto"> + <OptionTemplate> + <FluentLabel>Create "@(context)"</FluentLabel> + </OptionTemplate> + </FluentAutocomplete> + </div> +</div> + +@code { + [Parameter, EditorRequired] + public string LabelText { get; set; } = string.Empty; + + [Parameter, EditorRequired] + public string TooltipText { get; set; } = string.Empty; + + private IEnumerable<string> stopSequenceValue = new List<string>(); + private List<string> searchTextItems = new(); + + private Task OnSearchAsync(OptionsSearchEventArgs<string> e) + { + searchTextItems.Clear(); + if (string.IsNullOrEmpty(e.Text) || stopSequenceValue.Contains(e.Text)) + return Task.CompletedTask; + + searchTextItems.Add(e.Text); + e.Items = searchTextItems; + + return Task.CompletedTask; + } +} diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor similarity index 56% rename from src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor rename to src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor index 1506b605..01f3c052 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/SliderWithTextfield.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor @@ -1,21 +1,38 @@ @inherits FluentComponentBase @typeparam TValue where TValue : System.Numerics.INumber<TValue> -<div class=@Class> - <FluentStack Orientation="Orientation.Horizontal"> - - <FluentSlider Min="@Min" Max="@Max" Step="@Step" - @bind-Value=Value @bind-Value:after=AfterSliderChange - Style="width:88%;padding-top:15px;" /> - - <FluentTextField @bind-Value=textFieldValue @bind-Value:after=AfterTextFieldChange - Style="width:12%;font-size:9px" /> +<div id="@Id"> + <label id=@($"{Id}-label") class="parameter-label" for=@($"{Id}-content")> + @LabelText + + @* Tooltip Image *@ + <FluentIcon Id=@($"{Id}-anchor") Value="@(new Icons.Regular.Size12.Info())" /> + <FluentTooltip Id=@($"{Id}-tooltip") + Anchor=@($"{Id}-anchor") + Position="TooltipPosition.End" + UseTooltipService="false" + MaxWidth="250px" + Style="line-break:anywhere"> + @TooltipText + </FluentTooltip> + </label> + + <FluentStack Id=@($"{Id}-content") + Orientation="Orientation.Horizontal" + Style="column-gap:0px"> + + <FluentSlider Class="parameter-slider" + Min="@Min" Max="@Max" Step="@Step" + @bind-Value=Value @bind-Value:after=AfterSliderChange /> + + <FluentTextField Class="parameter-textfield" + @bind-Value=textFieldValue @bind-Value:after=AfterTextFieldChange /> </FluentStack> @if (!hasNoError) { - <FluentCard Style="padding:10px;width:95%;margin:0 auto;border-color:crimson;background-color:lightcoral;color:black"> + <FluentCard Class="parameter-error"> @errorText </FluentCard> } @@ -37,8 +54,11 @@ [Parameter] public EventCallback<TValue> ValueChanged { get; set; } - [Parameter] - public EventCallback OnChangeEvent { get; set; } + [Parameter, EditorRequired] + public string LabelText { get; set; } = string.Empty; + + [Parameter, EditorRequired] + public string TooltipText { get; set; } = string.Empty; public string? textFieldValue { get; set; } @@ -47,9 +67,10 @@ protected override void OnInitialized() { - base.OnInitialized(); textFieldValue = Value!.ToString(); errorText = $"Only numbers between {Min} and {Max} are permitted"; + + base.OnInitialized(); } private async Task AfterSliderChange() @@ -58,7 +79,6 @@ textFieldValue = Value!.ToString(); await ValueChanged.InvokeAsync(Value); - await OnChangeEvent.InvokeAsync(); } private async Task AfterTextFieldChange() @@ -73,6 +93,5 @@ this.Value = parsed; await ValueChanged.InvokeAsync(Value); - await OnChangeEvent.InvokeAsync(); } } diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css new file mode 100644 index 00000000..9f15a73b --- /dev/null +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css @@ -0,0 +1,26 @@ +::deep .parameter-label { + display: inline-block; + padding-left: 5px; + font-weight: bold; + font-size: 8px; +} + +::deep .parameter-slider { + width: 88%; + padding-top: 15px; +} + +::deep .parameter-textfield { + width: 12%; + font-size: 9px; + padding-right: 5px; +} + +::deep .parameter-error { + padding: 10px; + width: 95%; + margin: 5px auto; + border-color: crimson; + background-color: lightcoral; + color: black +} diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index 58cdfa06..4ea33346 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -1,73 +1,58 @@ @using System.Linq <div id="@Id"> + <ParameterSliderComponent Id="slider-pastmessages" + Class="label-with-tooltip" + LabelText="Past messages included" + TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." + Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue /> @* Past Messages Slider *@ - <LabelWithTooltip Id="slider-past-messages" - Class="label-with-tooltip" - LabelText="Past messages included" - TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." /> - - <SliderWithTextfield Class="slider-with-text" Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue /> + <ParameterSliderComponent Id="slider-past-messages" + Class="label-with-tooltip" + LabelText="Past messages included" + TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." + Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue /> @* Max Response Slider *@ - <LabelWithTooltip Id="slider-max-response" - Class="label-with-tooltip" - LabelText="Max response" - TooltipText="Set a limit on the number of tokens per model response. The API supports a maximum of MaxTokensPlaceholderDoNotTranslate tokens shared between the prompt (including system message, examples, message history, and user query) and the model's response. One token is roughly 4 characters for typical English text." /> - - <SliderWithTextfield Class="slider-with-text" Min="1" Max="16000" Step="1" @bind-Value=@maxResponseValue /> + <ParameterSliderComponent Id="slider-max-response" + Class="label-with-tooltip" + LabelText="Max response" + TooltipText="Set a limit on the number of tokens per model response. The API supports a maximum of MaxTokensPlaceholderDoNotTranslate tokens shared between the prompt (including system message, examples, message history, and user query) and the model's response. One token is roughly 4 characters for typical English text." + Min="1" Max="16000" Step="1" @bind-Value=@maxResponseValue /> @* Temperature Slider *@ - <LabelWithTooltip Id="slider-temperature" - Class="label-with-tooltip" - LabelText="Temperature" - TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." /> - - <SliderWithTextfield Class="slider-with-text" Min="0" Max="1" Step="0.01" @bind-Value=@temperatureValue /> + <ParameterSliderComponent Id="slider-temperature" + Class="label-with-tooltip" + LabelText="Temperature" + TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." + Min="0" Max="1" Step="0.01" @bind-Value=@temperatureValue /> @* Top P Slider *@ - <LabelWithTooltip Id="slider-top-p" - Class="label-with-tooltip" - LabelText="Top P" - TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." /> - - <SliderWithTextfield Class="slider-with-text" Min="0" Max="1" Step="0.01" @bind-Value=@topPValue /> + <ParameterSliderComponent Id="slider-top-p" + Class="label-with-tooltip" + LabelText="Top P" + TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." + Min="0" Max="1" Step="0.01" @bind-Value=@topPValue /> @* Stop Sequence Auto Complete *@ - <LabelWithTooltip Id="complete-stop-sequence" - Class="label-with-tooltip" - LabelText="Stop sequence" - TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." /> - - <FluentAutocomplete TOption="string" Multiple="true" AutoComplete="false" - ShowOverlayOnEmptyResults="false" - SelectValueOnTab="true" - MaximumOptionsSearch="1" - @bind-SelectedOptions=stopSequenceValue - OnOptionsSearch=OnSearchAsync - Style="width:95%;padding:5px 0px;margin: 0 auto"> - <OptionTemplate> - <FluentLabel>Create "@(context)"</FluentLabel> - </OptionTemplate> - </FluentAutocomplete> + <ParameterListComponent Id="complete-stop-sequence" + LabelText="Stop sequence" + TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." /> @* Frequency Penalty Slider *@ - <LabelWithTooltip Id="slider-frequency-penalty" - Class="label-with-tooltip" - LabelText="Frequency penalty" - TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." /> - - <SliderWithTextfield Class="slider-with-text" Min="0" Max="2" Step="0.01" @bind-Value=@frequencyPenaltyValue /> + <ParameterSliderComponent Id="slider-frequency-penalty" + Class="label-with-tooltip" + LabelText="Frequency penalty" + TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." + Min="0" Max="2" Step="0.01" @bind-Value=@frequencyPenaltyValue /> @* Presence Penalty Slider *@ - <LabelWithTooltip Id="slider-presence-penalty" - Class="label-with-tooltip" - LabelText="Presence penalty" - TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." /> - - <SliderWithTextfield Class="slider-with-text" Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue /> - + <ParameterSliderComponent Id="slider-presence-penalty" + Class="label-with-tooltip" + LabelText="Presence penalty" + TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." + Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue /> </div> @code { @@ -84,16 +69,4 @@ private IEnumerable<string> stopSequenceValue = new List<string>(); private List<string> searchTextItems = new(); - - private Task OnSearchAsync(OptionsSearchEventArgs<string> e) - { - searchTextItems.Clear(); - if (string.IsNullOrEmpty(e.Text) || stopSequenceValue.Contains(e.Text)) - return Task.CompletedTask; - - searchTextItems.Add(e.Text); - e.Items = searchTextItems; - - return Task.CompletedTask; - } } \ No newline at end of file diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css deleted file mode 100644 index acab3cf1..00000000 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css +++ /dev/null @@ -1,9 +0,0 @@ -::deep .label-with-tooltip { - padding-left: 10px; - font-weight: bold; -} - -::deep .slider-with-text { - padding-left: 5px; - padding-right: 10px; -} \ No newline at end of file From 5d2ccb4e766bf8d07ec11ce55b913f0f4eec8b8d Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Thu, 19 Sep 2024 14:49:17 +0900 Subject: [PATCH 12/27] Move label css to parent tab css file --- .../Components/UI/ParameterListComponent.razor | 2 +- .../Components/UI/ParameterSliderComponent.razor.css | 2 -- .../Components/UI/ParametersTabComponent.razor | 2 +- .../Components/UI/ParametersTabComponent.razor.css | 4 ++++ 4 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor index 184f0e71..81007a2f 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor @@ -2,7 +2,7 @@ <div id="@Id"> <label id=@($"{Id}-label") for=@($"{Id}-content") - style="display:inline-block;padding-left:5px;font-weight:bold;"> + style="display:inline-block;padding-left:5px;"> @LabelText @* Tooltip Image *@ diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css index 9f15a73b..ca3735c6 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css @@ -1,8 +1,6 @@ ::deep .parameter-label { display: inline-block; padding-left: 5px; - font-weight: bold; - font-size: 8px; } ::deep .parameter-slider { diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index 4ea33346..909e6ca4 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -1,6 +1,6 @@ @using System.Linq -<div id="@Id"> +<div id="@Id" class="parameter-tab"> <ParameterSliderComponent Id="slider-pastmessages" Class="label-with-tooltip" LabelText="Past messages included" diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css new file mode 100644 index 00000000..a00baaaf --- /dev/null +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css @@ -0,0 +1,4 @@ +.parameter-tab ::deep label { + font-size: 12px; + font-weight: bold; +} From 0b1421b03f2c7e1737a2b7b849eb625108188bde Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Thu, 19 Sep 2024 18:17:24 +0900 Subject: [PATCH 13/27] Add property for stop sequence component --- .../Components/UI/ParameterListComponent.razor | 2 ++ .../Components/UI/ParametersTabComponent.razor | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor index 81007a2f..e223a926 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor @@ -39,6 +39,8 @@ [Parameter, EditorRequired] public string TooltipText { get; set; } = string.Empty; + public IEnumerable<string> Value => stopSequenceValue; + private IEnumerable<string> stopSequenceValue = new List<string>(); private List<string> searchTextItems = new(); diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index 909e6ca4..99622270 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -38,7 +38,8 @@ @* Stop Sequence Auto Complete *@ <ParameterListComponent Id="complete-stop-sequence" LabelText="Stop sequence" - TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." /> + TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." + @ref=stopSequence /> @* Frequency Penalty Slider *@ <ParameterSliderComponent Id="slider-frequency-penalty" @@ -67,6 +68,5 @@ private double frequencyPenaltyValue = 0; private double presencePenaltyValue = 0; - private IEnumerable<string> stopSequenceValue = new List<string>(); - private List<string> searchTextItems = new(); + private ParameterListComponent? stopSequence; } \ No newline at end of file From 5a2136e966914d11515258ea058f8e891ecf5f90 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Fri, 20 Sep 2024 03:59:28 +0900 Subject: [PATCH 14/27] Remove test component --- .../Components/UI/ParametersTabComponent.razor | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index 99622270..4d7a6b78 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -1,12 +1,6 @@ @using System.Linq <div id="@Id" class="parameter-tab"> - <ParameterSliderComponent Id="slider-pastmessages" - Class="label-with-tooltip" - LabelText="Past messages included" - TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." - Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue /> - @* Past Messages Slider *@ <ParameterSliderComponent Id="slider-past-messages" Class="label-with-tooltip" From 7a6c819cbd415d783604681dbc0bb4ce58a31ac2 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Fri, 20 Sep 2024 21:05:11 +0900 Subject: [PATCH 15/27] Adjust component id and blazor namespace --- ...razor => ParameterMultiselectComponent.razor} | 4 +++- .../Components/UI/ParameterSliderComponent.razor | 8 ++++---- .../UI/ParameterSliderComponent.razor.css | 8 ++++---- .../Components/UI/ParametersTabComponent.razor | 16 +++++----------- 4 files changed, 16 insertions(+), 20 deletions(-) rename src/AzureOpenAIProxy.PlaygroundApp/Components/UI/{ParameterListComponent.razor => ParameterMultiselectComponent.razor} (92%) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor similarity index 92% rename from src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor rename to src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor index e223a926..e1bb3165 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterListComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor @@ -2,6 +2,7 @@ <div id="@Id"> <label id=@($"{Id}-label") for=@($"{Id}-content") + class="parameter-child-label" style="display:inline-block;padding-left:5px;"> @LabelText @@ -18,7 +19,8 @@ </label> <div id=@($"{Id}-content")> - <FluentAutocomplete TOption="string" Multiple="true" AutoComplete="false" + <FluentAutocomplete Id=@($"{Id}-textfield") + TOption="string" Multiple="true" AutoComplete="false" ShowOverlayOnEmptyResults="false" SelectValueOnTab="true" MaximumOptionsSearch="1" diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor index 01f3c052..b271c6ce 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor @@ -2,7 +2,7 @@ @typeparam TValue where TValue : System.Numerics.INumber<TValue> <div id="@Id"> - <label id=@($"{Id}-label") class="parameter-label" for=@($"{Id}-content")> + <label id=@($"{Id}-label") class="parameter-component-label" for=@($"{Id}-content")> @LabelText @* Tooltip Image *@ @@ -21,18 +21,18 @@ Orientation="Orientation.Horizontal" Style="column-gap:0px"> - <FluentSlider Class="parameter-slider" + <FluentSlider Id=@($"{Id}-slider") Class="parameter-component-slider" Min="@Min" Max="@Max" Step="@Step" @bind-Value=Value @bind-Value:after=AfterSliderChange /> - <FluentTextField Class="parameter-textfield" + <FluentTextField Id=@($"{Id}-textfield") Class="parameter-component-textfield" @bind-Value=textFieldValue @bind-Value:after=AfterTextFieldChange /> </FluentStack> @if (!hasNoError) { - <FluentCard Class="parameter-error"> + <FluentCard Class="parameter-component-error"> @errorText </FluentCard> } diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css index ca3735c6..16b71e1c 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css @@ -1,20 +1,20 @@ -::deep .parameter-label { +::deep .parameter-component-label { display: inline-block; padding-left: 5px; } -::deep .parameter-slider { +::deep .parameter-component-slider { width: 88%; padding-top: 15px; } -::deep .parameter-textfield { +::deep .parameter-component-textfield { width: 12%; font-size: 9px; padding-right: 5px; } -::deep .parameter-error { +::deep .parameter-component-error { padding: 10px; width: 95%; margin: 5px auto; diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index 4d7a6b78..7de6820c 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -3,48 +3,42 @@ <div id="@Id" class="parameter-tab"> @* Past Messages Slider *@ <ParameterSliderComponent Id="slider-past-messages" - Class="label-with-tooltip" LabelText="Past messages included" TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue /> @* Max Response Slider *@ <ParameterSliderComponent Id="slider-max-response" - Class="label-with-tooltip" LabelText="Max response" TooltipText="Set a limit on the number of tokens per model response. The API supports a maximum of MaxTokensPlaceholderDoNotTranslate tokens shared between the prompt (including system message, examples, message history, and user query) and the model's response. One token is roughly 4 characters for typical English text." Min="1" Max="16000" Step="1" @bind-Value=@maxResponseValue /> @* Temperature Slider *@ <ParameterSliderComponent Id="slider-temperature" - Class="label-with-tooltip" LabelText="Temperature" TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." Min="0" Max="1" Step="0.01" @bind-Value=@temperatureValue /> @* Top P Slider *@ <ParameterSliderComponent Id="slider-top-p" - Class="label-with-tooltip" LabelText="Top P" TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." Min="0" Max="1" Step="0.01" @bind-Value=@topPValue /> @* Stop Sequence Auto Complete *@ - <ParameterListComponent Id="complete-stop-sequence" - LabelText="Stop sequence" - TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." - @ref=stopSequence /> + <ParameterMultiselectComponent Id="multiselect-stop-sequence" + LabelText="Stop sequence" + TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." + @ref=stopSequence /> @* Frequency Penalty Slider *@ <ParameterSliderComponent Id="slider-frequency-penalty" - Class="label-with-tooltip" LabelText="Frequency penalty" TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." Min="0" Max="2" Step="0.01" @bind-Value=@frequencyPenaltyValue /> @* Presence Penalty Slider *@ <ParameterSliderComponent Id="slider-presence-penalty" - Class="label-with-tooltip" LabelText="Presence penalty" TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue /> @@ -62,5 +56,5 @@ private double frequencyPenaltyValue = 0; private double presencePenaltyValue = 0; - private ParameterListComponent? stopSequence; + private ParameterMultiselectComponent? stopSequence; } \ No newline at end of file From a7dc393da099f799738fa028a87751b5c11b7bde Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Fri, 20 Sep 2024 21:06:19 +0900 Subject: [PATCH 16/27] Add parameter tab component visible test --- .../Pages/PlaygroundPageConfigWindowTests.cs | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs index 2b4a100a..7c29fccd 100644 --- a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs +++ b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs @@ -368,4 +368,64 @@ string expectedValue isApplyButtonEnabled.Should().NotBeNull(); isResetButtonEnabled.Should().NotBeNull(); } + + [TestCase("slider-past-messages", "Past messages included")] + [TestCase("slider-max-response", "Max response")] + [TestCase("slider-temperature", "Temperature")] + [TestCase("slider-top-p", "Top P")] + [TestCase("slider-frequency-penalty", "Frequency penalty")] + [TestCase("slider-presence-penalty", "Presence penalty")] + public async Task Given_ParameterTab_When_Updated_Then_Parameter_Slider_Should_Be_Visible(string id, string label) + { + // Arrange + var parameterTab = Page.Locator("div.config-grid") + .Locator("fluent-tabs#config-tabs") + .Locator("fluent-tab#parameters-tab"); + + await parameterTab.ClickAsync(); + + var component = Page.Locator("div.config-grid") + .Locator("fluent-tabs#config-tabs") + .Locator("fluent-tab-panel#parameters-tab-panel") + .Locator($"div#{id}"); + + var labelComponent = component.Locator($"label[for='{id}-content']"); + + // Act + var labelText = await labelComponent.TextContentAsync(); + var slider = component.Locator($"fluent-slider#{id}-slider"); + var textfield = component.Locator($"fluent-text-field#{id}-textfield"); + + // Assert + labelText.Should().StartWith(label); + await Expect(slider).ToBeVisibleAsync(); + await Expect(textfield).ToBeVisibleAsync(); + } + + [Test] + [TestCase("multiselect-stop-sequence", "Stop sequence")] + public async Task Given_ParameterTab_When_Updated_Then_Parameter_MultiSelect_Should_Be_Visible(string id, string label) + { + // Arrange + var parameterTab = Page.Locator("div.config-grid") + .Locator("fluent-tabs#config-tabs") + .Locator("fluent-tab#parameters-tab"); + + await parameterTab.ClickAsync(); + + var component = Page.Locator("div.config-grid") + .Locator("fluent-tabs#config-tabs") + .Locator("fluent-tab-panel#parameters-tab-panel") + .Locator($"div#{id}"); + + var labelComponent = component.Locator($"label[for='{id}-content']"); + + // Act + var labelText = await labelComponent.TextContentAsync(); + var multiselect = component.Locator($"fluent-text-field#{id}-textfield"); + + // Assert + labelText.Should().StartWith(label); + await Expect(multiselect).ToBeVisibleAsync(); + } } From 25c4692fb222b7d74b7b41ae0272dfe183bdd5f7 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Fri, 20 Sep 2024 21:13:47 +0900 Subject: [PATCH 17/27] Resolve merge comflict --- .../Components/Pages/Playground.razor | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor index 2425fb7c..f402c62c 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor @@ -7,12 +7,11 @@ <FluentHeader Style="padding-top: 5px;"><h1>Azure OpenAI Proxy Playground</h1></FluentHeader> <FluentGrid Spacing="0" AdaptiveRendering="true" Justify="JustifyContent.FlexStart"> - <FluentGridItem Class="config-grid" xs="12" sm="12" md="4" lg="4" xl="4" xxl="4"> + <FluentGridItem Class="config-grid" xs="12" sm="12" md="4" lg="4" xl="4" xxl="4" Style="border:1px solid lightgrey"> <ConfigWindowComponent Id="config-window" OnSystemMessageChanged="SetSystemMessage" @rendermode="InteractiveServer" /> </FluentGridItem> - <FluentGridItem Class="chat-grid" xs="12" sm="12" md="8" lg="8" xl="8" xxl="8" - Style="border:1px solid lightgrey"> + <FluentGridItem Class="chat-grid" xs="12" sm="12" md="8" lg="8" xl="8" xxl="8" Style="border:1px solid lightgrey"> <ChatWindowComponent Id="chat-window" @rendermode="InteractiveServer" /> </FluentGridItem> </FluentGrid> From 054c16bffc76c346145d5c4234ecb14566a08184 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Wed, 25 Sep 2024 16:58:48 +0900 Subject: [PATCH 18/27] Change component name and id --- ...nt.razor => ParameterRangeComponent.razor} | 0 ....css => ParameterRangeComponent.razor.css} | 0 .../UI/ParametersTabComponent.razor | 28 ++++++------ .../Pages/PlaygroundPageConfigWindowTests.cs | 44 ++++++++----------- 4 files changed, 33 insertions(+), 39 deletions(-) rename src/AzureOpenAIProxy.PlaygroundApp/Components/UI/{ParameterSliderComponent.razor => ParameterRangeComponent.razor} (100%) rename src/AzureOpenAIProxy.PlaygroundApp/Components/UI/{ParameterSliderComponent.razor.css => ParameterRangeComponent.razor.css} (100%) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor similarity index 100% rename from src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor rename to src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor.css similarity index 100% rename from src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterSliderComponent.razor.css rename to src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor.css diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index 7de6820c..93f3cd1f 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -1,44 +1,44 @@ @using System.Linq <div id="@Id" class="parameter-tab"> - @* Past Messages Slider *@ - <ParameterSliderComponent Id="slider-past-messages" + @* Past Messages Range *@ + <ParameterRangeComponent Id="range-past-messages" LabelText="Past messages included" TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue /> - @* Max Response Slider *@ - <ParameterSliderComponent Id="slider-max-response" + @* Max Response Range *@ + <ParameterRangeComponent Id="range-max-response" LabelText="Max response" TooltipText="Set a limit on the number of tokens per model response. The API supports a maximum of MaxTokensPlaceholderDoNotTranslate tokens shared between the prompt (including system message, examples, message history, and user query) and the model's response. One token is roughly 4 characters for typical English text." Min="1" Max="16000" Step="1" @bind-Value=@maxResponseValue /> - @* Temperature Slider *@ - <ParameterSliderComponent Id="slider-temperature" + @* Temperature Range *@ + <ParameterRangeComponent Id="range-temperature" LabelText="Temperature" TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." Min="0" Max="1" Step="0.01" @bind-Value=@temperatureValue /> - @* Top P Slider *@ - <ParameterSliderComponent Id="slider-top-p" + @* Top P Range *@ + <ParameterRangeComponent Id="range-top-p" LabelText="Top P" TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." Min="0" Max="1" Step="0.01" @bind-Value=@topPValue /> - @* Stop Sequence Auto Complete *@ - <ParameterMultiselectComponent Id="multiselect-stop-sequence" + @* Stop Sequence Multi Select *@ + <ParameterMultiselectComponent Id="select-stop-sequence" LabelText="Stop sequence" TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." @ref=stopSequence /> - @* Frequency Penalty Slider *@ - <ParameterSliderComponent Id="slider-frequency-penalty" + @* Frequency Penalty Range *@ + <ParameterRangeComponent Id="range-frequency-penalty" LabelText="Frequency penalty" TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." Min="0" Max="2" Step="0.01" @bind-Value=@frequencyPenaltyValue /> - @* Presence Penalty Slider *@ - <ParameterSliderComponent Id="slider-presence-penalty" + @* Presence Penalty Range *@ + <ParameterRangeComponent Id="range-presence-penalty" LabelText="Presence penalty" TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue /> diff --git a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs index 7c29fccd..8a618eca 100644 --- a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs +++ b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs @@ -358,7 +358,7 @@ string expectedValue await applyButton.ClickAsync(new() { Delay = 500 }); await resetButton.ClickAsync(new() { Delay = 500 }); await Task.Delay(1000); - + var actualValue = await systemMessageTextArea.GetAttributeAsync("value"); var isApplyButtonEnabled = await applyButton.GetAttributeAsync("disabled"); var isResetButtonEnabled = await resetButton.GetAttributeAsync("disabled"); @@ -368,27 +368,24 @@ string expectedValue isApplyButtonEnabled.Should().NotBeNull(); isResetButtonEnabled.Should().NotBeNull(); } - - [TestCase("slider-past-messages", "Past messages included")] - [TestCase("slider-max-response", "Max response")] - [TestCase("slider-temperature", "Temperature")] - [TestCase("slider-top-p", "Top P")] - [TestCase("slider-frequency-penalty", "Frequency penalty")] - [TestCase("slider-presence-penalty", "Presence penalty")] + + [TestCase("range-past-messages", "Past messages included")] + [TestCase("range-max-response", "Max response")] + [TestCase("range-temperature", "Temperature")] + [TestCase("range-top-p", "Top P")] + [TestCase("range-frequency-penalty", "Frequency penalty")] + [TestCase("range-presence-penalty", "Presence penalty")] public async Task Given_ParameterTab_When_Updated_Then_Parameter_Slider_Should_Be_Visible(string id, string label) { // Arrange - var parameterTab = Page.Locator("div.config-grid") - .Locator("fluent-tabs#config-tabs") - .Locator("fluent-tab#parameters-tab"); + var configTab = Page.Locator("div.config-grid") + .Locator("fluent-tabs#config-tabs"); + var parameterTab = configTab.Locator("fluent-tab#parameters-tab"); await parameterTab.ClickAsync(); - var component = Page.Locator("div.config-grid") - .Locator("fluent-tabs#config-tabs") - .Locator("fluent-tab-panel#parameters-tab-panel") - .Locator($"div#{id}"); - + var component = configTab.Locator("fluent-tab-panel#parameters-tab-panel") + .Locator($"div#{id}"); var labelComponent = component.Locator($"label[for='{id}-content']"); // Act @@ -403,21 +400,18 @@ public async Task Given_ParameterTab_When_Updated_Then_Parameter_Slider_Should_B } [Test] - [TestCase("multiselect-stop-sequence", "Stop sequence")] + [TestCase("select-stop-sequence", "Stop sequence")] public async Task Given_ParameterTab_When_Updated_Then_Parameter_MultiSelect_Should_Be_Visible(string id, string label) { // Arrange - var parameterTab = Page.Locator("div.config-grid") - .Locator("fluent-tabs#config-tabs") - .Locator("fluent-tab#parameters-tab"); + var configTab = Page.Locator("div.config-grid") + .Locator("fluent-tabs#config-tabs"); + var parameterTab = configTab.Locator("fluent-tab#parameters-tab"); await parameterTab.ClickAsync(); - var component = Page.Locator("div.config-grid") - .Locator("fluent-tabs#config-tabs") - .Locator("fluent-tab-panel#parameters-tab-panel") - .Locator($"div#{id}"); - + var component = configTab.Locator("fluent-tab-panel#parameters-tab-panel") + .Locator($"div#{id}"); var labelComponent = component.Locator($"label[for='{id}-content']"); // Act From 4736fccafe65bc9c09db2b8483904d0c145ce7f0 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Sat, 5 Oct 2024 20:06:25 +0900 Subject: [PATCH 19/27] Remove no usage attribute in component --- .../Components/UI/ParameterMultiselectComponent.razor | 7 ++++--- .../Components/UI/ParameterRangeComponent.razor | 10 ++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor index e1bb3165..b97c0283 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor @@ -1,6 +1,4 @@ -@inherits FluentComponentBase - -<div id="@Id"> +<div id="@Id"> <label id=@($"{Id}-label") for=@($"{Id}-content") class="parameter-child-label" style="display:inline-block;padding-left:5px;"> @@ -41,6 +39,9 @@ [Parameter, EditorRequired] public string TooltipText { get; set; } = string.Empty; + [Parameter] + public string? Id { get; set; } + public IEnumerable<string> Value => stopSequenceValue; private IEnumerable<string> stopSequenceValue = new List<string>(); diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor index b271c6ce..9c773fa9 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor @@ -1,5 +1,4 @@ -@inherits FluentComponentBase -@typeparam TValue where TValue : System.Numerics.INumber<TValue> +@typeparam TValue where TValue : System.Numerics.INumber<TValue> <div id="@Id"> <label id=@($"{Id}-label") class="parameter-component-label" for=@($"{Id}-content")> @@ -32,9 +31,9 @@ @if (!hasNoError) { - <FluentCard Class="parameter-component-error"> + <FluentCard Class="parameter-component-error"> @errorText - </FluentCard> + </FluentCard> } </div> @@ -51,6 +50,9 @@ [Parameter] public TValue? Value { get; set; } + [Parameter] + public string? Id { get; set; } + [Parameter] public EventCallback<TValue> ValueChanged { get; set; } From dde0946bd252146afe06ee4f15b9519338cd6112 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Sun, 6 Oct 2024 06:18:58 +0900 Subject: [PATCH 20/27] Add fluent slider range test --- .../Pages/PlaygroundPageConfigWindowTests.cs | 51 ++++++++++++++++--- .../Pages/PlaywrightPageExtensions.cs | 14 +++++ 2 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaywrightPageExtensions.cs diff --git a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs index 8a618eca..8f8cc58c 100644 --- a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs +++ b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs @@ -380,9 +380,8 @@ public async Task Given_ParameterTab_When_Updated_Then_Parameter_Slider_Should_B // Arrange var configTab = Page.Locator("div.config-grid") .Locator("fluent-tabs#config-tabs"); - - var parameterTab = configTab.Locator("fluent-tab#parameters-tab"); - await parameterTab.ClickAsync(); + await configTab.Locator("fluent-tab#parameters-tab") + .ClickAsync(); var component = configTab.Locator("fluent-tab-panel#parameters-tab-panel") .Locator($"div#{id}"); @@ -406,9 +405,8 @@ public async Task Given_ParameterTab_When_Updated_Then_Parameter_MultiSelect_Sho // Arrange var configTab = Page.Locator("div.config-grid") .Locator("fluent-tabs#config-tabs"); - - var parameterTab = configTab.Locator("fluent-tab#parameters-tab"); - await parameterTab.ClickAsync(); + await configTab.Locator("fluent-tab#parameters-tab") + .ClickAsync(); var component = configTab.Locator("fluent-tab-panel#parameters-tab-panel") .Locator($"div#{id}"); @@ -422,4 +420,43 @@ public async Task Given_ParameterTab_When_Updated_Then_Parameter_MultiSelect_Sho labelText.Should().StartWith(label); await Expect(multiselect).ToBeVisibleAsync(); } -} + + [Test] + [TestCase("range-past-messages", 1, 20, 10)] + [TestCase("range-max-response", 1, 16000, 800)] + [TestCase("range-temperature", 0, 1, 0.7)] + [TestCase("range-top-p", 0, 1, 0.95)] + [TestCase("range-frequency-penalty", 0, 2, 0)] + [TestCase("range-presence-penalty", 0, 2, 0)] + public async Task Given_ParameterTab_When_Updated_Then_Parameter_Range_Should_Have_Correct_Range(string id, decimal min, decimal max, decimal start) + { + // Arrange + var configTab = Page.Locator("div.config-grid") + .Locator("fluent-tabs#config-tabs"); + await configTab.Locator("fluent-tab#parameters-tab") + .ClickAsync(); + + var content = configTab.Locator("fluent-tab-panel#parameters-tab-panel") + .Locator($"div#{id}") + .Locator($"div#{id}-content"); + + // Act + var slider = content.Locator("fluent-slider.parameter-component-slider"); + var textfield = content.Locator("fluent-text-field.parameter-component-textfield"); + + var handle = slider.Locator("div.thumb-cursor"); + var bound = await handle.BoundingBoxAsync(); + + // Assert + (await slider.GetAttributeAsync("current-value")).Should().Be(start.ToString()); + (await textfield.GetAttributeAsync("current-value")).Should().Be(start.ToString()); + + await Page.Mouse.DragToPoint(handle, 0, bound!.Y); + (await slider.GetAttributeAsync("current-value")).Should().Be(min.ToString()); + (await textfield.GetAttributeAsync("current-value")).Should().Be(min.ToString()); + + await Page.Mouse.DragToPoint(handle, float.MaxValue, bound!.Y); + (await slider.GetAttributeAsync("current-value")).Should().Be(max.ToString()); + (await textfield.GetAttributeAsync("current-value")).Should().Be(max.ToString()); + } +} \ No newline at end of file diff --git a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaywrightPageExtensions.cs b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaywrightPageExtensions.cs new file mode 100644 index 00000000..b8388b0f --- /dev/null +++ b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaywrightPageExtensions.cs @@ -0,0 +1,14 @@ +using Microsoft.Playwright; + +namespace AzureOpenAIProxy.PlaygroundApp.Tests.Pages; + +internal static class PlaywrightPageExtensions +{ + public static async Task DragToPoint(this IMouse mouse, ILocator source, float x, float y) + { + await source.HoverAsync(); + await mouse.DownAsync(); + await mouse.MoveAsync(x, y); + await mouse.UpAsync(); + } +} From 4f4909fc153625a04394b64463fe4a4e6595f92e Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Sun, 6 Oct 2024 06:38:09 +0900 Subject: [PATCH 21/27] Fix first execution error in playwright mouse move --- .../Pages/PlaygroundPageConfigWindowTests.cs | 4 ++-- .../Pages/PlaywrightPageExtensions.cs | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs index 8f8cc58c..b9271023 100644 --- a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs +++ b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs @@ -451,11 +451,11 @@ await configTab.Locator("fluent-tab#parameters-tab") (await slider.GetAttributeAsync("current-value")).Should().Be(start.ToString()); (await textfield.GetAttributeAsync("current-value")).Should().Be(start.ToString()); - await Page.Mouse.DragToPoint(handle, 0, bound!.Y); + await Page.Mouse.DragElementToPoint(handle, 0, bound!.Y); (await slider.GetAttributeAsync("current-value")).Should().Be(min.ToString()); (await textfield.GetAttributeAsync("current-value")).Should().Be(min.ToString()); - await Page.Mouse.DragToPoint(handle, float.MaxValue, bound!.Y); + await Page.Mouse.DragElementToPoint(handle, float.MaxValue, bound!.Y); (await slider.GetAttributeAsync("current-value")).Should().Be(max.ToString()); (await textfield.GetAttributeAsync("current-value")).Should().Be(max.ToString()); } diff --git a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaywrightPageExtensions.cs b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaywrightPageExtensions.cs index b8388b0f..66971155 100644 --- a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaywrightPageExtensions.cs +++ b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaywrightPageExtensions.cs @@ -4,11 +4,15 @@ namespace AzureOpenAIProxy.PlaygroundApp.Tests.Pages; internal static class PlaywrightPageExtensions { - public static async Task DragToPoint(this IMouse mouse, ILocator source, float x, float y) + public static async Task DragElementToPoint(this IMouse mouse, ILocator source, float x, float y) { await source.HoverAsync(); await mouse.DownAsync(); + + // Double execution for reliable mouse move https://playwright.dev/docs/input + await mouse.MoveAsync(x, y); await mouse.MoveAsync(x, y); + await mouse.UpAsync(); } -} +} \ No newline at end of file From fb87a63ebcc73cf5a296bd7e59281eac62972558 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Sun, 6 Oct 2024 07:46:46 +0900 Subject: [PATCH 22/27] Edit indent --- .../UI/ParameterRangeComponent.razor | 4 +-- .../UI/ParametersTabComponent.razor | 36 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor index 9c773fa9..adea9d2f 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor @@ -31,9 +31,9 @@ @if (!hasNoError) { - <FluentCard Class="parameter-component-error"> + <FluentCard Class="parameter-component-error"> @errorText - </FluentCard> + </FluentCard> } </div> diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index 93f3cd1f..7e6e5d51 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -3,27 +3,27 @@ <div id="@Id" class="parameter-tab"> @* Past Messages Range *@ <ParameterRangeComponent Id="range-past-messages" - LabelText="Past messages included" - TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." - Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue /> + LabelText="Past messages included" + TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." + Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue /> @* Max Response Range *@ <ParameterRangeComponent Id="range-max-response" - LabelText="Max response" - TooltipText="Set a limit on the number of tokens per model response. The API supports a maximum of MaxTokensPlaceholderDoNotTranslate tokens shared between the prompt (including system message, examples, message history, and user query) and the model's response. One token is roughly 4 characters for typical English text." - Min="1" Max="16000" Step="1" @bind-Value=@maxResponseValue /> + LabelText="Max response" + TooltipText="Set a limit on the number of tokens per model response. The API supports a maximum of MaxTokensPlaceholderDoNotTranslate tokens shared between the prompt (including system message, examples, message history, and user query) and the model's response. One token is roughly 4 characters for typical English text." + Min="1" Max="16000" Step="1" @bind-Value=@maxResponseValue /> @* Temperature Range *@ <ParameterRangeComponent Id="range-temperature" - LabelText="Temperature" - TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." - Min="0" Max="1" Step="0.01" @bind-Value=@temperatureValue /> + LabelText="Temperature" + TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." + Min="0" Max="1" Step="0.01" @bind-Value=@temperatureValue /> @* Top P Range *@ <ParameterRangeComponent Id="range-top-p" - LabelText="Top P" - TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." - Min="0" Max="1" Step="0.01" @bind-Value=@topPValue /> + LabelText="Top P" + TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." + Min="0" Max="1" Step="0.01" @bind-Value=@topPValue /> @* Stop Sequence Multi Select *@ <ParameterMultiselectComponent Id="select-stop-sequence" @@ -33,15 +33,15 @@ @* Frequency Penalty Range *@ <ParameterRangeComponent Id="range-frequency-penalty" - LabelText="Frequency penalty" - TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." - Min="0" Max="2" Step="0.01" @bind-Value=@frequencyPenaltyValue /> + LabelText="Frequency penalty" + TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." + Min="0" Max="2" Step="0.01" @bind-Value=@frequencyPenaltyValue /> @* Presence Penalty Range *@ <ParameterRangeComponent Id="range-presence-penalty" - LabelText="Presence penalty" - TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." - Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue /> + LabelText="Presence penalty" + TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." + Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue /> </div> @code { From 419f58a517f285a1f259ee68307eee3e8f920508 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Wed, 9 Oct 2024 15:38:54 +0900 Subject: [PATCH 23/27] Update multiselect OnSearch callback --- .../UI/ParameterMultiselectComponent.razor | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor index b97c0283..952bf0a3 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor @@ -23,7 +23,7 @@ SelectValueOnTab="true" MaximumOptionsSearch="1" @bind-SelectedOptions=stopSequenceValue - OnOptionsSearch=OnSearchAsync + OnOptionsSearch=OnSearch Style="width:95%;padding:5px 0px;margin: 0 auto"> <OptionTemplate> <FluentLabel>Create "@(context)"</FluentLabel> @@ -47,15 +47,17 @@ private IEnumerable<string> stopSequenceValue = new List<string>(); private List<string> searchTextItems = new(); - private Task OnSearchAsync(OptionsSearchEventArgs<string> e) + private void OnSearch(OptionsSearchEventArgs<string> e) { searchTextItems.Clear(); - if (string.IsNullOrEmpty(e.Text) || stopSequenceValue.Contains(e.Text)) - return Task.CompletedTask; - searchTextItems.Add(e.Text); - e.Items = searchTextItems; + var input = e.Text.Trim(); + if (string.IsNullOrWhiteSpace(input) || stopSequenceValue.Contains(input)) + { + return; + } - return Task.CompletedTask; + searchTextItems.Add(input); + e.Items = searchTextItems; } } From fbaaefc3e6a139f7464064582933f3631f93ce2d Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Wed, 9 Oct 2024 16:02:59 +0900 Subject: [PATCH 24/27] Change parameter tab div container to fluent layout --- .../Components/UI/ParametersTabComponent.razor | 4 ++-- .../Components/UI/ParametersTabComponent.razor.css | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) delete mode 100644 src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index 7e6e5d51..60ee1353 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -1,6 +1,6 @@ @using System.Linq -<div id="@Id" class="parameter-tab"> +<FluentLayout Id="@Id" Style="font-size:12px;font-weight:bold;"> @* Past Messages Range *@ <ParameterRangeComponent Id="range-past-messages" LabelText="Past messages included" @@ -42,7 +42,7 @@ LabelText="Presence penalty" TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue /> -</div> +</FluentLayout> @code { [Parameter] diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css deleted file mode 100644 index a00baaaf..00000000 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor.css +++ /dev/null @@ -1,4 +0,0 @@ -.parameter-tab ::deep label { - font-size: 12px; - font-weight: bold; -} From 691dbd2f6dd039af6bbf4136c2f0467950c2bf59 Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Sun, 13 Oct 2024 02:16:19 +0900 Subject: [PATCH 25/27] Fix input range generic type to float --- .../UI/ParameterRangeComponent.razor | 19 +++++++++--------- .../UI/ParametersTabComponent.razor | 20 +++++++++---------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor index adea9d2f..8bc40c84 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor @@ -1,6 +1,4 @@ -@typeparam TValue where TValue : System.Numerics.INumber<TValue> - -<div id="@Id"> +<div id="@Id"> <label id=@($"{Id}-label") class="parameter-component-label" for=@($"{Id}-content")> @LabelText @@ -21,6 +19,7 @@ Style="column-gap:0px"> <FluentSlider Id=@($"{Id}-slider") Class="parameter-component-slider" + TValue="float" Min="@Min" Max="@Max" Step="@Step" @bind-Value=Value @bind-Value:after=AfterSliderChange /> @@ -39,22 +38,22 @@ @code { [Parameter, EditorRequired] - public TValue? Min { get; set; } = default; + public float Min { get; set; } = default; [Parameter, EditorRequired] - public TValue? Max { get; set; } = default; + public float Max { get; set; } = default; [Parameter, EditorRequired] - public TValue? Step { get; set; } = default; + public float Step { get; set; } = default; [Parameter] - public TValue? Value { get; set; } + public float Value { get; set; } [Parameter] public string? Id { get; set; } [Parameter] - public EventCallback<TValue> ValueChanged { get; set; } + public EventCallback<float> ValueChanged { get; set; } [Parameter, EditorRequired] public string LabelText { get; set; } = string.Empty; @@ -85,8 +84,8 @@ private async Task AfterTextFieldChange() { - hasNoError = TValue.TryParse(textFieldValue, null, out var parsed); - if (!hasNoError || parsed == null) + hasNoError = float.TryParse(textFieldValue, null, out var parsed); + if (!hasNoError) return; hasNoError = parsed >= Min! && parsed <= Max!; diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index 60ee1353..98f96206 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -17,13 +17,13 @@ <ParameterRangeComponent Id="range-temperature" LabelText="Temperature" TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." - Min="0" Max="1" Step="0.01" @bind-Value=@temperatureValue /> + Min="0" Max="1" Step="0.01f" @bind-Value=@temperatureValue /> @* Top P Range *@ <ParameterRangeComponent Id="range-top-p" LabelText="Top P" TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." - Min="0" Max="1" Step="0.01" @bind-Value=@topPValue /> + Min="0" Max="1" Step="0.01f" @bind-Value=@topPValue /> @* Stop Sequence Multi Select *@ <ParameterMultiselectComponent Id="select-stop-sequence" @@ -35,26 +35,26 @@ <ParameterRangeComponent Id="range-frequency-penalty" LabelText="Frequency penalty" TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." - Min="0" Max="2" Step="0.01" @bind-Value=@frequencyPenaltyValue /> + Min="0" Max="2" Step="0.01f" @bind-Value=@frequencyPenaltyValue /> @* Presence Penalty Range *@ <ParameterRangeComponent Id="range-presence-penalty" LabelText="Presence penalty" TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." - Min="0" Max="2" Step="0.01" @bind-Value=@presencePenaltyValue /> + Min="0" Max="2" Step="0.01f" @bind-Value=@presencePenaltyValue /> </FluentLayout> @code { [Parameter] public string? Id { get; set; } - private int pastMessagesValue = 10; - private int maxResponseValue = 800; - private double temperatureValue = 0.7; - private double topPValue = 0.95; + private float pastMessagesValue = 10; + private float maxResponseValue = 800; + private float temperatureValue = 0.7f; + private float topPValue = 0.95f; - private double frequencyPenaltyValue = 0; - private double presencePenaltyValue = 0; + private float frequencyPenaltyValue = 0; + private float presencePenaltyValue = 0; private ParameterMultiselectComponent? stopSequence; } \ No newline at end of file From a72bad9b214fa35833f7e0301967967ce9f107ca Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Wed, 16 Oct 2024 04:58:23 +0900 Subject: [PATCH 26/27] Add ChatParameters and adjust event call --- .../UI/ParameterMultiselectComponent.razor | 23 ++++++-- .../UI/ParameterRangeComponent.razor | 27 ++++++---- .../UI/ParametersTabComponent.razor | 54 ++++++++++++++----- .../Models/ChatParameters.cs | 14 +++++ 4 files changed, 88 insertions(+), 30 deletions(-) create mode 100644 src/AzureOpenAIProxy.PlaygroundApp/Models/ChatParameters.cs diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor index 952bf0a3..daf212a6 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterMultiselectComponent.razor @@ -22,7 +22,8 @@ ShowOverlayOnEmptyResults="false" SelectValueOnTab="true" MaximumOptionsSearch="1" - @bind-SelectedOptions=stopSequenceValue + @bind-SelectedOptions=Values + @bind-SelectedOptions:after=OnChangeValues OnOptionsSearch=OnSearch Style="width:95%;padding:5px 0px;margin: 0 auto"> <OptionTemplate> @@ -33,26 +34,38 @@ </div> @code { + [Parameter] + public string? Id { get; set; } + + // Label Property [Parameter, EditorRequired] public string LabelText { get; set; } = string.Empty; [Parameter, EditorRequired] public string TooltipText { get; set; } = string.Empty; + // Bind Property [Parameter] - public string? Id { get; set; } + public IEnumerable<string>? Values { get; set; } - public IEnumerable<string> Value => stopSequenceValue; + [Parameter] + public EventCallback<IEnumerable<string>> ValuesChanged { get; set; } - private IEnumerable<string> stopSequenceValue = new List<string>(); + // Fields private List<string> searchTextItems = new(); + private async Task OnChangeValues() + { + await ValuesChanged.InvokeAsync(Values); + } + private void OnSearch(OptionsSearchEventArgs<string> e) { searchTextItems.Clear(); var input = e.Text.Trim(); - if (string.IsNullOrWhiteSpace(input) || stopSequenceValue.Contains(input)) + if (string.IsNullOrWhiteSpace(input) || + Values != null && Values.Contains(input)) { return; } diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor index 8bc40c84..c4bb6782 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParameterRangeComponent.razor @@ -37,6 +37,17 @@ </div> @code { + [Parameter] + public string? Id { get; set; } + + // Label Property + [Parameter, EditorRequired] + public string LabelText { get; set; } = string.Empty; + + [Parameter, EditorRequired] + public string TooltipText { get; set; } = string.Empty; + + // Slider Property [Parameter, EditorRequired] public float Min { get; set; } = default; @@ -46,23 +57,17 @@ [Parameter, EditorRequired] public float Step { get; set; } = default; - [Parameter] - public float Value { get; set; } + // Text Field Property + public string? textFieldValue { get; set; } + // Bind Property [Parameter] - public string? Id { get; set; } + public float Value { get; set; } [Parameter] public EventCallback<float> ValueChanged { get; set; } - [Parameter, EditorRequired] - public string LabelText { get; set; } = string.Empty; - - [Parameter, EditorRequired] - public string TooltipText { get; set; } = string.Empty; - - public string? textFieldValue { get; set; } - + // Fields private bool hasNoError = true; private string errorText = string.Empty; diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index 98f96206..1bc48f2d 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -1,60 +1,86 @@ @using System.Linq +@using PlaygroundApp.Models <FluentLayout Id="@Id" Style="font-size:12px;font-weight:bold;"> @* Past Messages Range *@ <ParameterRangeComponent Id="range-past-messages" LabelText="Past messages included" TooltipText="Select the number of past messages to include in each new API request. This helps give the model context for new user queries. Setting this number to 10 will include 5 user queries and 5 system responses." - Min="1" Max="20" Step="1" @bind-Value=@pastMessagesValue /> + Min="1" Max="20" Step="1" + @bind-Value=@(parameters.pastMessages) + @bind-Value:after=HandleParametersChanged /> @* Max Response Range *@ <ParameterRangeComponent Id="range-max-response" LabelText="Max response" TooltipText="Set a limit on the number of tokens per model response. The API supports a maximum of MaxTokensPlaceholderDoNotTranslate tokens shared between the prompt (including system message, examples, message history, and user query) and the model's response. One token is roughly 4 characters for typical English text." - Min="1" Max="16000" Step="1" @bind-Value=@maxResponseValue /> + Min="1" Max="16000" Step="1" + @bind-Value=@(parameters.maxResponse) + @bind-Value:after=HandleParametersChanged /> @* Temperature Range *@ <ParameterRangeComponent Id="range-temperature" LabelText="Temperature" TooltipText="Controls randomness. Lowering the temperature means that the model will produce more repetitive and deterministic responses. Increasing the temperature will result in more unexpected or creative responses. Try adjusting temperature or Top P but not both." - Min="0" Max="1" Step="0.01f" @bind-Value=@temperatureValue /> + Min="0" Max="1" Step="0.01f" + @bind-Value=@(parameters.temperature) + @bind-Value:after=HandleParametersChanged /> @* Top P Range *@ <ParameterRangeComponent Id="range-top-p" LabelText="Top P" TooltipText="Similar to temperature, this controls randomness but uses a different method. Lowering Top P will narrow the model’s token selection to likelier tokens. Increasing Top P will let the model choose from tokens with both high and low likelihood. Try adjusting temperature or Top P but not both." - Min="0" Max="1" Step="0.01f" @bind-Value=@topPValue /> + Min="0" Max="1" Step="0.01f" + @bind-Value=@(parameters.topP) + @bind-Value:after=HandleParametersChanged /> @* Stop Sequence Multi Select *@ <ParameterMultiselectComponent Id="select-stop-sequence" LabelText="Stop sequence" TooltipText="Make the model end its response at a desired point. The model response will end before the specified sequence, so it won't contain the stop sequence text. For ChatGPT, using <|im_end|> ensures that the model response doesn't generate a follow-up user query. You can include as many as four stop sequences." - @ref=stopSequence /> + @bind-Values=@(parameters.stopSequence) + @bind-Values:after=HandleParametersChanged /> @* Frequency Penalty Range *@ <ParameterRangeComponent Id="range-frequency-penalty" LabelText="Frequency penalty" TooltipText="Reduce the chance of repeating a token proportionally based on how often it has appeared in the text so far. This decreases the likelihood of repeating the exact same text in a response." - Min="0" Max="2" Step="0.01f" @bind-Value=@frequencyPenaltyValue /> + Min="0" Max="2" Step="0.01f" + @bind-Value=@(parameters.frequencyPenalty) + @bind-Value:after=HandleParametersChanged /> @* Presence Penalty Range *@ <ParameterRangeComponent Id="range-presence-penalty" LabelText="Presence penalty" TooltipText="Reduce the chance of repeating any token that has appeared in the text at all so far. This increases the likelihood of introducing new topics in a response." - Min="0" Max="2" Step="0.01f" @bind-Value=@presencePenaltyValue /> + Min="0" Max="2" Step="0.01f" + @bind-Value=@(parameters.presencePenalty) + @bind-Value:after=HandleParametersChanged /> </FluentLayout> @code { [Parameter] public string? Id { get; set; } - private float pastMessagesValue = 10; - private float maxResponseValue = 800; - private float temperatureValue = 0.7f; - private float topPValue = 0.95f; + [Parameter] + public EventCallback<ChatParameters> OnParametersChanged { get; set; } + + public ChatParameters parameters = new(); + + protected override void OnInitialized() + { + base.OnInitialized(); - private float frequencyPenaltyValue = 0; - private float presencePenaltyValue = 0; + parameters.pastMessages = 10; + parameters.maxResponse = 800; + parameters.temperature = 0.7f; + parameters.topP = 0.95f; + parameters.frequencyPenalty = 0; + parameters.presencePenalty = 0; + } - private ParameterMultiselectComponent? stopSequence; + public async Task HandleParametersChanged() + { + await OnParametersChanged.InvokeAsync(parameters); + } } \ No newline at end of file diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Models/ChatParameters.cs b/src/AzureOpenAIProxy.PlaygroundApp/Models/ChatParameters.cs new file mode 100644 index 00000000..ee1e6b57 --- /dev/null +++ b/src/AzureOpenAIProxy.PlaygroundApp/Models/ChatParameters.cs @@ -0,0 +1,14 @@ +namespace AzureOpenAIProxy.PlaygroundApp.Models; + +public class ChatParameters +{ + public float pastMessages; + public float maxResponse; + public float temperature; + public float topP; + + public IEnumerable<string>? stopSequence; + + public float frequencyPenalty; + public float presencePenalty; +} \ No newline at end of file From 0e4d52449a3ff05a121fd78a6e48962290ea705e Mon Sep 17 00:00:00 2001 From: juhangil <tensil94@gmail.com> Date: Sat, 19 Oct 2024 11:15:02 +0900 Subject: [PATCH 27/27] Add event bubbling to playground --- .../Components/Pages/Playground.razor | 15 ++++++++++++++- .../Components/UI/ConfigTabComponent.razor | 9 +++++++-- .../Components/UI/ConfigWindowComponent.razor | 10 ++++++++-- .../Components/UI/ParametersTabComponent.razor | 3 ++- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor index f402c62c..13b8d0ca 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor @@ -1,6 +1,8 @@ @page "/playground" @rendermode InteractiveServer +@using AzureOpenAIProxy.PlaygroundApp.Models + <PageTitle>Playground Page</PageTitle> <FluentLayout> @@ -8,7 +10,10 @@ <FluentGrid Spacing="0" AdaptiveRendering="true" Justify="JustifyContent.FlexStart"> <FluentGridItem Class="config-grid" xs="12" sm="12" md="4" lg="4" xl="4" xxl="4" Style="border:1px solid lightgrey"> - <ConfigWindowComponent Id="config-window" OnSystemMessageChanged="SetSystemMessage" @rendermode="InteractiveServer" /> + <ConfigWindowComponent Id="config-window" + OnSystemMessageChanged="SetSystemMessage" + OnChatParametersChanged="SetChatParameters" + @rendermode="InteractiveServer" /> </FluentGridItem> <FluentGridItem Class="chat-grid" xs="12" sm="12" md="8" lg="8" xl="8" xxl="8" Style="border:1px solid lightgrey"> @@ -19,6 +24,7 @@ @code { private string? systemMessage; + private ChatParameters? chatParameters; private async Task SetSystemMessage(string systemMessage) { @@ -26,4 +32,11 @@ await Task.CompletedTask; } + + private async Task SetChatParameters(ChatParameters parameters) + { + this.chatParameters = parameters; + + await Task.CompletedTask; + } } \ No newline at end of file diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigTabComponent.razor index afe64b81..69e65ef8 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigTabComponent.razor @@ -1,10 +1,12 @@ +@using AzureOpenAIProxy.PlaygroundApp.Models + <FluentStack Id="@Id" Style="width: 100%;" Orientation="Orientation.Vertical" VerticalAlignment="VerticalAlignment.Top"> <FluentTabs Id="config-tabs" Style="width: 100%;" ActiveTabId="system-message-tab" OnTabChange="ChangeTab"> <FluentTab Id="system-message-tab" Label="System message"> <SystemMessageTabComponent Id="system-message-tab-component" OnSystemMessageChanged="SetSystemMessage" /> </FluentTab> <FluentTab Id="parameters-tab" Label="Parameters"> - <ParametersTabComponent /> + <ParametersTabComponent OnParametersChanged="OnChatParametersChanged" /> </FluentTab> </FluentTabs> </FluentStack> @@ -19,6 +21,9 @@ [Parameter] public EventCallback<string> OnSystemMessageChanged { get; set; } + [Parameter] + public EventCallback<ChatParameters> OnChatParametersChanged { get; set; } + private async Task ChangeTab(FluentTab tab) { this.selectedTab = tab; @@ -29,7 +34,7 @@ private async Task SetSystemMessage(string systemMessage) { this.systemMessage = systemMessage; - + await OnSystemMessageChanged.InvokeAsync(systemMessage); } } \ No newline at end of file diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigWindowComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigWindowComponent.razor index 739e4e7c..d1155ca5 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigWindowComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigWindowComponent.razor @@ -5,7 +5,10 @@ <ApiKeyInputComponent Id="api-key" OnKeyInput="SetApiKey" @rendermode="InteractiveServer" /> <DeploymentModelListComponent Id="deployment-model-list" OnUserOptionSelected="SetDeploymentModel" @rendermode="InteractiveServer" /> <FluentDivider /> - <ConfigTabComponent id="config-tab" OnSystemMessageChanged="SetSystemMessage" @rendermode="InteractiveServer" /> + <ConfigTabComponent id="config-tab" + OnSystemMessageChanged="SetSystemMessage" + OnChatParametersChanged="OnChatParametersChanged" + @rendermode="InteractiveServer" /> </FluentStack> @code { @@ -19,6 +22,9 @@ [Parameter] public EventCallback<string> OnSystemMessageChanged { get; set; } + [Parameter] + public EventCallback<ChatParameters> OnChatParametersChanged { get; set; } + private async Task SetApiKey(string apiKey) { this.apiKey = apiKey; @@ -36,7 +42,7 @@ private async Task SetSystemMessage(string systemMessage) { this.systemMessage = systemMessage; - + await OnSystemMessageChanged.InvokeAsync(systemMessage); } } \ No newline at end of file diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor index 1bc48f2d..eb0c2876 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ParametersTabComponent.razor @@ -1,5 +1,6 @@ @using System.Linq -@using PlaygroundApp.Models + +@using AzureOpenAIProxy.PlaygroundApp.Models <FluentLayout Id="@Id" Style="font-size:12px;font-weight:bold;"> @* Past Messages Range *@