bol20162021 commited on
Commit
99728fb
1 Parent(s): 5283eeb

Better error message, add back up API key

Browse files
Files changed (1) hide show
  1. app.py +85 -47
app.py CHANGED
@@ -25,6 +25,10 @@ character_avatars = {
25
  }
26
 
27
 
 
 
 
 
28
  predefined_characters = ["Harry Potter", "Hermione Granger", "poor Ph.D. student", "Donald Trump", "a super cute red panda"]
29
 
30
  def get_character(dropdown_value, custom_value):
@@ -47,71 +51,105 @@ for character, filename in character_avatars.items():
47
  else:
48
  pass
49
 
50
- async def generate_response_stream(messages, api_key):
51
- client = openai.AsyncOpenAI(
52
- api_key=api_key,
53
- base_url="https://api.sambanova.ai/v1",
54
- )
55
- try:
56
- if len(messages) >= 10:
57
- # avoid hitting rate limit
58
- time.sleep(0.5)
59
- response = await client.chat.completions.create(
60
- model='Meta-Llama-3.1-405B-Instruct',
61
- messages=messages,
62
- temperature=0.7,
63
- top_p=0.9,
64
- stream=True
65
  )
66
- full_response = ""
67
- async for chunk in response:
68
- if chunk.choices[0].delta.content is not None:
69
- full_response += chunk.choices[0].delta.content
70
- yield full_response
71
- except Exception as e:
72
- yield f"Error: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
  async def simulate_conversation_stream(character1, character2, initial_message, num_turns, api_key):
75
- messages_character_1 = [{"role": "system", "content": f"Avoid overly verbose answer in your response. Act as {character1}."},
76
- {"role": "assistant", "content": initial_message}]
77
- messages_character_2 = [{"role": "system", "content": f"Avoid overly verbose answer in your response. Act as {character2}."},
78
- {"role": "user", "content": initial_message}]
 
 
 
 
79
 
80
  conversation = [
81
  {"character": character1, "content": initial_message},
82
- {"character": character2, "content": ""} # Initialize with an empty response for character2
83
  ]
84
  yield format_conversation_as_html(conversation)
85
  num_turns *= 2
86
  for turn_num in range(num_turns - 1):
87
  current_character = character2 if turn_num % 2 == 0 else character1
88
  messages = messages_character_2 if turn_num % 2 == 0 else messages_character_1
89
-
 
 
 
90
  full_response = ""
91
- async for response in generate_response_stream(messages, api_key):
92
- full_response = response
93
- conversation[-1]["content"] = full_response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  yield format_conversation_as_html(conversation)
 
 
95
 
96
- if turn_num % 2 == 0:
97
- messages_character_1.append({"role": "user", "content": full_response})
98
- messages_character_2.append({"role": "assistant", "content": full_response})
99
- else:
100
- messages_character_2.append({"role": "user", "content": full_response})
101
- messages_character_1.append({"role": "assistant", "content": full_response})
102
-
103
- # Add a new empty message for the next turn, if it's not the last turn
104
- if turn_num < num_turns - 2:
105
- next_character = character1 if turn_num % 2 == 0 else character2
106
- conversation.append({"character": next_character, "content": ""})
107
 
108
  def stream_conversation(character1, character2, initial_message, num_turns, api_key, queue):
109
  async def run_simulation():
110
- async for html in simulate_conversation_stream(character1, character2, initial_message, num_turns, api_key):
111
- queue.put(html)
112
- queue.put(None) # Signal that the conversation is complete
113
-
114
- asyncio.run(run_simulation())
 
 
 
 
 
 
 
 
 
 
115
 
116
  def validate_api_key(api_key):
117
  if not api_key.strip():
 
25
  }
26
 
27
 
28
+ BACKUP_API_KEY_0 = os.environ.get('BACKUP_API_KEY_0')
29
+ BACKUP_API_KEY_1 = os.environ.get('BACKUP_API_KEY_1')
30
+ BACKUP_API_KEYS = [BACKUP_API_KEY_0, BACKUP_API_KEY_1]
31
+
32
  predefined_characters = ["Harry Potter", "Hermione Granger", "poor Ph.D. student", "Donald Trump", "a super cute red panda"]
33
 
34
  def get_character(dropdown_value, custom_value):
 
51
  else:
52
  pass
53
 
54
+ async def generate_response_stream(messages, user_api_key):
55
+ # Combine the user's API key with your backup keys
56
+ api_keys = [user_api_key] + BACKUP_API_KEYS # backup_api_keys is a list of your internal keys
57
+
58
+ for idx, api_key in enumerate(api_keys):
59
+ client = openai.AsyncOpenAI(
60
+ api_key=api_key,
61
+ base_url="https://api.sambanova.ai/v1",
 
 
 
 
 
 
 
62
  )
63
+ try:
64
+ response = await client.chat.completions.create(
65
+ model='Meta-Llama-3.1-405B-Instruct',
66
+ messages=messages,
67
+ temperature=0.7,
68
+ top_p=0.9,
69
+ stream=True
70
+ )
71
+ full_response = ""
72
+ async for chunk in response:
73
+ if chunk.choices[0].delta.content:
74
+ full_response += chunk.choices[0].delta.content
75
+ yield full_response
76
+ # If successful, exit the loop
77
+ return
78
+ except RateLimitError:
79
+ if idx == len(api_keys) - 1:
80
+ # No more API keys to try
81
+ raise Exception("Rate limit exceeded")
82
+ else:
83
+ # Try the next API key
84
+ continue
85
+ except Exception as e:
86
+ # For other exceptions, raise the error
87
+ raise e
88
 
89
  async def simulate_conversation_stream(character1, character2, initial_message, num_turns, api_key):
90
+ messages_character_1 = [
91
+ {"role": "system", "content": f"Avoid overly verbose answer in your response. Act as {character1}."},
92
+ {"role": "assistant", "content": initial_message}
93
+ ]
94
+ messages_character_2 = [
95
+ {"role": "system", "content": f"Avoid overly verbose answer in your response. Act as {character2}."},
96
+ {"role": "user", "content": initial_message}
97
+ ]
98
 
99
  conversation = [
100
  {"character": character1, "content": initial_message},
101
+ # We will add new messages as we loop
102
  ]
103
  yield format_conversation_as_html(conversation)
104
  num_turns *= 2
105
  for turn_num in range(num_turns - 1):
106
  current_character = character2 if turn_num % 2 == 0 else character1
107
  messages = messages_character_2 if turn_num % 2 == 0 else messages_character_1
108
+
109
+ # Add a new empty message for the current character
110
+ conversation.append({"character": current_character, "content": ""})
111
+
112
  full_response = ""
113
+ try:
114
+ async for response in generate_response_stream(messages, api_key):
115
+ full_response = response
116
+ conversation[-1]["content"] = full_response
117
+ yield format_conversation_as_html(conversation)
118
+
119
+ # After a successful response, update the messages
120
+ if turn_num % 2 == 0:
121
+ messages_character_1.append({"role": "user", "content": full_response})
122
+ messages_character_2.append({"role": "assistant", "content": full_response})
123
+ else:
124
+ messages_character_2.append({"role": "user", "content": full_response})
125
+ messages_character_1.append({"role": "assistant", "content": full_response})
126
+ except Exception as e:
127
+ # Replace the current message with the error message
128
+ error_message = f"Error: {str(e)}"
129
+ conversation[-1]["character"] = "System"
130
+ conversation[-1]["content"] = error_message
131
  yield format_conversation_as_html(conversation)
132
+ # Stop the conversation
133
+ break
134
 
 
 
 
 
 
 
 
 
 
 
 
135
 
136
  def stream_conversation(character1, character2, initial_message, num_turns, api_key, queue):
137
  async def run_simulation():
138
+ try:
139
+ async for html in simulate_conversation_stream(character1, character2, initial_message, num_turns, api_key):
140
+ queue.put(html)
141
+ queue.put(None) # Signal that the conversation is complete
142
+ except Exception as e:
143
+ # Handle exceptions and put the error message in the queue
144
+ error_message = f"Error: {str(e)}"
145
+ queue.put(error_message)
146
+ queue.put(None) # Signal that the conversation is complete
147
+
148
+ # Create a new event loop for the thread
149
+ loop = asyncio.new_event_loop()
150
+ asyncio.set_event_loop(loop)
151
+ loop.run_until_complete(run_simulation())
152
+ loop.close()
153
 
154
  def validate_api_key(api_key):
155
  if not api_key.strip():