Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

UX: improve embeddings config styles #1085

Merged
merged 7 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions app/models/embedding_definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def presets
# indexes, so we downsample to 2000 via API.
{
preset_id: "text-embedding-3-large",
display_name: "OpenAI's text-embedding-3-large",
display_name: "text-embedding-3-large",
dimensions: 2000,
max_sequence_length: 8191,
pg_function: "<=>",
Expand All @@ -91,7 +91,7 @@ def presets
},
{
preset_id: "text-embedding-3-small",
display_name: "OpenAI's text-embedding-3-small",
display_name: "text-embedding-3-small",
dimensions: 1536,
max_sequence_length: 8191,
pg_function: "<=>",
Expand All @@ -105,7 +105,7 @@ def presets
},
{
preset_id: "text-embedding-ada-002",
display_name: "OpenAI's text-embedding-ada-002",
display_name: "text-embedding-ada-002",
dimensions: 1536,
max_sequence_length: 8191,
pg_function: "<=>",
Expand Down
124 changes: 94 additions & 30 deletions assets/javascripts/discourse/components/ai-embedding-editor.gjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { Input } from "@ember/component";
import { concat, get } from "@ember/helper";
import { Input, Textarea } from "@ember/component";
import { concat, fn, get } from "@ember/helper";
import { on } from "@ember/modifier";
import { action, computed } from "@ember/object";
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
Expand All @@ -13,6 +13,8 @@ import DButton from "discourse/components/d-button";
import icon from "discourse/helpers/d-icon";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { i18n } from "discourse-i18n";
import AdminSectionLandingItem from "admin/components/admin-section-landing-item";
import AdminSectionLandingWrapper from "admin/components/admin-section-landing-wrapper";
import ComboBox from "select-kit/components/combo-box";
import DTooltip from "float-kit/components/d-tooltip";
import not from "truth-helpers/helpers/not";
Expand Down Expand Up @@ -48,7 +50,19 @@ export default class AiEmbeddingEditor extends Component {
};

return this.args.embeddings.resultSetMeta.distance_functions.map((df) => {
return { id: df, name: t(df) };
let iconName;

if (df === "<=>") {
iconName = "discourse-spaceship-operator";
} else if (df === "<#>") {
iconName = "discourse-negative-inner-product";
}

return {
id: df,
name: t(df),
icon: iconName,
};
});
}

Expand All @@ -57,12 +71,14 @@ export default class AiEmbeddingEditor extends Component {
return {
name: preset.display_name,
id: preset.preset_id,
provider: preset.provider,
};
});

presets.pushObject({
presets.unshiftObject({
name: i18n("discourse_ai.embeddings.configure_manually"),
id: "manual",
provider: "fake",
});

return presets;
Expand Down Expand Up @@ -90,11 +106,11 @@ export default class AiEmbeddingEditor extends Component {
}

@action
configurePreset() {
configurePreset(preset) {
this.selectedPreset =
this.args.embeddings.resultSetMeta.presets.findBy(
"preset_id",
this.presetId
preset.id
) || {};

this.editingModel = this.store
Expand Down Expand Up @@ -185,35 +201,64 @@ export default class AiEmbeddingEditor extends Component {
});
}

<template>
<BackButton
@route="adminPlugins.show.discourse-ai-embeddings"
@label="discourse_ai.embeddings.back"
/>
@action
resetForm() {
this.selectedPreset = null;
this.editingModel = null;
}

<template>
<form
{{didInsert this.updateModel @model.id}}
{{didUpdate this.updateModel @model.id}}
class="form-horizontal ai-embedding-editor"
>
{{#if this.showPresets}}
<BackButton
@route="adminPlugins.show.discourse-ai-embeddings"
@label="discourse_ai.embeddings.back"
/>
<div class="control-group">
<label>{{i18n "discourse_ai.embeddings.presets"}}</label>
<ComboBox
@value={{this.presetId}}
@content={{this.presets}}
class="ai-embedding-editor__presets"
/>
<h2>{{i18n "discourse_ai.embeddings.presets"}}</h2>
<AdminSectionLandingWrapper>
{{#each this.presets as |preset|}}
<AdminSectionLandingItem
@titleLabelTranslated={{preset.name}}
@taglineLabel={{concat
"discourse_ai.embeddings.providers."
preset.provider
}}
data-preset-id={{preset.id}}
class="ai-llms-list-editor__templates-list-item"
>
<:buttons as |buttons|>
<buttons.Default
@action={{fn this.configurePreset preset}}
@icon="gear"
@label="discourse_ai.llms.preconfigured.button"
/>
</:buttons>
</AdminSectionLandingItem>

{{/each}}
</AdminSectionLandingWrapper>

</div>

<div class="control-group ai-llm-editor__action_panel">
{{else}}
{{#if this.editingModel.isNew}}
<DButton
@action={{this.configurePreset}}
@label="discourse_ai.tools.next.title"
class="ai-embedding-editor__next"
@action={{this.resetForm}}
@label="back_button"
@icon="chevron-left"
class="btn-flat back-button"
/>
</div>
{{else}}
{{else}}
<BackButton
@route="adminPlugins.show.discourse-ai-embeddings"
@label="discourse_ai.embeddings.back"
/>
{{/if}}
<div class="control-group">
<label>{{i18n "discourse_ai.embeddings.display_name"}}</label>
<Input
Expand Down Expand Up @@ -295,27 +340,38 @@ export default class AiEmbeddingEditor extends Component {
@type="checkbox"
@checked={{this.editingModel.matryoshka_dimensions}}
/>
<label>{{i18n
"discourse_ai.embeddings.matryoshka_dimensions"
}}</label>
<label>{{i18n "discourse_ai.embeddings.matryoshka_dimensions"}}
</label>
<DTooltip
@icon="circle-question"
@content={{i18n
"discourse_ai.embeddings.hints.matryoshka_dimensions"
}}
/>
</div>

<div class="control-group">
<label>{{i18n "discourse_ai.embeddings.embed_prompt"}}</label>
<Input
@type="text"
<Textarea
class="ai-embedding-editor-input ai-embedding-editor__embed_prompt"
@value={{this.editingModel.embed_prompt}}
/>
<DTooltip
@icon="circle-question"
@content={{i18n "discourse_ai.embeddings.hints.embed_prompt"}}
/>
</div>

<div class="control-group">
<label>{{i18n "discourse_ai.embeddings.search_prompt"}}</label>
<Input
@type="text"
<Textarea
class="ai-embedding-editor-input ai-embedding-editor__search_prompt"
@value={{this.editingModel.search_prompt}}
/>
<DTooltip
@icon="circle-question"
@content={{i18n "discourse_ai.embeddings.hints.search_prompt"}}
/>
</div>

<div class="control-group">
Expand All @@ -329,6 +385,10 @@ export default class AiEmbeddingEditor extends Component {
@value={{this.editingModel.max_sequence_length}}
required="true"
/>
<DTooltip
@icon="circle-question"
@content={{i18n "discourse_ai.embeddings.hints.sequence_length"}}
/>
</div>

<div class="control-group">
Expand All @@ -338,6 +398,10 @@ export default class AiEmbeddingEditor extends Component {
@content={{this.distanceFunctions}}
@class="ai-embedding-editor__distance_functions"
/>
<DTooltip
@icon="circle-question"
@content={{i18n "discourse_ai.embeddings.hints.distance_function"}}
/>
</div>

{{#each-in this.metaProviderParams as |field type|}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,47 @@
display: flex;
align-items: flex-start;
}

&__distance_functions.select-kit {
.selected-name {
.d-icon {
width: 2em;
height: 2em;
position: absolute;

+ .name {
margin-left: 2.25em;
}
}
}

.svg-icon-title {
width: 2em;
top: -0.5em;

svg {
width: 2em;
height: 2em;
}
}
}
}

.discourse-ai-embeddings {
.btn-flat.back-button {
padding-left: 0;
}

.fk-d-tooltip__icon {
margin-left: 0.25em;
color: var(--primary-medium);
}

textarea + .fk-d-tooltip__trigger {
vertical-align: top;
}

.d-icon-circle-exclamation {
color: var(--danger);
}
}
14 changes: 9 additions & 5 deletions config/locales/client.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -515,14 +515,18 @@ en:
configure_manually: "Configure manually"
edit: "Edit"
seeded_warning: "This is pre-configured on your site and cannot be edited."
tests:
tests:
title: "Run test"
running: "Running test..."
success: "Success!"
failure: "Attempting to generate an embedding resulted in: %{error}"
hints:
dimensions_warning: "Once saved, this value can't be changed."

matryoshka_dimensions: "Defines the size of nested embeddings used for hierarchical or multi-layered representation of data, similar to how nested dolls fit within each other."
embed_prompt: "Tells the LLM how to process text to create its numerical summary (embedding) for analysis or comparison."
search_prompt: "Tells the LLM how to compare a search query with existing embeddings and find the best matches."
sequence_length: "The maximum number of tokens that can be processed at once when creating embeddings or handling a query."
distance_function: "Determines how similarity between embeddings is calculated, using either cosine distance (measuring the angle between vectors) or negative inner product (measuring overlap of vector values)."
display_name: "Name"
provider: "Provider"
url: "Embeddings service URL"
Expand All @@ -536,18 +540,18 @@ en:

distance_function: "Distance function"
distance_functions:
<#>: "Negative inner product (<#>)"
<=>: "Cosine distance (<=>)"
<#>: "Negative inner product"
<=>: "Cosine distance"
providers:
hugging_face: "Hugging Face"
open_ai: "OpenAI"
google: "Google"
cloudflare: "Cloudflare"
CDCK: "CDCK"
fake: "Custom"
provider_fields:
model_name: "Model name"


semantic_search: "Topics (Semantic)"
semantic_search_loading: "Searching for more results using AI"
semantic_search_results:
Expand Down
19 changes: 8 additions & 11 deletions spec/system/embeddings/ai_embedding_definition_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@
visit "/admin/plugins/discourse-ai/ai-embeddings"

find(".ai-embeddings-list-editor__new-button").click()
select_kit = PageObjects::Components::SelectKit.new(".ai-embedding-editor__presets")
select_kit.expand
select_kit.select_row_by_value(preset)
find(".ai-embedding-editor__next").click

find("[data-preset-id='text-embedding-3-small'] button").click()

find("input.ai-embedding-editor__api-key").fill_in(with: api_key)
find(".ai-embedding-editor__save").click()

Expand All @@ -43,12 +42,10 @@
visit "/admin/plugins/discourse-ai/ai-embeddings"

find(".ai-embeddings-list-editor__new-button").click()
select_kit = PageObjects::Components::SelectKit.new(".ai-embedding-editor__presets")
select_kit.expand
select_kit.select_row_by_value("manual")
find(".ai-embedding-editor__next").click

find("input.ai-embedding-editor__display-name").fill_in(with: "OpenAI's text-embedding-3-small")
find("[data-preset-id='manual'] button").click()

find("input.ai-embedding-editor__display-name").fill_in(with: "text-embedding-3-small")

select_kit = PageObjects::Components::SelectKit.new(".ai-embedding-editor__provider")
select_kit.expand
Expand All @@ -63,8 +60,8 @@

embed_prefix = "On creation:"
search_prefix = "On search:"
find("input.ai-embedding-editor__embed_prompt").fill_in(with: embed_prefix)
find("input.ai-embedding-editor__search_prompt").fill_in(with: search_prefix)
find(".ai-embedding-editor__embed_prompt").fill_in(with: embed_prefix)
find(".ai-embedding-editor__search_prompt").fill_in(with: search_prefix)

find("input.ai-embedding-editor__dimensions").fill_in(with: 1536)
find("input.ai-embedding-editor__max_sequence_length").fill_in(with: 8191)
Expand Down
12 changes: 11 additions & 1 deletion svg-icons/icons-sprite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading