resumesearch commited on
Commit
6d260b0
·
verified ·
1 Parent(s): 738451b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -60
app.py CHANGED
@@ -1,116 +1,114 @@
1
  """
2
  app.py – Advanced Chatbot with Automatic Long-Input Handling
 
3
  """
4
 
5
  import os
6
  import asyncio
7
  import gradio as gr
8
-
9
- import openai
10
  import tiktoken
 
11
 
12
- # Alias the right exception class (your SDK uses BadRequestError for invalid‐request)
13
- try:
14
- # if your install still has openai.error, this will work
15
- from openai.error import InvalidRequestError
16
- except ImportError:
17
- # otherwise, BadRequestError covers context-length errors
18
- from openai import BadRequestError as InvalidRequestError
19
 
20
  # Configuration
21
- MODEL_NAME = "gpt-4-32k"
22
- MAX_CONTEXT_TOKENS = 32768
23
- SUMMARY_MAX_TOKENS = 1024
24
- REPLY_MAX_TOKENS = 2048
25
- TEMPERATURE = 0.3
26
- BUFFER_TOKENS = 500 # reserved for the models reply
27
-
28
- # Load your key
29
- openai.api_key = os.getenv("OPENAI_API_KEY", "").strip()
30
 
31
  def count_tokens(text: str, model: str = MODEL_NAME) -> int:
32
  enc = tiktoken.encoding_for_model(model)
33
  return len(enc.encode(text))
34
 
35
- def chunk_text(text: str, max_tokens: int, model: str = MODEL_NAME) -> list[str]:
36
- words, chunks, current = text.split(), [], []
37
  for w in words:
38
- current.append(w)
39
- if count_tokens(" ".join(current), model) >= max_tokens:
40
- last = current.pop()
41
- chunks.append(" ".join(current))
42
- current = [last]
43
- if current:
44
- chunks.append(" ".join(current))
45
  return chunks
46
 
47
  async def summarize_chunk(chunk: str) -> str:
48
- resp = await openai.ChatCompletion.acreate(
49
  model=MODEL_NAME,
50
  messages=[
51
- {"role":"system","content":"You are a concise summarizer."},
52
- {"role":"user","content":f"Summarize this text briefly, preserving key details:\n\n{chunk}"}
53
  ],
54
- max_tokens=SUMMARY_MAX_TOKENS,
55
  temperature=0.0,
56
  )
57
  return resp.choices[0].message.content.strip()
58
 
59
- def safe_chat_completion(convo: list[dict], max_tokens: int):
60
- """Try once, catch context-length, summarize last user message, retry."""
 
 
 
 
61
  try:
62
- return openai.ChatCompletion.create(
63
  model=MODEL_NAME,
64
  messages=convo,
65
- max_tokens=max_tokens,
66
  temperature=TEMPERATURE
67
  )
68
- except InvalidRequestError as e:
69
- err = str(e)
70
- if "maximum context length" not in err:
71
- raise # some other bad request error
 
72
 
73
- # calculate tokens used by everything except the last user message
74
  used = count_tokens("".join(m["content"] for m in convo[:-1]), MODEL_NAME)
75
- allowed_for_user = MAX_CONTEXT_TOKENS - used - BUFFER_TOKENS
76
- if allowed_for_user < 100:
77
- raise RuntimeError("Input too large, even after trimming.")
78
 
79
- # chunk & summarize
80
- last = convo[-1]["content"]
81
- chunks = chunk_text(last, allowed_for_user // 2, MODEL_NAME)
82
  summaries = asyncio.get_event_loop().run_until_complete(
83
- asyncio.gather(*(summarize_chunk(c) for c in chunks))
84
  )
 
85
  convo[-1]["content"] = " ".join(summaries)
86
 
87
- # retry once
88
- return openai.ChatCompletion.create(
89
  model=MODEL_NAME,
90
  messages=convo,
91
- max_tokens=max_tokens,
92
  temperature=TEMPERATURE
93
  )
94
 
95
  def chat_handler(
96
  user_message: str,
97
- history: list[tuple[str, str]],
98
  system_prompt: str
99
- ) -> tuple[list[tuple[str, str]], str]:
100
  if not user_message.strip():
101
  return history, ""
102
- if not openai.api_key:
103
  return history, "❌ OPENAI_API_KEY not set."
104
 
105
- # build convo
106
  convo = [{"role":"system","content":system_prompt}]
107
  for u, b in history or []:
108
  convo.append({"role":"user", "content":u})
109
  convo.append({"role":"assistant", "content":b})
110
- convo.append({"role":"user","content":user_message})
111
 
112
  try:
113
- resp = safe_chat_completion(convo, max_tokens=REPLY_MAX_TOKENS)
114
  reply = resp.choices[0].message.content
115
  except Exception as e:
116
  reply = f"❌ OpenAI error: {e}"
@@ -119,7 +117,7 @@ def chat_handler(
119
  history.append((user_message, reply))
120
  return history, ""
121
 
122
- # --- Gradio UI ---
123
  with gr.Blocks(title="🤖 Advanced Chatbot (Long-Input Safe)") as demo:
124
  gr.Markdown(
125
  """
@@ -138,9 +136,9 @@ with gr.Blocks(title="🤖 Advanced Chatbot (Long-Input Safe)") as demo:
138
  label="System Prompt"
139
  )
140
 
141
- chatbot = gr.Chatbot(label="Conversation")
142
- user_input = gr.Textbox(placeholder="Type your message here...", label="You")
143
- send_btn = gr.Button("Send")
144
 
145
  send_btn.click(
146
  fn=chat_handler,
 
1
  """
2
  app.py – Advanced Chatbot with Automatic Long-Input Handling
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
11
 
12
+ # Instantiate the new client
13
+ client = OpenAI(api_key=os.getenv("OPENAI_API_KEY", "").strip())
 
 
 
 
 
14
 
15
  # Configuration
16
+ MODEL_NAME = "gpt-4-32k"
17
+ MAX_CONTEXT = 32768
18
+ SUMMARY_MAX = 1024
19
+ REPLY_MAX = 2048
20
+ TEMPERATURE = 0.3
21
+ BUFFER_TOKENS = 500 # leave room for the model's answer
 
 
 
22
 
23
  def count_tokens(text: str, model: str = MODEL_NAME) -> int:
24
  enc = tiktoken.encoding_for_model(model)
25
  return len(enc.encode(text))
26
 
27
+ def chunk_text(text: str, max_toks: int, model: str = MODEL_NAME) -> list[str]:
28
+ words, chunks, cur = text.split(), [], []
29
  for w in words:
30
+ cur.append(w)
31
+ if count_tokens(" ".join(cur), model) >= max_toks:
32
+ last = cur.pop()
33
+ chunks.append(" ".join(cur))
34
+ cur = [last]
35
+ if cur:
36
+ chunks.append(" ".join(cur))
37
  return chunks
38
 
39
  async def summarize_chunk(chunk: str) -> str:
40
+ resp = await client.chat.completions.create(
41
  model=MODEL_NAME,
42
  messages=[
43
+ {"role":"system", "content":"You are a concise summarizer."},
44
+ {"role":"user", "content":f"Summarize this text briefly, preserving key details:\n\n{chunk}"}
45
  ],
46
+ max_tokens=SUMMARY_MAX,
47
  temperature=0.0,
48
  )
49
  return resp.choices[0].message.content.strip()
50
 
51
+ def safe_chat(convo: list[dict], max_reply: int):
52
+ """
53
+ 1) Try a normal chat
54
+ 2) On context-length error, summarize only the last user message
55
+ 3) Retry once with the summaries in place
56
+ """
57
  try:
58
+ return client.chat.completions.create(
59
  model=MODEL_NAME,
60
  messages=convo,
61
+ max_tokens=max_reply,
62
  temperature=TEMPERATURE
63
  )
64
+ except Exception as e:
65
+ text = str(e).lower()
66
+ if "context length" not in text and "maximum context length" not in text:
67
+ # Not a token-limit issue
68
+ raise
69
 
70
+ # How many tokens have we used so far?
71
  used = count_tokens("".join(m["content"] for m in convo[:-1]), MODEL_NAME)
72
+ allowed = MAX_CONTEXT - used - BUFFER_TOKENS
73
+ if allowed < 100:
74
+ raise RuntimeError("Even after trimming, input is too large.")
75
 
76
+ # Chunk & summarize the last message
77
+ last_msg = convo[-1]["content"]
78
+ bits = chunk_text(last_msg, max_toks=allowed // 2, model=MODEL_NAME)
79
  summaries = asyncio.get_event_loop().run_until_complete(
80
+ asyncio.gather(*(summarize_chunk(b) for b in bits))
81
  )
82
+
83
  convo[-1]["content"] = " ".join(summaries)
84
 
85
+ # Retry once
86
+ return client.chat.completions.create(
87
  model=MODEL_NAME,
88
  messages=convo,
89
+ max_tokens=max_reply,
90
  temperature=TEMPERATURE
91
  )
92
 
93
  def chat_handler(
94
  user_message: str,
95
+ history: list[tuple[str,str]],
96
  system_prompt: str
97
+ ) -> tuple[list[tuple[str,str]], str]:
98
  if not user_message.strip():
99
  return history, ""
100
+ if not client.api_key:
101
  return history, "❌ OPENAI_API_KEY not set."
102
 
103
+ # Build the full conversation
104
  convo = [{"role":"system","content":system_prompt}]
105
  for u, b in history or []:
106
  convo.append({"role":"user", "content":u})
107
  convo.append({"role":"assistant", "content":b})
108
+ convo.append({"role":"user", "content":user_message})
109
 
110
  try:
111
+ resp = safe_chat(convo, max_reply=REPLY_MAX)
112
  reply = resp.choices[0].message.content
113
  except Exception as e:
114
  reply = f"❌ OpenAI error: {e}"
 
117
  history.append((user_message, reply))
118
  return history, ""
119
 
120
+ # ——— Gradio UI ———
121
  with gr.Blocks(title="🤖 Advanced Chatbot (Long-Input Safe)") as demo:
122
  gr.Markdown(
123
  """
 
136
  label="System Prompt"
137
  )
138
 
139
+ chatbot = gr.Chatbot(label="Conversation")
140
+ user_input = gr.Textbox(placeholder="Type your message here", label="You")
141
+ send_btn = gr.Button("Send")
142
 
143
  send_btn.click(
144
  fn=chat_handler,