resumesearch commited on
Commit
e4b7b93
Β·
verified Β·
1 Parent(s): 1e12ce1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -49
app.py CHANGED
@@ -1,9 +1,10 @@
1
  """
2
- app.py – Advanced Chatbot with Sliding-Window Context Management
3
  (OpenAI Python SDK β‰₯1.0.0)
4
  """
5
 
6
  import os
 
7
  import gradio as gr
8
  import tiktoken
9
  from openai import OpenAI
@@ -11,83 +12,80 @@ from openai import OpenAI
11
  # β€”β€”β€” Initialize OpenAI client β€”β€”β€”
12
  client = OpenAI(api_key=os.getenv("OPENAI_API_KEY", "").strip())
13
 
14
- # β€”β€”β€” Model fallback list (highest quality first) β€”β€”β€”
15
- # Comma-separated in env, e.g. "gpt-4-32k,gpt-4,gpt-3.5-turbo"
16
- model_list = os.getenv("OPENAI_MODEL_LIST", "gpt-4-32k,gpt-4,gpt-3.5-turbo")
17
- MODELS = [m.strip() for m in model_list.split(",") if m.strip()]
18
 
19
- # β€”β€”β€” Configuration β€”β€”β€”
20
- MAX_CONTEXT = 32768 # model’s max context window (e.g. GPT-4-32k)
21
- BUFFER_TOKENS = 500 # reserved tokens for the reply
22
- REPLY_MAX = 2048 # max tokens in the answer
23
- TEMPERATURE = 0.3 # creativity vs. determinism
24
 
25
  def count_tokens(text: str, model: str) -> int:
26
- """Return the number of tokens for given text under specified model."""
27
  enc = tiktoken.encoding_for_model(model)
28
  return len(enc.encode(text))
29
 
30
- def trim_conversation(convo: list[dict], model: str) -> list[dict]:
31
  """
32
- Slide the window: drop oldest user/assistant turns
33
- until total tokens + buffer ≀ MAX_CONTEXT.
34
  """
35
- # compute initial usage
36
  tokens = [count_tokens(m["content"], model) for m in convo]
37
- total = sum(tokens)
38
- # pop oldest turns (after system prompt) while over budget
39
- while total + BUFFER_TOKENS > MAX_CONTEXT and len(convo) > 2:
40
- convo.pop(1) # remove oldest user
41
- convo.pop(1) # remove that assistant reply
42
  tokens = [count_tokens(m["content"], model) for m in convo]
43
- total = sum(tokens)
44
  return convo
45
 
46
- def safe_chat(convo: list[dict]):
47
  """
48
- 1) Try each model in MODELS in order.
49
- 2) If model-not-found, skip to next.
50
- 3) If context-length error, trim history and retry same model once.
51
  """
52
  last_exc = None
53
-
54
- for model in MODELS:
55
  try:
56
  return client.chat.completions.create(
57
  model=model,
58
  messages=convo,
59
- max_tokens=REPLY_MAX,
60
  temperature=TEMPERATURE
61
  )
62
  except Exception as e:
63
  msg = str(e).lower()
64
- # model not found β†’ fallback
65
  if "does not exist" in msg or "model_not_found" in msg or "404" in msg:
66
  last_exc = e
67
  continue
68
- # context-length error β†’ trim & retry
69
  if "context length" in msg or "maximum context length" in msg:
70
- trimmed = trim_conversation(convo.copy(), model)
71
  try:
72
  return client.chat.completions.create(
73
  model=model,
74
  messages=trimmed,
75
- max_tokens=REPLY_MAX,
76
  temperature=TEMPERATURE
77
  )
78
  except Exception as e2:
79
  last_exc = e2
80
  continue
81
- # other errors β†’ re-raise
82
  raise
83
-
84
- # none succeeded
85
  raise last_exc or RuntimeError("All models failed in safe_chat()")
86
 
87
  def chat_handler(
88
  user_message: str,
89
  history: list[tuple[str, str]],
90
- system_prompt: str
 
 
 
91
  ) -> tuple[list[tuple[str, str]], str]:
92
  """Gradio handler: builds convo, calls safe_chat, updates history."""
93
  if not user_message.strip():
@@ -96,14 +94,18 @@ def chat_handler(
96
  return history, "❌ OPENAI_API_KEY not set."
97
 
98
  # Build the conversation payload
99
- convo = [{"role": "system", "content": system_prompt}]
100
  for u, b in history or []:
101
- convo.append({"role": "user", "content": u})
102
- convo.append({"role": "assistant", "content": b})
103
- convo.append({"role": "user", "content": user_message})
 
 
 
 
104
 
105
  try:
106
- resp = safe_chat(convo)
107
  reply = resp.choices[0].message.content
108
  except Exception as e:
109
  reply = f"❌ OpenAI error: {e}"
@@ -113,16 +115,34 @@ def chat_handler(
113
  return history, ""
114
 
115
  # β€”β€”β€” Gradio UI β€”β€”β€”
116
- with gr.Blocks(title="πŸ€– Advanced Chatbot (Sliding-Window Context)") as demo:
117
  gr.Markdown(
118
  """
119
  # Advanced Chatbot
120
- This bot preserves your newest input by **sliding** out the oldest history
121
- when you exceed the model's context windowβ€”no summarization required.
122
- It also **automatically falls back** through multiple models if one isn’t available.
 
123
  """
124
  )
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  system_txt = gr.Textbox(
127
  lines=3,
128
  value=(
@@ -132,16 +152,22 @@ with gr.Blocks(title="πŸ€– Advanced Chatbot (Sliding-Window Context)") as demo:
132
  label="System Prompt"
133
  )
134
 
135
- chatbot = gr.Chatbot(label="Conversation")
136
  user_input = gr.Textbox(placeholder="Type your message here...", label="You")
137
- send_btn = gr.Button("Send")
138
 
139
  send_btn.click(
140
  fn=chat_handler,
141
- inputs=[user_input, chatbot, system_txt],
 
 
 
 
 
 
 
142
  outputs=[chatbot, user_input]
143
  )
144
 
145
  if __name__ == "__main__":
146
  demo.launch()
147
-
 
1
  """
2
+ app.py – Advanced Chatbot with Model Selector, Context & Reply Token Sliders
3
  (OpenAI Python SDK β‰₯1.0.0)
4
  """
5
 
6
  import os
7
+ import asyncio
8
  import gradio as gr
9
  import tiktoken
10
  from openai import OpenAI
 
12
  # β€”β€”β€” Initialize OpenAI client β€”β€”β€”
13
  client = OpenAI(api_key=os.getenv("OPENAI_API_KEY", "").strip())
14
 
15
+ # β€”β€”β€” Environment-configured model list (fallback order) β€”β€”β€”
16
+ env_models = os.getenv("OPENAI_MODEL_LIST", "gpt-4-32k,gpt-4,gpt-3.5-turbo")
17
+ ALL_MODELS = [m.strip() for m in env_models.split(",") if m.strip()]
 
18
 
19
+ # β€”β€”β€” Default limits β€”β€”β€”
20
+ DEFAULT_MAX_CONTEXT = 32768 # tokens
21
+ DEFAULT_REPLY_MAX = 2048 # tokens
22
+ BUFFER_TOKENS = 500 # reserved for the model’s answer
23
+ TEMPERATURE = 0.3
24
 
25
  def count_tokens(text: str, model: str) -> int:
 
26
  enc = tiktoken.encoding_for_model(model)
27
  return len(enc.encode(text))
28
 
29
+ def trim_conversation(convo: list[dict], model: str, max_context: int) -> list[dict]:
30
  """
31
+ Slide-window: drop the oldest user/assistant turns until
32
+ total tokens + BUFFER_TOKENS ≀ max_context.
33
  """
 
34
  tokens = [count_tokens(m["content"], model) for m in convo]
35
+ total = sum(tokens)
36
+ while total + BUFFER_TOKENS > max_context and len(convo) > 2:
37
+ convo.pop(1) # oldest user
38
+ convo.pop(1) # its assistant reply
 
39
  tokens = [count_tokens(m["content"], model) for m in convo]
40
+ total = sum(tokens)
41
  return convo
42
 
43
+ def safe_chat(convo: list[dict], max_context: int, max_reply: int, model_list: list[str]):
44
  """
45
+ Try each model in model_list:
46
+ - on model-not-found: skip to next
47
+ - on context-length: trim history & retry same model once
48
  """
49
  last_exc = None
50
+ for model in model_list:
 
51
  try:
52
  return client.chat.completions.create(
53
  model=model,
54
  messages=convo,
55
+ max_tokens=max_reply,
56
  temperature=TEMPERATURE
57
  )
58
  except Exception as e:
59
  msg = str(e).lower()
60
+ # Model unavailable β†’ fallback
61
  if "does not exist" in msg or "model_not_found" in msg or "404" in msg:
62
  last_exc = e
63
  continue
64
+ # Context-length error β†’ slide window & retry
65
  if "context length" in msg or "maximum context length" in msg:
66
+ trimmed = trim_conversation(convo.copy(), model, max_context)
67
  try:
68
  return client.chat.completions.create(
69
  model=model,
70
  messages=trimmed,
71
+ max_tokens=max_reply,
72
  temperature=TEMPERATURE
73
  )
74
  except Exception as e2:
75
  last_exc = e2
76
  continue
77
+ # Other errors β†’ bubble up
78
  raise
79
+ # All models failed
 
80
  raise last_exc or RuntimeError("All models failed in safe_chat()")
81
 
82
  def chat_handler(
83
  user_message: str,
84
  history: list[tuple[str, str]],
85
+ system_prompt: str,
86
+ selected_model: str,
87
+ max_context: int,
88
+ max_reply: int
89
  ) -> tuple[list[tuple[str, str]], str]:
90
  """Gradio handler: builds convo, calls safe_chat, updates history."""
91
  if not user_message.strip():
 
94
  return history, "❌ OPENAI_API_KEY not set."
95
 
96
  # Build the conversation payload
97
+ convo = [{"role":"system","content":system_prompt}]
98
  for u, b in history or []:
99
+ convo.append({"role":"user", "content":u})
100
+ convo.append({"role":"assistant", "content":b})
101
+ convo.append({"role":"user","content":user_message})
102
+
103
+ # Prepare model list: user choice first, then the rest
104
+ fallback = [m for m in ALL_MODELS if m != selected_model]
105
+ models_to_try = [selected_model] + fallback
106
 
107
  try:
108
+ resp = safe_chat(convo, max_context, max_reply, models_to_try)
109
  reply = resp.choices[0].message.content
110
  except Exception as e:
111
  reply = f"❌ OpenAI error: {e}"
 
115
  return history, ""
116
 
117
  # β€”β€”β€” Gradio UI β€”β€”β€”
118
+ with gr.Blocks(title="πŸ€– Advanced Chatbot") as demo:
119
  gr.Markdown(
120
  """
121
  # Advanced Chatbot
122
+ - **Model selector**: pick any supported OpenAI model
123
+ - **Context slider**: adjust how many tokens of history to keep
124
+ - **Reply slider**: adjust maximum tokens in the answer
125
+ - **Sliding-window**: oldest history drops automatically when over limit
126
  """
127
  )
128
 
129
+ with gr.Row():
130
+ model_dropdown = gr.Dropdown(
131
+ choices=ALL_MODELS,
132
+ value=ALL_MODELS[0],
133
+ label="Choose Model"
134
+ )
135
+ context_slider = gr.Slider(
136
+ minimum=1000, maximum=DEFAULT_MAX_CONTEXT,
137
+ step=256, value=DEFAULT_MAX_CONTEXT,
138
+ label="Max Context Tokens"
139
+ )
140
+ reply_slider = gr.Slider(
141
+ minimum=100, maximum=8192,
142
+ step=100, value=DEFAULT_REPLY_MAX,
143
+ label="Max Reply Tokens"
144
+ )
145
+
146
  system_txt = gr.Textbox(
147
  lines=3,
148
  value=(
 
152
  label="System Prompt"
153
  )
154
 
155
+ chatbot = gr.Chatbot(label="Conversation")
156
  user_input = gr.Textbox(placeholder="Type your message here...", label="You")
157
+ send_btn = gr.Button("Send")
158
 
159
  send_btn.click(
160
  fn=chat_handler,
161
+ inputs=[
162
+ user_input,
163
+ chatbot,
164
+ system_txt,
165
+ model_dropdown,
166
+ context_slider,
167
+ reply_slider
168
+ ],
169
  outputs=[chatbot, user_input]
170
  )
171
 
172
  if __name__ == "__main__":
173
  demo.launch()