adamtobegreat commited on
Commit
782e2c0
·
verified ·
1 Parent(s): d16ab9b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -67
app.py CHANGED
@@ -1,8 +1,7 @@
1
  import os, re, base64
2
  from langchain_core.documents import Document
3
  from langchain_chroma import Chroma
4
- from openai import OpenAI
5
- from langchain.embeddings.base import Embeddings
6
  from langchain_google_genai import ChatGoogleGenerativeAI
7
  import chromadb
8
  import gradio as gr
@@ -18,21 +17,9 @@ except ImportError:
18
 
19
 
20
  # =============================================
21
- # 1️⃣ 自訂 LM Studio Embedding 類別
22
  # =============================================
23
- class LmStudioEmbeddings(Embeddings):
24
- def __init__(self, model_name, url):
25
- self.model_name = model_name
26
- self.client = OpenAI(base_url=url, api_key="lm-studio")
27
-
28
- def embed_query(self, text: str):
29
- res = self.client.embeddings.create(input=text, model=self.model_name)
30
- return res.data[0].embedding
31
-
32
- def embed_documents(self, texts: list[str]):
33
- res = self.client.embeddings.create(input=texts, model=self.model_name)
34
- return [x.embedding for x in res.data]
35
-
36
 
37
  # =============================================
38
  # 2️⃣ 載入 QA 檔案並分類
@@ -65,13 +52,9 @@ for k, v in qa_docs.items():
65
  # =============================================
66
  # 3️⃣ 建立向量資料庫
67
  # =============================================
68
- embedding = LmStudioEmbeddings(
69
- model_name="text-embedding-bge-large-zh-v1.5",
70
- url="http://127.0.0.1:1234/v1"
71
- )
72
  client = chromadb.PersistentClient(path="./chroma_db")
73
-
74
  collection_names = {"證券": "stocks", "期貨": "futures", "複委託": "overseas"}
 
75
  vectordbs = {}
76
  for cat, docs in qa_docs.items():
77
  vectordbs[cat] = Chroma(
@@ -85,7 +68,7 @@ print("✅ 各類別向量資料庫建立完成")
85
 
86
 
87
  # =============================================
88
- # 4️⃣ 初始化 Gemini LLM
89
  # =============================================
90
  API_KEY = os.getenv("GOOGLE_API_KEY")
91
  if not API_KEY:
@@ -132,7 +115,7 @@ def chat_fn(message, history):
132
 
133
 
134
  # =============================================
135
- # 6️⃣ 介面(含飛出動畫 + 純白footer)
136
  # =============================================
137
  logo_path = os.path.join(BASE_DIR, "mega.png")
138
  logo_base64 = ""
@@ -167,22 +150,16 @@ with gr.Blocks(
167
 
168
  /* ====== footer(純白背景) ====== */
169
  #footer {
170
- position: fixed;
171
- bottom: 40px;
172
- left: 0;
173
- width: 100%;
174
- text-align: center;
175
- font-size: 13px;
176
- color: #aaa; /* ✅ 更淡的灰色 */
177
- border-top: 1px solid #ddd; /* ✅ 細灰分隔線 */
178
- padding-top: 8px;
179
- background-color: transparent; /* ✅ 移除反白 */
180
  }
181
  @media (max-width: 768px) {
182
  #footer { position: relative; margin-top: 40px; }
183
  }
184
 
185
- /* ====== LINE 風格輸入區 ====== */
186
  #input-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
187
  #user-input {
188
  flex-grow: 1; border-radius: 20px; border: 1px solid #ccc;
@@ -190,56 +167,40 @@ with gr.Blocks(
190
  box-shadow: inset 0 0 1px rgba(0,0,0,0.05);
191
  }
192
 
193
- /* 🟢 小巧箭頭按鈕(含飛出動畫) */
194
  #send-btn {
195
- background-color: #00b800; border: none; border-radius: 50%;
196
- width: 28px; height: 28px; cursor: pointer;
197
- display: flex; align-items: center; justify-content: center;
 
 
 
 
 
 
198
  transition: background-color 0.2s ease, transform 0.1s ease;
199
- box-shadow: 0 1px 2px rgba(0,0,0,0.1); padding: 0; overflow: hidden;
200
- }
201
- #send-btn svg {
202
- width: 12px; height: 12px; fill: white;
203
- transition: transform 0.25s ease;
204
  }
205
  #send-btn:hover { background-color: #00a000; }
206
- #send-btn:hover svg { transform: rotate(10deg) scale(1.15); }
207
- #send-btn:active { transform: scale(0.9); }
208
- #send-btn:active svg { animation: send-fly 0.5s ease-out; }
209
-
210
- @keyframes send-fly {
211
- 0% { transform: translateX(0) scale(1); opacity: 1; }
212
- 50% { transform: translateX(8px) scale(1.2); opacity: 0; }
213
- 100% { transform: translateX(0) scale(1); opacity: 1; }
214
- }
215
  """
216
  ) as demo:
217
- # 左上角 logo
218
  if logo_base64:
219
- gr.HTML(f"""
220
- <div id="logo-top"><img src="data:image/png;base64,{logo_base64}" alt="logo"></div>
221
- """)
222
 
223
- # 標題區
224
  gr.HTML("""
225
- <div id="main-title-wrapper" style="text-align:center; margin-top:20px;">
226
  <h1 id='main-title'><span>👨‍💼 我是小智&nbsp;&nbsp;您的金融好幫手 🫰</span></h1>
227
  <p id='sub-title' style='margin-top:10px; font-size:14px; color:#666;'>Powered by Gemini & LangChain</p>
228
  </div>
229
  """)
230
 
231
- # 聊天介面
232
  with gr.Row():
233
  with gr.Column(scale=4):
234
  chatbox = gr.Chatbot(label="💬 對話紀錄", type="messages")
235
-
236
  with gr.Row(elem_id="input-row"):
237
  user_input = gr.Textbox(elem_id="user-input", show_label=False, placeholder="輸入訊息...", scale=8)
238
- send_btn = gr.Button(
239
- value="""
240
- <svg viewBox="0 0 24 24"><path d="M3 12l18-9-6 9 6 9z"/></svg>
241
- """, elem_id="send-btn", scale=1
242
- )
243
 
244
  def handle_input(message, history):
245
  if not message.strip():
@@ -272,10 +233,8 @@ with gr.Blocks(
272
  return [], gr.update(value="", placeholder="輸入訊息...")
273
  gr.Button("🧹 整理畫面").click(clear_memory, outputs=[chatbox, user_input])
274
 
275
- # 底部 footer(純白)
276
  gr.HTML("<div id='footer'>© Fintech Assistant — 僅業務使用,非官方授權</div>")
277
 
278
- # 手機鍵盤彈出自動捲動
279
  demo.load(None, None, None, js="""
280
  window.addEventListener('focusin', () => {
281
  document.querySelector('textarea')?.scrollIntoView({ behavior: 'smooth', block: 'center' });
 
1
  import os, re, base64
2
  from langchain_core.documents import Document
3
  from langchain_chroma import Chroma
4
+ from langchain_huggingface import HuggingFaceEmbeddings # ✅ 雲端可直接使用
 
5
  from langchain_google_genai import ChatGoogleGenerativeAI
6
  import chromadb
7
  import gradio as gr
 
17
 
18
 
19
  # =============================================
20
+ # 1️⃣ 使用 Hugging Face 雲端 embedding 模型
21
  # =============================================
22
+ embedding = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5")
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
  # =============================================
25
  # 2️⃣ 載入 QA 檔案並分類
 
52
  # =============================================
53
  # 3️⃣ 建立向量資料庫
54
  # =============================================
 
 
 
 
55
  client = chromadb.PersistentClient(path="./chroma_db")
 
56
  collection_names = {"證券": "stocks", "期貨": "futures", "複委託": "overseas"}
57
+
58
  vectordbs = {}
59
  for cat, docs in qa_docs.items():
60
  vectordbs[cat] = Chroma(
 
68
 
69
 
70
  # =============================================
71
+ # 4️⃣ 初始化 Gemini LLM(雲端)
72
  # =============================================
73
  API_KEY = os.getenv("GOOGLE_API_KEY")
74
  if not API_KEY:
 
115
 
116
 
117
  # =============================================
118
+ # 6️⃣ Gradio 介面(LINE風格 + 小輸入按鈕 + 純白footer)
119
  # =============================================
120
  logo_path = os.path.join(BASE_DIR, "mega.png")
121
  logo_base64 = ""
 
150
 
151
  /* ====== footer(純白背景) ====== */
152
  #footer {
153
+ position: fixed; bottom: 40px; left: 0; width: 100%;
154
+ text-align: center; font-size: 13px; color: #aaa;
155
+ border-top: 1px solid #ddd; padding-top: 8px;
156
+ background-color: transparent;
 
 
 
 
 
 
157
  }
158
  @media (max-width: 768px) {
159
  #footer { position: relative; margin-top: 40px; }
160
  }
161
 
162
+ /* ====== LINE風格輸入區 ====== */
163
  #input-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
164
  #user-input {
165
  flex-grow: 1; border-radius: 20px; border: 1px solid #ccc;
 
167
  box-shadow: inset 0 0 1px rgba(0,0,0,0.05);
168
  }
169
 
170
+ /* 🟢 小巧文字版「輸入」按鈕 */
171
  #send-btn {
172
+ background-color: #00b800;
173
+ color: white;
174
+ border: none;
175
+ border-radius: 14px;
176
+ height: 26px;
177
+ padding: 0 10px;
178
+ font-size: 13px;
179
+ font-weight: 600;
180
+ cursor: pointer;
181
  transition: background-color 0.2s ease, transform 0.1s ease;
182
+ box-shadow: 0 1px 2px rgba(0,0,0,0.1);
 
 
 
 
183
  }
184
  #send-btn:hover { background-color: #00a000; }
185
+ #send-btn:active { transform: scale(0.95); }
 
 
 
 
 
 
 
 
186
  """
187
  ) as demo:
 
188
  if logo_base64:
189
+ gr.HTML(f"<div id='logo-top'><img src='data:image/png;base64,{logo_base64}' alt='logo'></div>")
 
 
190
 
 
191
  gr.HTML("""
192
+ <div id='main-title-wrapper' style='text-align:center; margin-top:20px;'>
193
  <h1 id='main-title'><span>👨‍💼 我是小智&nbsp;&nbsp;您的金融好幫手 🫰</span></h1>
194
  <p id='sub-title' style='margin-top:10px; font-size:14px; color:#666;'>Powered by Gemini & LangChain</p>
195
  </div>
196
  """)
197
 
 
198
  with gr.Row():
199
  with gr.Column(scale=4):
200
  chatbox = gr.Chatbot(label="💬 對話紀錄", type="messages")
 
201
  with gr.Row(elem_id="input-row"):
202
  user_input = gr.Textbox(elem_id="user-input", show_label=False, placeholder="輸入訊息...", scale=8)
203
+ send_btn = gr.Button("輸入", elem_id="send-btn", scale=1)
 
 
 
 
204
 
205
  def handle_input(message, history):
206
  if not message.strip():
 
233
  return [], gr.update(value="", placeholder="輸入訊息...")
234
  gr.Button("🧹 整理畫面").click(clear_memory, outputs=[chatbox, user_input])
235
 
 
236
  gr.HTML("<div id='footer'>© Fintech Assistant — 僅業務使用,非官方授權</div>")
237
 
 
238
  demo.load(None, None, None, js="""
239
  window.addEventListener('focusin', () => {
240
  document.querySelector('textarea')?.scrollIntoView({ behavior: 'smooth', block: 'center' });