Skip to content

Commit 7211a7f

Browse files
authored
chore: Fix chat example to preserve message history (#17)
1 parent 9207b8d commit 7211a7f

3 files changed

Lines changed: 102 additions & 104 deletions

File tree

examples/chatbot/README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ This repository includes examples for `OpenAI` and `Bedrock`. Depending on your
1313
### General setup
1414

1515
1. Install the required dependencies with `bundle install` in the appropriate example directory.
16-
1. Set the environment variable `LAUNCHDARKLY_SDK_KEY` to your LaunchDarkly SDK key. If there is an existing an AI Config in your LaunchDarkly project that you want to evaluate, set `LAUNCHDARKLY_AI_CONFIG_KEY` to the flag key; otherwise, an AI Config of `sample-ai-config` will be assumed.
16+
1. [Create an AI Config](https://launchdarkly.com/docs/home/ai-configs/create) using the key specified in the examples, or copy the key of an existing AI Config in your LaunchDarkly project that you want to use.
17+
1. Update the default model (`replace-with-your-model`) in the example file.
18+
1. Set the environment variable `LAUNCHDARKLY_SDK_KEY` to your LaunchDarkly SDK key and `LAUNCHDARKLY_AI_CONFIG_KEY` to the AI Config key; otherwise, an AI Config of `sample-ai-config` will be assumed.
1719

1820
```bash
1921
export LAUNCHDARKLY_SDK_KEY="1234567890abcdef"
2022
export LAUNCHDARKLY_AI_CONFIG_KEY="sample-ai-config"
2123
```
2224

23-
1. Replace `my-default-model` with your preferred model if the application cannot connect to LaunchDarkly Services.
24-
2525
### OpenAI setup
2626

2727
1. Set the environment variable `OPENAI_API_KEY` to your OpenAI key.
@@ -39,6 +39,10 @@ This repository includes examples for `OpenAI` and `Bedrock`. Depending on your
3939
```bash
4040
export AWS_ACCESS_KEY_ID="0987654321fedcba"
4141
export AWS_SECRET_ACCESS_KEY="0987654321fedcba"
42+
43+
# or
44+
45+
export AWS_PROFILE="aws-profile-name"
4246
```
4347

4448
1. Run the program `bundle exec ruby hello_bedrock.rb`

examples/chatbot/aws-bedrock/hello_bedrock.rb

Lines changed: 48 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -10,57 +10,27 @@
1010
# Set config_key to the AI Config key you want to evaluate.
1111
ai_config_key = ENV['LAUNCHDARKLY_AI_CONFIG_KEY'] || 'sample-ai-config'
1212

13-
# Set aws_access_key_id and aws_secret_access_key for AWS credentials.
14-
aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
15-
aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
1613
region = ENV['AWS_REGION'] || 'us-east-1'
1714

1815
if sdk_key.nil? || sdk_key.empty?
1916
puts '*** Please set the LAUNCHDARKLY_SDK_KEY env first'
2017
exit 1
2118
end
2219

23-
if aws_access_key_id.nil? || aws_access_key_id.empty?
24-
puts '*** Please set the AWS_ACCESS_KEY_ID env variable first'
25-
exit 1
26-
end
27-
28-
if aws_secret_access_key.nil? || aws_secret_access_key.empty?
29-
puts '*** Please set the AWS_SECRET_ACCESS_KEY env variable first'
30-
exit 1
31-
end
32-
3320
#
3421
# Chatbot class that interacts with LaunchDarkly AI and AWS Bedrock
3522
#
3623
class BedrockChatbot
37-
attr_reader :aiclient, :ai_config_key, :bedrock_client
38-
39-
DEFAULT_VALUE = LaunchDarkly::Server::AI::AIConfig.new(
40-
enabled: true,
41-
model: LaunchDarkly::Server::AI::ModelConfig.new(name: 'my-default-model'),
42-
messages: [
43-
LaunchDarkly::Server::AI::Message.new('system',
44-
'You are a default unhelpful assistant with the persona of HAL 9000 talking with {{ldctx.name}}'),
45-
LaunchDarkly::Server::AI::Message.new('user', '{{user_question}}'),
46-
]
47-
)
48-
49-
def initialize(aiclient, ai_config_key, bedrock_client, context)
50-
@aiclient = aiclient
51-
@ai_config_key = ai_config_key
24+
attr_reader :ai_config, :bedrock_client, :messages
25+
26+
def initialize(ai_config, bedrock_client)
27+
@ai_config = ai_config
28+
@messages = ai_config.messages
5229
@bedrock_client = bedrock_client
53-
@context = context
5430
end
5531

5632
def ask_agent(question)
57-
ai_config = aiclient.config(
58-
@ai_config_key,
59-
@context,
60-
DEFAULT_VALUE,
61-
{ user_question: question }
62-
)
63-
33+
@messages << LaunchDarkly::Server::AI::Message.new('user', question)
6434
begin
6535
response = ai_config.tracker.track_bedrock_converse_metrics do
6636
@bedrock_client.converse(
@@ -70,29 +40,25 @@ def ask_agent(question)
7040
)
7141
)
7242
end
73-
[response.output.message.content[0].text, ai_config.tracker]
43+
@messages << LaunchDarkly::Server::AI::Message.new('assistant', response.output.message.content[0].text)
44+
response.output.message.content[0].text
7445
rescue StandardError => e
75-
["An error occured: #{e.message}", nil]
46+
"An error occured: #{e.message}"
7647
end
7748
end
7849

79-
def agent_was_helpful(tracker, helpful)
50+
def agent_was_helpful(helpful)
8051
kind = helpful ? :positive : :negative
81-
tracker.track_feedback(kind: kind)
52+
ai_config.tracker.track_feedback(kind: kind)
8253
end
8354

8455
def map_converse_arguments(model_id, messages)
8556
args = {
8657
model_id: model_id,
8758
}
8859

89-
mapped_messages = []
90-
user_messages = messages.select { |msg| msg.role == 'user' }
91-
mapped_messages << { role: 'user', content: user_messages.map { |msg| { text: msg.content } } } unless user_messages.empty?
92-
93-
assistant_messages = messages.select { |msg| msg.role == 'assistant' }
94-
mapped_messages << { role: 'assistant', content: assistant_messages.map { |msg| { text: msg.content } } } unless assistant_messages.empty?
95-
args[:messages] = mapped_messages unless mapped_messages.empty?
60+
chat_messages = messages.select { |msg| msg.role != 'system' }
61+
args[:messages] = chat_messages.map { |msg| { role: msg.role, content: [{ text: msg.content }] } }
9662

9763
system_messages = messages.select { |msg| msg.role == 'system' }
9864
args[:system] = system_messages.map { |msg| { text: msg.content } } unless system_messages.empty?
@@ -118,27 +84,49 @@ def map_converse_arguments(model_id, messages)
11884
})
11985

12086
bedrock_client = Aws::BedrockRuntime::Client.new(
121-
aws_access_key_id: aws_access_key_id,
122-
aws_secret_access_key: aws_secret_access_key,
12387
region: region
12488
)
125-
chatbot = BedrockChatbot.new(ai_client, ai_config_key, bedrock_client, context)
89+
90+
91+
DEFAULT_VALUE = LaunchDarkly::Server::AI::AIConfig.new(
92+
enabled: true,
93+
model: LaunchDarkly::Server::AI::ModelConfig.new(name: 'replace-with-your-model'),
94+
messages: [
95+
LaunchDarkly::Server::AI::Message.new('system',
96+
'You are the backup assistant when something prevents retrieving LaunchDarkly configured assistant. You have the persona of HAL 9000 talking with {{ldctx.name}}'),
97+
]
98+
)
99+
100+
# You can also default to disabled if you are unable to connect to LaunchDarkly services.
101+
# DEFAULT_VALUE = LaunchDarkly::Server::AI::AIConfig.new(
102+
# enabled: false
103+
# )
104+
105+
ai_config = ai_client.config(
106+
ai_config_key,
107+
context,
108+
DEFAULT_VALUE
109+
)
110+
111+
unless ai_config.enabled
112+
puts '*** AI features are disabled'
113+
exit 1
114+
end
115+
116+
chatbot = BedrockChatbot.new(ai_config, bedrock_client)
126117

127118
loop do
128-
print "Ask a question: (or type 'exit'): "
119+
print "Ask a question (or type 'exit'): "
129120
question = gets&.chomp
130121
break if question.nil? || question.strip.downcase == 'exit'
131122

132-
response, tracker = chatbot.ask_agent(question)
123+
response = chatbot.ask_agent(question)
133124
puts "AI Response: #{response}"
125+
end
134126

135-
next if tracker.nil? # If tracker is nil, skip feedback collection
136-
137-
print "Was the response helpful? [yes/no] (or type 'exit'): "
138-
feedback = gets&.chomp
139-
break if feedback.nil? || feedback.strip.downcase == 'exit'
127+
print "Was the chat helpful? [yes/no]: "
128+
feedback = gets&.chomp
140129

141-
chatbot.agent_was_helpful(tracker, feedback == 'yes')
142-
end
130+
chatbot.agent_was_helpful(feedback == 'yes') unless feedback.nil?
143131

144-
ld_client.close
132+
ld_client.close

examples/chatbot/openai/hello_openai.rb

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,52 +27,51 @@
2727
# Chatbot class that interacts with LaunchDarkly AI and OpenAI
2828
#
2929
class Chatbot
30-
attr_reader :aiclient, :ai_config_key, :openai_client, :context
31-
32-
DEFAULT_VALUE = LaunchDarkly::Server::AI::AIConfig.new(
33-
enabled: true,
34-
model: LaunchDarkly::Server::AI::ModelConfig.new(name: 'my-default-model'),
35-
messages: [
36-
LaunchDarkly::Server::AI::Message.new('system',
37-
'You are a default unhelpful assistant with the persona of HAL 9000 talking with {{ldctx.name}}'),
38-
LaunchDarkly::Server::AI::Message.new('user', '{{user_question}}'),
39-
]
40-
)
41-
42-
def initialize(aiclient, ai_config_key, openai_client, context)
43-
@aiclient = aiclient
44-
@ai_config_key = ai_config_key
30+
attr_reader :ai_config, :openai_client, :messages
31+
32+
def initialize(ai_config, openai_client)
33+
@ai_config = ai_config
34+
@messages = ai_config.messages
4535
@openai_client = openai_client
46-
@context = context
4736
end
4837

4938
def ask_agent(question)
50-
ai_config = aiclient.config(
51-
@ai_config_key,
52-
@context,
53-
DEFAULT_VALUE,
54-
{ user_question: question }
55-
)
56-
39+
@messages << LaunchDarkly::Server::AI::Message.new('user', question)
5740
begin
5841
completion = ai_config.tracker.track_openai_metrics do
5942
@openai_client.chat.completions.create(
6043
model: ai_config.model.name,
61-
messages: ai_config.messages.map(&:to_h)
44+
messages: @messages.map(&:to_h)
6245
)
6346
end
64-
[completion[:choices][0][:message][:content], ai_config.tracker]
47+
response_content = completion[:choices][0][:message][:content]
48+
@messages << LaunchDarkly::Server::AI::Message.new('assistant', response_content)
49+
response_content
6550
rescue StandardError => e
66-
["An error occurred: #{e.message}", nil]
51+
"An error occurred: #{e.message}"
6752
end
6853
end
6954

70-
def agent_was_helpful(tracker, helpful)
55+
def agent_was_helpful(helpful)
7156
kind = helpful ? :positive : :negative
72-
tracker.track_feedback(kind: kind)
57+
ai_config.tracker.track_feedback(kind: kind)
7358
end
7459
end
7560

61+
DEFAULT_VALUE = LaunchDarkly::Server::AI::AIConfig.new(
62+
enabled: true,
63+
model: LaunchDarkly::Server::AI::ModelConfig.new(name: 'replace-with-your-model'),
64+
messages: [
65+
LaunchDarkly::Server::AI::Message.new('system',
66+
'You are the backup assistant when something prevents retrieving LaunchDarkly configured assistant. You have the persona of HAL 9000 talking with {{ldctx.name}}'),
67+
]
68+
)
69+
70+
# You can also default to disabled if you are unable to connect to LaunchDarkly services.
71+
# DEFAULT_VALUE = LaunchDarkly::Server::AI::AIConfig.new(
72+
# enabled: false
73+
# )
74+
7675
ld_client = LaunchDarkly::LDClient.new(sdk_key)
7776
ai_client = LaunchDarkly::Server::AI::Client.new(ld_client)
7877

@@ -90,24 +89,31 @@ def agent_was_helpful(tracker, helpful)
9089
name: 'Lucy',
9190
})
9291

93-
chatbot = Chatbot.new(ai_client, ai_config_key, OpenAI::Client.new(api_key: openai_api_key), context)
92+
ai_config = ai_client.config(
93+
ai_config_key,
94+
context,
95+
DEFAULT_VALUE
96+
)
97+
98+
unless ai_config.enabled
99+
puts '*** AI features are disabled'
100+
exit 1
101+
end
102+
103+
chatbot = Chatbot.new(ai_config, OpenAI::Client.new(api_key: openai_api_key))
94104

95105
loop do
96106
print "Ask a question (or type 'exit'): "
97-
input = gets&.chomp
98-
break if input.nil? || input.strip.downcase == 'exit'
107+
question = gets&.chomp
108+
break if question.nil? || question.strip.downcase == 'exit'
99109

100-
response, tracker = chatbot.ask_agent(input)
110+
response = chatbot.ask_agent(question)
101111
puts "AI Response: #{response}"
112+
end
102113

103-
next if tracker.nil? # If tracker is nil, skip feedback collection
104-
105-
print "Was the response helpful? [yes/no] (or type 'exit'): "
106-
feedback = gets&.chomp
107-
break if feedback.nil? || feedback.strip.downcase == 'exit'
114+
print "Was the chat helpful? [yes/no]: "
115+
feedback = gets&.chomp
108116

109-
helpful = feedback.strip.downcase == 'yes'
110-
chatbot.agent_was_helpful(tracker, helpful)
111-
end
117+
chatbot.agent_was_helpful(feedback == 'yes') unless feedback.nil?
112118

113-
ld_client.close
119+
ld_client.close

0 commit comments

Comments
 (0)