Spaces:
Sleeping
Sleeping
File size: 6,410 Bytes
69f3993 f9c1b83 69f3993 f9c1b83 69f3993 f9c1b83 5355578 69f3993 f9c1b83 0ea06d4 f9c1b83 0ea06d4 f9c1b83 69f3993 f9c1b83 69f3993 f9c1b83 69f3993 f9c1b83 4d16bf0 cb20315 f9c1b83 cb20315 557979f f9c1b83 557979f f9c1b83 4b4084a cb20315 f9c1b83 cb20315 69f3993 f9c1b83 69f3993 f9c1b83 69f3993 4d16bf0 f9c1b83 69f3993 f9c1b83 cb20315 f9c1b83 69f3993 f9c1b83 3573828 f9c1b83 69f3993 f9c1b83 69f3993 f9c1b83 69f3993 cb20315 f9c1b83 69f3993 4d16bf0 69f3993 f9c1b83 69f3993 6f25afa 69f3993 cb20315 69f3993 f9c1b83 69f3993 f9c1b83 69f3993 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
import streamlit as st
import google.generativeai as genai
import os
import torch
import sys
import pysqlite3
from FlagEmbedding import FlagModel
# 將 sqlite3 指向 pysqlite3
sys.modules['sqlite3'] = pysqlite3
import chromadb
if hasattr(torch.classes, '__path__'):
torch.classes.__path__ = []
########################################
# 設定 Google Gemini API & 主要參數
########################################
GEMINI_API_KEY = st.secrets["GEMINI_API_KEY"]
genai.configure(api_key=GEMINI_API_KEY)
########################################
# 建立模型 (Gemini 2.0 Flash)
########################################
geminiModel = genai.GenerativeModel("gemini-2.0-flash")
checkModel = genai.GenerativeModel("gemini-2.0-flash")
########################################
# 判斷是否需要 RAG 查詢
########################################
def need_rag_check(model, user_input):
prompt = f"""
你是一個智慧客服助理,專精於保險專業資訊。
無論使用者是詢問保險方案推薦、投保流程或其他與保險相關的專業問題,只要提到保險相關資訊,就必須查詢保險資料庫來輔助回答。
請根據下面的對話內容,僅輸出 "YES" ,表示需要查詢資料庫;否則輸出 "NO"。
對話內容:{user_input}
"""
resp = model.generate_content(prompt)
return ("YES" in resp.text.upper())
########################################
# 載入 Chuxin Embedding 模型 (快取)
########################################
@st.cache_resource
def load_embedding_model():
return FlagModel(
'chuxin-llm/Chuxin-Embedding',
query_instruction_for_retrieval="为这个句子生成表示以用于检索相关文章:",
use_fp16=True
)
embedding_model = load_embedding_model()
########################################
# 取得向量
########################################
def get_chuxin_embedding(text: str):
return embedding_model.encode([text])[0].tolist()
########################################
# 初始化 ChromaDB
########################################
chroma_client = chromadb.PersistentClient(path="./chroma_db")
collection = chroma_client.get_or_create_collection(name="insurance_database", embedding_function=None)
########################################
# Streamlit 介面配置
########################################
st.title("💬 InsureGPT保險顧問")
st.write("🔍 與 AI 互動,詢問保險相關問題。")
# 自訂背景
st.markdown(
"""
<style>
.stApp {
background: linear-gradient(
rgba(238, 100, 2, 0.5),
rgba(238, 100, 2, 0.5)
), url("https://imgur.com/LvZQr6p.png") no-repeat center center fixed;
background-size: 50%;
background-color: #fdd692;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
</style>
""",
unsafe_allow_html=True
)
########################################
# 建立 Chat Session 狀態
########################################
if "chat" not in st.session_state:
# 初始化對話 (System Prompt)
st.session_state.chat = geminiModel.start_chat(history=[
{
"role": "model",
"parts": [(
"背景設定: 你是一位精通台灣保險法規與保險商品的專業顧問,名字叫做InsureGPT。"
"你可以使用知識庫中儲存的保險內容作為專業知識,回答使用者問題。"
"也能根據使用者提供的個人資訊推薦客製化保險方案。"
"若資訊不足或無法找到答案,請直接說明無法回答。"
"請使用條列式或表格回答問題,以確保清楚易讀。"
"請勿捏造資訊,如無法回答,請提供合理建議。"
"在必要時,示範如何計算並提供適合的保險方案與試算金額。"
)]
}
])
########################################
# 用戶輸入 UI
########################################
user_input = st.text_input("💡 你的問題(例如:什麼是強制險?)", key="user_input")
########################################
# 按鈕事件
########################################
if st.button("送出"):
if user_input.strip():
# 先判斷是否需要 RAG
do_rag = need_rag_check(checkModel, user_input)
if do_rag:
# Embedding + Query
emb = get_chuxin_embedding(user_input)
results = collection.query(query_embeddings=[emb], n_results=10)
if results["documents"]:
retrieved_docs = "\n\n---\n\n".join(results["documents"][0])
else:
retrieved_docs = "無匹配資料"
else:
retrieved_docs = "(模型判定此次提問無需檢索)"
print(retrieved_docs)
# 組合對話
user_message = (
f"你擁有以下與『{user_input}』相關的專業知識:\n\n"
f"{retrieved_docs}\n\n"
f"請回答下列問題:\n"
f"{user_input}"
)
# 發送給 Gemini Chat
chat = st.session_state.chat
response = chat.send_message(user_message)
# 顯示回應
st.markdown(f"### 🤖 InsureGPT 回應:\n{response.text}")
# 更新 chat 狀態
st.session_state.chat = chat
st.session_state.input_value = ""
else:
st.warning("請輸入問題!")
########################################
# 顯示聊天紀錄
########################################
st.subheader("💬 聊天記錄")
for msg in st.session_state.chat.history:
role = "user" if msg.role == "user" else "assistant"
if role == "assistant" and "背景設定" in msg.parts[0].text:
continue
if role == "user":
question_start = msg.parts[0].text.find("問題:\n")
if question_start != -1:
msg_text = msg.parts[0].text[question_start:]
else:
msg_text = msg.parts[0].text
else:
msg_text = msg.parts[0].text
with st.chat_message(role):
st.markdown(msg_text)
|