amiguel commited on
Commit
1adf5f1
Β·
verified Β·
1 Parent(s): 1e2e42f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -22
app.py CHANGED
@@ -10,21 +10,21 @@ from langchain_community.embeddings import HuggingFaceEmbeddings
10
  from langchain.vectorstores import FAISS
11
  from langchain.schema import Document
12
 
13
- # --- HF Token ---
14
  HF_TOKEN = st.secrets["HF_TOKEN"]
15
 
16
  # --- Page Config ---
17
  st.set_page_config(page_title="DigiTwin RAG", page_icon="πŸ“‚", layout="centered")
18
  st.title("πŸ“‚ DigiTs the Twin")
19
 
20
- # --- Upload Files Sidebar ---
21
  with st.sidebar:
22
  st.header("πŸ“„ Upload Knowledge Files")
23
  uploaded_files = st.file_uploader("Upload PDFs or .txt files", accept_multiple_files=True, type=["pdf", "txt"])
24
  if uploaded_files:
25
  st.success(f"{len(uploaded_files)} file(s) uploaded")
26
 
27
- # --- Model Loading ---
28
  @st.cache_resource
29
  def load_model():
30
  tokenizer = AutoTokenizer.from_pretrained("amiguel/GM_Qwen1.8B_Finetune", trust_remote_code=True, token=HF_TOKEN)
@@ -39,7 +39,7 @@ def load_model():
39
 
40
  model, tokenizer = load_model()
41
 
42
- # --- Prompt Helper ---
43
  SYSTEM_PROMPT = (
44
  "You are DigiTwin, a digital expert and senior topside engineer specializing in inspection and maintenance "
45
  "of offshore piping systems, structural elements, mechanical equipment, floating production units, pressure vessels "
@@ -48,7 +48,7 @@ SYSTEM_PROMPT = (
48
  "field experience, industry regulations, and proven methodologies in asset integrity and reliability engineering."
49
  )
50
 
51
-
52
  def build_prompt(messages, context=""):
53
  prompt = f"<|im_start|>system\n{SYSTEM_PROMPT}\n\nContext:\n{context}<|im_end|>\n"
54
  for msg in messages:
@@ -57,17 +57,15 @@ def build_prompt(messages, context=""):
57
  prompt += "<|im_start|>assistant\n"
58
  return prompt
59
 
60
-
61
- # --- RAG Embedding and Search ---
62
  @st.cache_resource
63
  def embed_uploaded_files(files):
64
  raw_docs = []
65
  for f in files:
66
- file_path = f"/tmp/{f.name}"
67
- with open(file_path, "wb") as out_file:
68
  out_file.write(f.read())
69
-
70
- loader = PyPDFLoader(file_path) if f.name.endswith(".pdf") else TextLoader(file_path)
71
  raw_docs.extend(loader.load())
72
 
73
  splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=64)
@@ -78,7 +76,7 @@ def embed_uploaded_files(files):
78
 
79
  retriever = embed_uploaded_files(uploaded_files) if uploaded_files else None
80
 
81
- # --- Streaming Response ---
82
  def generate_response(prompt_text):
83
  streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
84
  inputs = tokenizer(prompt_text, return_tensors="pt").to(model.device)
@@ -95,37 +93,56 @@ def generate_response(prompt_text):
95
  thread.start()
96
  return streamer
97
 
98
- # --- Avatars & Messages ---
99
  USER_AVATAR = "https://raw.githubusercontent.com/achilela/vila_fofoka_analysis/9904d9a0d445ab0488cf7395cb863cce7621d897/USER_AVATAR.png"
100
  BOT_AVATAR = "https://raw.githubusercontent.com/achilela/vila_fofoka_analysis/991f4c6e4e1dc7a8e24876ca5aae5228bcdb4dba/Ataliba_Avatar.jpg"
101
 
 
102
  if "messages" not in st.session_state:
103
  st.session_state.messages = []
104
 
 
105
  for msg in st.session_state.messages:
106
- avatar = USER_AVATAR if msg["role"] == "user" else BOT_AVATAR
107
- with st.chat_message(msg["role"], avatar=avatar):
108
  st.markdown(msg["content"])
109
 
110
- # --- Chat UI ---
111
  if prompt := st.chat_input("Ask something based on uploaded documents..."):
112
  st.chat_message("user", avatar=USER_AVATAR).markdown(prompt)
113
  st.session_state.messages.append({"role": "user", "content": prompt})
114
 
115
  context = ""
 
116
  if retriever:
117
  docs = retriever.similarity_search(prompt, k=3)
118
- context = "\n\n".join([d.page_content for d in docs])
119
 
120
- full_prompt = build_prompt(st.session_state.messages, context=context)
 
 
121
 
122
  with st.chat_message("assistant", avatar=BOT_AVATAR):
123
- start_time = time.time()
124
- streamer = generate_response(full_prompt)
125
  container = st.empty()
126
  answer = ""
127
- for chunk in streamer:
 
128
  answer += chunk
129
  container.markdown(answer + "β–Œ", unsafe_allow_html=True)
130
  container.markdown(answer)
131
- st.session_state.messages.append({"role": "assistant", "content": answer})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  from langchain.vectorstores import FAISS
11
  from langchain.schema import Document
12
 
13
+ # --- Hugging Face Token ---
14
  HF_TOKEN = st.secrets["HF_TOKEN"]
15
 
16
  # --- Page Config ---
17
  st.set_page_config(page_title="DigiTwin RAG", page_icon="πŸ“‚", layout="centered")
18
  st.title("πŸ“‚ DigiTs the Twin")
19
 
20
+ # --- File Upload UI ---
21
  with st.sidebar:
22
  st.header("πŸ“„ Upload Knowledge Files")
23
  uploaded_files = st.file_uploader("Upload PDFs or .txt files", accept_multiple_files=True, type=["pdf", "txt"])
24
  if uploaded_files:
25
  st.success(f"{len(uploaded_files)} file(s) uploaded")
26
 
27
+ # --- Load Model & Tokenizer ---
28
  @st.cache_resource
29
  def load_model():
30
  tokenizer = AutoTokenizer.from_pretrained("amiguel/GM_Qwen1.8B_Finetune", trust_remote_code=True, token=HF_TOKEN)
 
39
 
40
  model, tokenizer = load_model()
41
 
42
+ # --- System Prompt ---
43
  SYSTEM_PROMPT = (
44
  "You are DigiTwin, a digital expert and senior topside engineer specializing in inspection and maintenance "
45
  "of offshore piping systems, structural elements, mechanical equipment, floating production units, pressure vessels "
 
48
  "field experience, industry regulations, and proven methodologies in asset integrity and reliability engineering."
49
  )
50
 
51
+ # --- Prompt Builder ---
52
  def build_prompt(messages, context=""):
53
  prompt = f"<|im_start|>system\n{SYSTEM_PROMPT}\n\nContext:\n{context}<|im_end|>\n"
54
  for msg in messages:
 
57
  prompt += "<|im_start|>assistant\n"
58
  return prompt
59
 
60
+ # --- Embed Uploaded Documents ---
 
61
  @st.cache_resource
62
  def embed_uploaded_files(files):
63
  raw_docs = []
64
  for f in files:
65
+ path = f"/tmp/{f.name}"
66
+ with open(path, "wb") as out_file:
67
  out_file.write(f.read())
68
+ loader = PyPDFLoader(path) if f.name.endswith(".pdf") else TextLoader(path)
 
69
  raw_docs.extend(loader.load())
70
 
71
  splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=64)
 
76
 
77
  retriever = embed_uploaded_files(uploaded_files) if uploaded_files else None
78
 
79
+ # --- Streaming Generator ---
80
  def generate_response(prompt_text):
81
  streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
82
  inputs = tokenizer(prompt_text, return_tensors="pt").to(model.device)
 
93
  thread.start()
94
  return streamer
95
 
96
+ # --- Avatars ---
97
  USER_AVATAR = "https://raw.githubusercontent.com/achilela/vila_fofoka_analysis/9904d9a0d445ab0488cf7395cb863cce7621d897/USER_AVATAR.png"
98
  BOT_AVATAR = "https://raw.githubusercontent.com/achilela/vila_fofoka_analysis/991f4c6e4e1dc7a8e24876ca5aae5228bcdb4dba/Ataliba_Avatar.jpg"
99
 
100
+ # --- Initialize Chat Memory ---
101
  if "messages" not in st.session_state:
102
  st.session_state.messages = []
103
 
104
+ # --- Display Message History ---
105
  for msg in st.session_state.messages:
106
+ with st.chat_message(msg["role"], avatar=USER_AVATAR if msg["role"] == "user" else BOT_AVATAR):
 
107
  st.markdown(msg["content"])
108
 
109
+ # --- Chat Interface ---
110
  if prompt := st.chat_input("Ask something based on uploaded documents..."):
111
  st.chat_message("user", avatar=USER_AVATAR).markdown(prompt)
112
  st.session_state.messages.append({"role": "user", "content": prompt})
113
 
114
  context = ""
115
+ docs = []
116
  if retriever:
117
  docs = retriever.similarity_search(prompt, k=3)
118
+ context = "\n\n".join([doc.page_content for doc in docs])
119
 
120
+ # Limit to last 6 messages for memory
121
+ recent_messages = st.session_state.messages[-6:]
122
+ full_prompt = build_prompt(recent_messages, context)
123
 
124
  with st.chat_message("assistant", avatar=BOT_AVATAR):
125
+ start = time.time()
 
126
  container = st.empty()
127
  answer = ""
128
+
129
+ for chunk in generate_response(full_prompt):
130
  answer += chunk
131
  container.markdown(answer + "β–Œ", unsafe_allow_html=True)
132
  container.markdown(answer)
133
+
134
+ end = time.time()
135
+ st.session_state.messages.append({"role": "assistant", "content": answer})
136
+
137
+ input_tokens = len(tokenizer(full_prompt)["input_ids"])
138
+ output_tokens = len(tokenizer(answer)["input_ids"])
139
+ speed = output_tokens / (end - start)
140
+
141
+ with st.expander("πŸ“Š Debug Info"):
142
+ st.caption(
143
+ f"πŸ”‘ Input Tokens: {input_tokens} | Output Tokens: {output_tokens} | "
144
+ f"πŸ•’ Speed: {speed:.1f} tokens/sec"
145
+ )
146
+ for i, doc in enumerate(docs):
147
+ st.markdown(f"**Chunk #{i+1}**")
148
+ st.code(doc.page_content.strip()[:500])