|
|
import streamlit as st |
|
|
import os |
|
|
import tempfile |
|
|
from dotenv import load_dotenv |
|
|
|
|
|
from langchain_community.vectorstores import FAISS |
|
|
from langchain_community.document_loaders import PyPDFLoader |
|
|
from langchain.text_splitter import RecursiveCharacterTextSplitter |
|
|
from langchain_community.chat_models import ChatOpenAI |
|
|
from langchain_community.embeddings import OpenAIEmbeddings |
|
|
from langchain.chains import ConversationalRetrievalChain |
|
|
from langchain.memory import ConversationBufferMemory |
|
|
|
|
|
|
|
|
load_dotenv() |
|
|
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY") |
|
|
|
|
|
st.set_page_config(page_title="ChatGPT PDF Botu", page_icon="💬", layout="wide") |
|
|
st.markdown( |
|
|
""" |
|
|
<h2 style='text-align: center;'>📄 Customer Service Bot</h2> |
|
|
<p style='text-align: center; color: #888;'>PDF içeriğinden ChatGPT tarzı sohbet ile bilgi alın.</p> |
|
|
""", |
|
|
unsafe_allow_html=True |
|
|
) |
|
|
|
|
|
|
|
|
col1, col2 = st.columns([1, 2]) |
|
|
|
|
|
with col1: |
|
|
st.subheader("📄 PDF Yükle") |
|
|
uploaded_file = st.file_uploader("PDF dosyanızı yükleyin", type="pdf", key="pdf_uploader") |
|
|
|
|
|
if uploaded_file is not None: |
|
|
if "last_uploaded_name" not in st.session_state or uploaded_file.name != st.session_state.last_uploaded_name: |
|
|
with st.spinner("PDF işleniyor..."): |
|
|
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp: |
|
|
tmp.write(uploaded_file.read()) |
|
|
tmp_path = tmp.name |
|
|
|
|
|
loader = PyPDFLoader(tmp_path) |
|
|
documents = loader.load() |
|
|
|
|
|
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50) |
|
|
docs = splitter.split_documents(documents) |
|
|
|
|
|
embedding = OpenAIEmbeddings(model="text-embedding-3-large") |
|
|
vectordb = FAISS.from_documents(docs, embedding) |
|
|
|
|
|
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True) |
|
|
llm = ChatOpenAI(model_name="gpt-4", temperature=0) |
|
|
|
|
|
qa_chain = ConversationalRetrievalChain.from_llm( |
|
|
llm=llm, |
|
|
retriever=vectordb.as_retriever(search_kwargs={"k": 3}), |
|
|
memory=memory |
|
|
) |
|
|
|
|
|
st.session_state.qa_chain = qa_chain |
|
|
st.session_state.chat_history = [] |
|
|
st.session_state.last_uploaded_name = uploaded_file.name |
|
|
|
|
|
st.success("✅ PDF başarıyla işlendi!") |
|
|
|
|
|
with col2: |
|
|
st.subheader("💬 Sohbet Alanı") |
|
|
|
|
|
if "qa_chain" not in st.session_state: |
|
|
st.info("Lütfen sol taraftan bir PDF yükleyin.") |
|
|
else: |
|
|
if "chat_history" not in st.session_state: |
|
|
st.session_state.chat_history = [] |
|
|
|
|
|
|
|
|
chat_placeholder = st.container() |
|
|
with chat_placeholder: |
|
|
for sender, message in st.session_state.chat_history: |
|
|
align = "flex-end" if sender == "🧑💼 Siz" else "flex-start" |
|
|
color = "#DCF8C6" if sender == "🧑💼 Siz" else "#F1F0F0" |
|
|
st.markdown( |
|
|
f""" |
|
|
<div style='display: flex; justify-content: {align};'> |
|
|
<div style='background: {color}; border-radius: 12px; padding: 8px 14px; margin: 6px 0; max-width: 70%;'> |
|
|
<b>{sender}:</b> {message} |
|
|
</div> |
|
|
</div> |
|
|
""", |
|
|
unsafe_allow_html=True |
|
|
) |
|
|
|
|
|
|
|
|
with st.form(key="user_input_form", clear_on_submit=True): |
|
|
user_input = st.text_input("Soru sorun veya yazışmaya devam edin...", key="input_field") |
|
|
submit = st.form_submit_button("Gönder") |
|
|
|
|
|
if submit and user_input: |
|
|
with st.spinner("Yanıtlanıyor..."): |
|
|
response = st.session_state.qa_chain.run(user_input) |
|
|
st.session_state.chat_history.append(("🧑💼 Siz", user_input)) |
|
|
st.session_state.chat_history.append(("🤖 Bot", response)) |
|
|
st.rerun() |
|
|
|