zakerytclarke commited on
Commit
cfd96b0
·
verified ·
1 Parent(s): c73781a

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +15 -107
src/streamlit_app.py CHANGED
@@ -2,23 +2,11 @@ import os
2
  import time
3
  import threading
4
  import requests
5
- import io
6
 
7
  import streamlit as st
8
  import torch
9
  from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, TextIteratorStreamer
10
 
11
- # Optional parsing libs (safe fallbacks)
12
- try:
13
- from pypdf import PdfReader # pip install pypdf
14
- except Exception:
15
- PdfReader = None
16
-
17
- try:
18
- import pandas as pd # pip install pandas
19
- except Exception:
20
- pd = None
21
-
22
  # Optional LangSmith
23
  try:
24
  from langsmith import Client as LangSmithClient
@@ -103,75 +91,13 @@ with st.sidebar:
103
  height=160,
104
  )
105
 
106
- local_context_text = st.text_area(
107
  "Local context (optional)",
108
- height=120,
109
- placeholder="Extra context to append after web snippets…",
110
- )
111
-
112
- uploaded_files = st.file_uploader(
113
- "Upload context files",
114
- accept_multiple_files=True,
115
- type=None,
116
- help="PDF, TXT, CSV, MD, JSON, etc.",
117
  )
118
 
119
 
120
- # =========================
121
- # FILE PARSING
122
- # =========================
123
- def safe_decode(b: bytes) -> str:
124
- for enc in ("utf-8", "utf-16", "latin-1"):
125
- try:
126
- return b.decode(enc)
127
- except Exception:
128
- pass
129
- return b.decode("utf-8", errors="ignore")
130
-
131
-
132
- def parse_file_to_text(file) -> str:
133
- name = (file.name or "").lower()
134
- raw = file.getvalue()
135
-
136
- if name.endswith(".pdf") and PdfReader:
137
- try:
138
- reader = PdfReader(io.BytesIO(raw))
139
- parts = []
140
- for p in reader.pages:
141
- t = (p.extract_text() or "").strip()
142
- if t:
143
- parts.append(t)
144
- return "\n\n".join(parts).strip()
145
- except Exception as e:
146
- return f"[PDF parse error: {e}]"
147
-
148
- if name.endswith(".csv") and pd:
149
- try:
150
- df = pd.read_csv(io.BytesIO(raw))
151
- return df.to_csv(index=False)
152
- except Exception:
153
- return safe_decode(raw)
154
-
155
- return safe_decode(raw).strip()
156
-
157
-
158
- def build_local_context(text_block: str, files) -> str:
159
- chunks = []
160
- if text_block and text_block.strip():
161
- chunks.append(text_block.strip())
162
-
163
- if files:
164
- for f in files:
165
- parsed = parse_file_to_text(f)
166
- if parsed and parsed.strip():
167
- chunks.append(f"\n\n--- {f.name} ---\n{parsed.strip()}")
168
-
169
- return "\n\n".join(chunks).strip()
170
-
171
-
172
- local_context = build_local_context(local_context_text, uploaded_files)
173
-
174
-
175
  # =========================
176
  # WEB SEARCH (ALWAYS ON)
177
  # =========================
@@ -198,7 +124,8 @@ def web_search_snippets(query: str):
198
 
199
  snippets = []
200
  for item in data.get("web", {}).get("results", [])[:TOP_K_SEARCH]:
201
- desc = (item.get("description") or "").replace("<strong>", "").replace("</strong>", "").strip()
 
202
  if desc:
203
  snippets.append(desc)
204
 
@@ -214,6 +141,7 @@ def truncate_context(web_ctx: str, local_ctx: str, system: str, question: str) -
214
  base = f"\n{system}\n{question}\n"
215
  base_tokens = tokenizer.encode(base)
216
  budget = MAX_INPUT_TOKENS - len(base_tokens)
 
217
  if budget <= 0:
218
  return ""
219
 
@@ -267,7 +195,6 @@ def handle_feedback(idx: int):
267
  run_id=msg["run_id"],
268
  key="thumb_rating",
269
  score=score,
270
- comment="thumbs_up" if score else "thumbs_down",
271
  )
272
  except Exception:
273
  pass
@@ -281,19 +208,12 @@ for i, msg in enumerate(st.session_state.messages):
281
  st.markdown(msg["content"])
282
 
283
  if msg["role"] == "assistant":
284
- # Light, normal-looking stats
285
  st.caption(
286
- f"{msg['search_time']:.2f}s search • {msg['gen_time']:.2f}s gen • "
287
  f"{msg['tps']:.1f} tok/s • in {msg['input_tokens']} • out {msg['output_tokens']}"
288
  )
289
 
290
- # Small inspector (collapsed)
291
  with st.expander("Inspect context"):
292
- st.markdown("**System**")
293
- st.code(msg.get("system_prompt", ""), language="text")
294
- st.markdown("**Question**")
295
- st.code(msg.get("question", ""), language="text")
296
- st.markdown("**Prompt (sent to model)**")
297
  st.code(msg.get("prompt", ""), language="text")
298
 
299
  key = f"fb_{i}"
@@ -323,35 +243,30 @@ if query:
323
  if st.session_state.messages and st.session_state.messages[-1]["role"] == "user":
324
  question = st.session_state.messages[-1]["content"]
325
 
326
- # web search
327
  web_ctx, search_time = web_search_snippets(question)
328
 
329
- # truncate final context
330
- final_context = truncate_context(web_ctx, local_context, system_prompt, question)
 
 
 
 
331
 
332
- # prompt sent to model
333
  prompt = f"{final_context}\n{system_prompt}\n{question}\n"
334
-
335
  input_tokens = count_tokens(prompt)
336
 
337
- # LangSmith run (optional)
338
  run_id = None
339
  if ls_client:
340
  try:
341
  run = ls_client.create_run(
342
  name="teapot_chat",
343
  run_type="llm",
344
- inputs={
345
- "system_prompt": system_prompt,
346
- "question": question,
347
- "prompt": prompt,
348
- },
349
  )
350
  run_id = run.id
351
  except Exception:
352
  pass
353
 
354
- # stream normally in chat
355
  with st.chat_message("assistant"):
356
  placeholder = st.empty()
357
  start = time.perf_counter()
@@ -366,16 +281,11 @@ if st.session_state.messages and st.session_state.messages[-1]["role"] == "user"
366
  tps = output_tokens / gen_time if gen_time > 0 else 0.0
367
 
368
  st.caption(
369
- f"{search_time:.2f}s search • {gen_time:.2f}s gen • "
370
  f"{tps:.1f} tok/s • in {input_tokens} • out {output_tokens}"
371
  )
372
 
373
  with st.expander("Inspect context"):
374
- st.markdown("**System**")
375
- st.code(system_prompt, language="text")
376
- st.markdown("**Question**")
377
- st.code(question, language="text")
378
- st.markdown("**Prompt (sent to model)**")
379
  st.code(prompt, language="text")
380
 
381
  if ls_client and run_id:
@@ -388,8 +298,6 @@ if st.session_state.messages and st.session_state.messages[-1]["role"] == "user"
388
  {
389
  "role": "assistant",
390
  "content": final_text,
391
- "system_prompt": system_prompt,
392
- "question": question,
393
  "prompt": prompt,
394
  "search_time": search_time,
395
  "gen_time": gen_time,
 
2
  import time
3
  import threading
4
  import requests
 
5
 
6
  import streamlit as st
7
  import torch
8
  from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, TextIteratorStreamer
9
 
 
 
 
 
 
 
 
 
 
 
 
10
  # Optional LangSmith
11
  try:
12
  from langsmith import Client as LangSmithClient
 
91
  height=160,
92
  )
93
 
94
+ local_context = st.text_area(
95
  "Local context (optional)",
96
+ height=140,
97
+ placeholder="Extra context appended after web snippets…",
 
 
 
 
 
 
 
98
  )
99
 
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  # =========================
102
  # WEB SEARCH (ALWAYS ON)
103
  # =========================
 
124
 
125
  snippets = []
126
  for item in data.get("web", {}).get("results", [])[:TOP_K_SEARCH]:
127
+ desc = (item.get("description") or "")
128
+ desc = desc.replace("<strong>", "").replace("</strong>", "").strip()
129
  if desc:
130
  snippets.append(desc)
131
 
 
141
  base = f"\n{system}\n{question}\n"
142
  base_tokens = tokenizer.encode(base)
143
  budget = MAX_INPUT_TOKENS - len(base_tokens)
144
+
145
  if budget <= 0:
146
  return ""
147
 
 
195
  run_id=msg["run_id"],
196
  key="thumb_rating",
197
  score=score,
 
198
  )
199
  except Exception:
200
  pass
 
208
  st.markdown(msg["content"])
209
 
210
  if msg["role"] == "assistant":
 
211
  st.caption(
212
+ f"{msg['search_time']:.2f}s • {msg['gen_time']:.2f}s • "
213
  f"{msg['tps']:.1f} tok/s • in {msg['input_tokens']} • out {msg['output_tokens']}"
214
  )
215
 
 
216
  with st.expander("Inspect context"):
 
 
 
 
 
217
  st.code(msg.get("prompt", ""), language="text")
218
 
219
  key = f"fb_{i}"
 
243
  if st.session_state.messages and st.session_state.messages[-1]["role"] == "user":
244
  question = st.session_state.messages[-1]["content"]
245
 
 
246
  web_ctx, search_time = web_search_snippets(question)
247
 
248
+ final_context = truncate_context(
249
+ web_ctx,
250
+ local_context,
251
+ system_prompt,
252
+ question,
253
+ )
254
 
 
255
  prompt = f"{final_context}\n{system_prompt}\n{question}\n"
 
256
  input_tokens = count_tokens(prompt)
257
 
 
258
  run_id = None
259
  if ls_client:
260
  try:
261
  run = ls_client.create_run(
262
  name="teapot_chat",
263
  run_type="llm",
264
+ inputs={"prompt": prompt, "question": question},
 
 
 
 
265
  )
266
  run_id = run.id
267
  except Exception:
268
  pass
269
 
 
270
  with st.chat_message("assistant"):
271
  placeholder = st.empty()
272
  start = time.perf_counter()
 
281
  tps = output_tokens / gen_time if gen_time > 0 else 0.0
282
 
283
  st.caption(
284
+ f"{search_time:.2f}s • {gen_time:.2f}s • "
285
  f"{tps:.1f} tok/s • in {input_tokens} • out {output_tokens}"
286
  )
287
 
288
  with st.expander("Inspect context"):
 
 
 
 
 
289
  st.code(prompt, language="text")
290
 
291
  if ls_client and run_id:
 
298
  {
299
  "role": "assistant",
300
  "content": final_text,
 
 
301
  "prompt": prompt,
302
  "search_time": search_time,
303
  "gen_time": gen_time,