Skip to content

Commit fddab6d

Browse files
committed
Get user associated to llm_model
1 parent 05858ad commit fddab6d

38 files changed

+550
-236
lines changed

app/controllers/discourse_ai/admin/ai_llms_controller.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ def ai_llm_params
106106
:max_prompt_tokens,
107107
:url,
108108
:api_key,
109+
:bot_username,
109110
)
110111
end
111112
end

app/models/llm_model.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# frozen_string_literal: true
22

33
class LlmModel < ActiveRecord::Base
4+
belongs_to :user
5+
46
def tokenizer_class
57
tokenizer.constantize
68
end

assets/javascripts/discourse/admin/models/ai-llm.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ export default class AiLlm extends RestModel {
1111
"tokenizer",
1212
"max_prompt_tokens",
1313
"url",
14-
"api_key"
14+
"api_key",
15+
"bot_username"
1516
);
1617
}
1718

assets/javascripts/discourse/components/ai-llm-editor.gjs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,18 @@ export default class AiLlmEditor extends Component {
181181
@content={{I18n.t "discourse_ai.llms.hints.max_prompt_tokens"}}
182182
/>
183183
</div>
184+
<div class="control-group">
185+
<label>{{i18n "discourse_ai.llms.companion_bot_username"}}</label>
186+
<Input
187+
@type="text"
188+
class="ai-llm-editor-input ai-llm-editor__companion-bot-user"
189+
@value={{@model.bot_username}}
190+
/>
191+
<DTooltip
192+
@icon="question-circle"
193+
@content={{I18n.t "discourse_ai.llms.hints.companion_bot_username"}}
194+
/>
195+
</div>
184196

185197
<div class="control-group ai-llm-editor__action_panel">
186198
<DButton

config/locales/client.en.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ en:
210210
max_prompt_tokens: "Number of tokens for the prompt"
211211
url: "URL of the service hosting the model"
212212
api_key: "API Key of the service hosting the model"
213+
companion_bot_username: "Companion user's username"
213214
save: "Save"
214215
edit: "Edit"
215216
saved: "LLM Model Saved"
@@ -226,6 +227,7 @@ en:
226227
hints:
227228
max_prompt_tokens: "Max numbers of tokens for the prompt. As a rule of thumb, this should be 50% of the model's context window."
228229
name: "We include this in the API call to specify which model we'll use."
230+
companion_bot_username: "Features like the AI Bot create an user with this username for users to interact with."
229231

230232
providers:
231233
aws_bedrock: "AWS Bedrock"

config/locales/server.en.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,9 @@ en:
318318
disable_module_first: "You have to disable %{setting} first."
319319
set_llm_first: "Set %{setting} first."
320320
model_unreachable: "We couldn't get a response from this model. Check your settings first."
321+
configure_llm:
322+
one: "We couldn't find an LLM with the name %{models}. Go to the plugin's LLMs section to set it up."
323+
other: "We couldn't find configured LLMs with these names: %{models}. Go to the plugin's LLMs section to set them up."
321324
endpoints:
322325
not_configured: "%{display_name} (not configured)"
323326
configuration_hint:

config/settings.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -342,19 +342,19 @@ discourse_ai:
342342
type: group_list
343343
list_type: compact
344344
default: "3|14" # 3: @staff, 14: @trust_level_4
345-
# Adding a new bot? Make sure to create a user for it on the seed file and update translations.
346345
ai_bot_public_sharing_allowed_groups:
347346
client: false
348347
type: group_list
349348
list_type: compact
350349
default: "1|2" # 1: admins, 2: moderators
351350
allow_any: false
352351
refresh: true
353-
ai_bot_enabled_chat_bots:
352+
ai_bot_enabled_chat_bots: # TODO(roman): Make this dynamic
354353
type: list
355-
default: "gpt-3.5-turbo"
354+
default: ""
356355
client: true
357-
choices: "DiscourseAi::Configuration::LlmEnumerator.ai_bot_models"
356+
validator: "DiscourseAi::Configuration::LlmModelValidator"
357+
choices: "DiscourseAi::Configuration::LlmEnumerator.available_ai_bots"
358358
ai_bot_add_to_header:
359359
default: true
360360
client: true
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# frozen_string_literal: true
2+
3+
class AddCompanionUserToLlmModel < ActiveRecord::Migration[7.0]
4+
def change
5+
add_column :llm_models, :bot_username, :string
6+
add_column :llm_models, :user_id, :integer
7+
end
8+
end

db/post_migrate/20240523142424_custom_fields_to_track_ai_bot_users.rb

Lines changed: 0 additions & 51 deletions
This file was deleted.
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# frozen_string_literal: true
2+
3+
class SeedOpenAiModels < ActiveRecord::Migration[7.0]
4+
def up
5+
models = []
6+
7+
open_ai_api_key = fetch_setting("ai_openai_api_key")
8+
9+
if open_ai_api_key.present?
10+
models << mirror_open_ai(
11+
"GPT-3.5 Turbo",
12+
"gpt-3.5-turbo",
13+
8192,
14+
"ai_openai_gpt35_url",
15+
open_ai_api_key,
16+
"gpt3.5_bot",
17+
-111,
18+
)
19+
models << mirror_open_ai(
20+
"GPT-3.5 Turbo 16K",
21+
"gpt-3.5-turbo-16k",
22+
16_384,
23+
"ai_openai_gpt35_16k_url",
24+
open_ai_api_key,
25+
"gpt3.5_bot",
26+
-111,
27+
)
28+
models << mirror_open_ai(
29+
"GPT-4",
30+
"gpt-4",
31+
8192,
32+
"ai_openai_gpt4_url",
33+
open_ai_api_key,
34+
"gpt4_bot",
35+
-110,
36+
)
37+
models << mirror_open_ai(
38+
"GPT-4 32K",
39+
"gpt-4-32k",
40+
32_768,
41+
"ai_openai_gpt4_32k_url",
42+
open_ai_api_key,
43+
"gpt4_bot",
44+
-110,
45+
)
46+
models << mirror_open_ai(
47+
"GPT-4 Turbo",
48+
"gpt-4-turbo",
49+
131_072,
50+
"ai_openai_gpt4_turbo_url",
51+
open_ai_api_key,
52+
"gpt4t_bot",
53+
-113,
54+
)
55+
models << mirror_open_ai(
56+
"GPT-4o",
57+
"gpt-4o",
58+
131_072,
59+
"ai_openai_gpt4o_url",
60+
open_ai_api_key,
61+
"gpt4o_bot",
62+
-121,
63+
)
64+
end
65+
66+
if models.present?
67+
rows = models.compact.join(",")
68+
69+
DB.exec(<<~SQL, rows: rows) if rows.present?
70+
INSERT INTO llm_models (display_name, name, provider, tokenizer, max_prompt_tokens, url, api_key, bot_username, user_id, created_at, updated_at)
71+
VALUES :rows;
72+
SQL
73+
end
74+
end
75+
76+
def has_companion_user?(user_id)
77+
DB.query_single("SELECT id FROM users WHERE id = :user_id", user_id: user_id).first.present?
78+
end
79+
80+
def fetch_setting(name)
81+
DB.query_single(
82+
"SELECT value FROM site_settings WHERE name = :setting_name",
83+
setting_name: name,
84+
).first
85+
end
86+
87+
def mirror_open_ai(display_name, name, max_prompt_tokens, setting_name, key, bot_username, bot_id)
88+
url = fetch_setting(setting_name)
89+
90+
user_id = has_companion_user?(bot_id) ? bot_id : "NULL"
91+
92+
if url
93+
"(#{name.titleize}, #{name}, open_ai, OpenAiTokenizer, #{max_prompt_tokens}, #{url}, #{key}, #{bot_username}, #{user_id}, NOW(), NOW())"
94+
end
95+
end
96+
97+
def down
98+
raise ActiveRecord::IrreversibleMigration
99+
end
100+
end
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# frozen_string_literal: true
2+
3+
class SeedClaudeModels < ActiveRecord::Migration[7.0]
4+
def up
5+
claude_models = %w[claude-instant-1 claude-2 claude-3-haiku claude-3-sonnet claude-3-opus]
6+
7+
models = []
8+
9+
bedrock_secret_access_key = fetch_setting("ai_bedrock_secret_access_key")
10+
11+
if bedrock_secret_access_key.present?
12+
bedrock_region = fetch_setting("ai_bedrock_region")
13+
14+
claude_models.each do |cm|
15+
url =
16+
"https://bedrock-runtime.#{bedrock_region}.amazonaws.com/model/#{mapped_bedrock_model(cm)}/invoke"
17+
18+
models << "(#{display_name(cm)}, #{cm}, aws_bedrock, AnthropicTokenizer, 200000, #{url}, #{kbedrock_secret_access_key}, NOW(), NOW())"
19+
end
20+
end
21+
22+
anthropic_ai_api_key = fetch_setting("ai_anthropic_api_key")
23+
if anthropic_ai_api_key.present?
24+
claude_models.each do |cm|
25+
url = "https://api.anthropic.com/v1/messages"
26+
27+
user_id = has_companion_user?(-114) ? -114 : "NULL"
28+
29+
models << "(#{display_name(cm)}, #{cm}, anthropic, AnthropicTokenizer, 200000, #{url}, #{anthropic_ai_api_key}, mixtral_bot, #{user_id}, NOW(), NOW())"
30+
end
31+
end
32+
33+
if models.present?
34+
rows = models.compact.join(",")
35+
36+
DB.exec(<<~SQL, rows: rows) if rows.present?
37+
INSERT INTO llm_models (display_name, name, provider, tokenizer, max_prompt_tokens, url, api_key, bot_username, user_id, created_at, updated_at)
38+
VALUES :rows;
39+
SQL
40+
end
41+
end
42+
43+
def has_companion_user?(user_id)
44+
DB.query_single("SELECT id FROM users WHERE id = :user_id", user_id: user_id).first.present?
45+
end
46+
47+
def fetch_setting(name)
48+
DB.query_single(
49+
"SELECT value FROM site_settings WHERE name = :setting_name",
50+
setting_name: name,
51+
).first
52+
end
53+
54+
def claude_bot_username(model)
55+
case model
56+
when "claude-2"
57+
"claude_bot"
58+
when "claude-3-haiku"
59+
"claude_3_haiku_bot"
60+
when "claude-3-sonnet"
61+
"claude_3_sonnet_bot"
62+
when "claude-instant-1"
63+
"anthropic.claude-instant-v1"
64+
when "claude-3-opus"
65+
"claude_3_opus_bot"
66+
else
67+
"claude_instant_bot"
68+
end
69+
end
70+
71+
def claude_bot_id(model)
72+
end
73+
74+
def mapped_bedrock_model(model)
75+
case model
76+
when "claude-2"
77+
"anthropic.claude-v2:1"
78+
when "claude-3-haiku"
79+
"anthropic.claude-3-haiku-20240307-v1:0"
80+
when "claude-3-sonnet"
81+
"anthropic.claude-3-sonnet-20240229-v1:0"
82+
when "claude-instant-1"
83+
"anthropic.claude-instant-v1"
84+
when "claude-3-opus"
85+
"anthropic.claude-3-opus-20240229-v1:0"
86+
end
87+
end
88+
89+
def display_name(model)
90+
case model
91+
when "claude-2"
92+
"Claude 2"
93+
when "claude-3-haiku"
94+
"Claude 3 Haiku"
95+
when "claude-3-sonnet"
96+
"Claude 3 Sonnet"
97+
when "claude-instant-1"
98+
"Claude Instant 1"
99+
when "claude-3-opus"
100+
"Claude 3 Opus"
101+
end
102+
end
103+
104+
def down
105+
raise ActiveRecord::IrreversibleMigration
106+
end
107+
end

0 commit comments

Comments
 (0)