FEATURE: Examples support for personas. (#1334)
Examples simulate previous interactions with an LLM and come right after the system prompt. This helps grounding the model and producing better responses.
This commit is contained in:
@@ -34,6 +34,7 @@ const CREATE_ATTRIBUTES = [
|
||||
"allow_chat_channel_mentions",
|
||||
"allow_chat_direct_messages",
|
||||
"response_format",
|
||||
"examples",
|
||||
];
|
||||
|
||||
const SYSTEM_ATTRIBUTES = [
|
||||
@@ -61,7 +62,6 @@ const SYSTEM_ATTRIBUTES = [
|
||||
"allow_topic_mentions",
|
||||
"allow_chat_channel_mentions",
|
||||
"allow_chat_direct_messages",
|
||||
"response_format",
|
||||
];
|
||||
|
||||
export default class AiPersona extends RestModel {
|
||||
@@ -154,6 +154,7 @@ export default class AiPersona extends RestModel {
|
||||
this.populateTools(attrs);
|
||||
attrs.forced_tool_count = this.forced_tool_count || -1;
|
||||
attrs.response_format = attrs.response_format || [];
|
||||
attrs.examples = attrs.examples || [];
|
||||
|
||||
return attrs;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import AdminUser from "admin/models/admin-user";
|
||||
import GroupChooser from "select-kit/components/group-chooser";
|
||||
import AiPersonaResponseFormatEditor from "../components/modal/ai-persona-response-format-editor";
|
||||
import AiLlmSelector from "./ai-llm-selector";
|
||||
import AiPersonaCollapsableExample from "./ai-persona-example";
|
||||
import AiPersonaToolOptions from "./ai-persona-tool-options";
|
||||
import AiToolSelector from "./ai-tool-selector";
|
||||
import RagOptionsFk from "./rag-options-fk";
|
||||
@@ -230,6 +231,12 @@ export default class PersonaEditor extends Component {
|
||||
return this.allTools.filter((tool) => tools.includes(tool.id));
|
||||
}
|
||||
|
||||
@action
|
||||
addExamplesPair(form, data) {
|
||||
const newExamples = [...data.examples, ["", ""]];
|
||||
form.set("examples", newExamples);
|
||||
}
|
||||
|
||||
mapToolOptions(currentOptions, toolNames) {
|
||||
const updatedOptions = Object.assign({}, currentOptions);
|
||||
|
||||
@@ -422,6 +429,32 @@ export default class PersonaEditor extends Component {
|
||||
</form.Field>
|
||||
{{/unless}}
|
||||
|
||||
<form.Section
|
||||
@title={{i18n "discourse_ai.ai_persona.examples.title"}}
|
||||
@subtitle={{i18n "discourse_ai.ai_persona.examples.examples_help"}}
|
||||
>
|
||||
{{#unless data.system}}
|
||||
<form.Container>
|
||||
<form.Button
|
||||
@action={{fn this.addExamplesPair form data}}
|
||||
@label="discourse_ai.ai_persona.examples.new"
|
||||
class="ai-persona-editor__new_example"
|
||||
/>
|
||||
</form.Container>
|
||||
{{/unless}}
|
||||
|
||||
{{#if (gt data.examples.length 0)}}
|
||||
<form.Collection @name="examples" as |exCollection exCollectionIdx|>
|
||||
<AiPersonaCollapsableExample
|
||||
@examplesCollection={{exCollection}}
|
||||
@exampleNumber={{exCollectionIdx}}
|
||||
@system={{data.system}}
|
||||
@form={{form}}
|
||||
/>
|
||||
</form.Collection>
|
||||
{{/if}}
|
||||
</form.Section>
|
||||
|
||||
<form.Section @title={{i18n "discourse_ai.ai_persona.ai_tools"}}>
|
||||
<form.Field
|
||||
@name="tools"
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { concat } from "@ember/helper";
|
||||
import { on } from "@ember/modifier";
|
||||
import { action } from "@ember/object";
|
||||
import { eq } from "truth-helpers";
|
||||
import icon from "discourse/helpers/d-icon";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
export default class AiPersonaCollapsableExample extends Component {
|
||||
@tracked collapsed = true;
|
||||
|
||||
get caretIcon() {
|
||||
return this.collapsed ? "angle-right" : "angle-down";
|
||||
}
|
||||
|
||||
@action
|
||||
toggleExample() {
|
||||
this.collapsed = !this.collapsed;
|
||||
}
|
||||
|
||||
@action
|
||||
deletePair() {
|
||||
this.collapsed = true;
|
||||
this.args.examplesCollection.remove(this.args.exampleNumber);
|
||||
}
|
||||
|
||||
get exampleTitle() {
|
||||
return i18n("discourse_ai.ai_persona.examples.collapsable_title", {
|
||||
number: this.args.exampleNumber + 1,
|
||||
});
|
||||
}
|
||||
|
||||
<template>
|
||||
<div role="button" {{on "click" this.toggleExample}}>
|
||||
<span>{{icon this.caretIcon}}</span>
|
||||
{{this.exampleTitle}}
|
||||
</div>
|
||||
{{#unless this.collapsed}}
|
||||
<@examplesCollection.Collection as |exPair pairIdx|>
|
||||
<exPair.Field
|
||||
@title={{i18n
|
||||
(concat
|
||||
"discourse_ai.ai_persona.examples."
|
||||
(if (eq pairIdx 0) "user" "model")
|
||||
)
|
||||
}}
|
||||
@validation="required|length:1,100"
|
||||
@disabled={{@system}}
|
||||
as |field|
|
||||
>
|
||||
<field.Textarea />
|
||||
</exPair.Field>
|
||||
</@examplesCollection.Collection>
|
||||
|
||||
{{#unless @system}}
|
||||
<@form.Container>
|
||||
<@form.Button
|
||||
@action={{this.deletePair}}
|
||||
@label="discourse_ai.ai_persona.examples.remove"
|
||||
class="ai-persona-editor__delete_example btn-danger"
|
||||
/>
|
||||
</@form.Container>
|
||||
{{/unless}}
|
||||
{{/unless}}
|
||||
</template>
|
||||
}
|
||||
Reference in New Issue
Block a user