Kullanacağınız yazılım:
https://github.com/hwchase17/notion-...g.streamlit.io
🔪 Daha iyi içerik bölme için belirli markdown karakterlerini kullanma
🧠 Bota bellek ekleme
💬 Streamlit'i yeni sohbet özellikleriyle ön uç sohbet uygulaması olarak kullanma
📣 Streamlit uygulamasını bir Notion sayfasına gömme
Uygulama ile oynamak için OpenAI Anahtarınızı ekleyin!
Kendi Notion sohbet robotunuzu nasıl oluşturabileceğinizi inceleyelim!
Adım adım öğretici
1. Proje yapısı ve başlatılması
Proje yapısını inceleyerek ve gerekli bağımlılıkları yükleyerek başlayalım. OpenAI API anahtarınızı almayı ve herkese açık bir Notion sayfasını çoğaltmayı (temel olarak kullanmak için) unutmayın.
1.1 Proje yapısı notion-chatbot'un proje yapısı aşağıdakilerden oluşur:- .streamlit/secrets.toml: OpenAI API anahtarınızı saklar.
- faiss_index: tüm vektörleri saklayan bir FAISS dizini (vektör veritabanı).
- notion_content: Markdown dosyalarındaki Notion içeriğini içeren bir klasör.
- .gitignore: OpenAI API anahtarınızı ve Notion içeriğinizi yok sayar.
- app.py: Streamlit sohbet uygulamasının komut dosyası.
- ingest.py: Notion içeriğini vektörlere dönüştürmek ve bunları bir vektör dizininde saklamak için kullanılan komut dosyası.
- utils.py: Konuşma Alma Zinciri oluşturmak için kullanılan komut dosyası.
- requirements.txt: Streamlit Community Cloud'a dağıtmak için gerekli paketleri içeren bir dosya.
Her dosyayı adım adım oluşturacağınız için hepsini aynı anda oluşturmanıza gerek yoktur. Şimdi projeyi başlatalım!
1.2 Projenin başlatılması- Bir proje klasörü oluşturarak başlayınnotion-chatbot
- Yeni bir ortam oluşturun ve gerekli bağımlılıkları yükleyin
pip install streamlit langchain openai tiktoken faiss-cpu
- .gitignoreHangi dosyaların izlenmeyeceğini belirtmek için dosyayı oluşturun
# .gitignore
notion_content/
.streamlit/
- Klasörü oluştur.streamlit
- içinde , OpenAI API anahtarınızı saklayacak .streamlitdosyayı aşağıdaki gibi oluşturun secrets.toml
>>> secrets.toml
OPENAI_API_KEY = 'sk-A1B2C3D4E5F6G7H8I9J'
Notion hesabınız yoksa
buradan oluşturun . Bedava!
Duplicate Notion'unuza kopyalamak için sağ üst köşedeki öğesini seçin
2. Belge alımı
Notion sayfalarınızdaki tüm içeriği sayısal temsillere (vektörlere) dönüştürmek için, metni OpenAI'nin yerleştirme modeli tarafından işlenebilecek daha küçük parçalara bölmek üzere LangChain'i kullanın. Model, metin parçalarını daha sonra bir vektör veritabanında depolayacağınız vektörlere dönüştürecektir.
2.1 Notion içeriğinizi dışa aktarın - Blendle Çalışan El Kitabının ana Notion sayfasına gidin.
- Sağ üst köşedeki üç noktaya tıklayın.
- SeçmekExport
- Markdown and CSVDışa Aktarma Formatı için seçin
- SeçmeInclude subpages
- Dosyayı farklı kaydet notion_content.zip
- Klasörü açın
- Klasörü proje notion_content klasörünüze yerleştirin notion-chatbot
Alıntı
Notion içeriğinizi Notion'un API'sini kullanarak da alabilirsiniz. Basit tutmak için içeriği manuel olarak dışa aktarmanız yeterlidir.
Harika! Artık tüm Notion içeriğini proje klasörünüzün içindeki klasörde .md dosyalar olarak bulundurmalısınız .notion_content notion-chatbot
2.1 Notion içeriğini vektörlere dönüştürme
Notion sayfanızın içeriğini chatbotunuzun bilgi tabanı olarak kullanmak için tüm içeriği vektörlere dönüştürün ve saklayın. Bunu yapmak için bir OpenAI yerleştirme modeli olan LangChain'i ve FAISS'i kullanın.
Favori IDE'nizde proje klasörünüzü açın ve şu adlı yeni bir dosya oluşturun ingest.py:
#ingest.py
import streamlit as st
import openai
from langchain.document_loaders import NotionDirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
# Load OpenAI API key
openai.api_key = st.secrets["OPENAI_API_KEY"]
# Load the Notion content located in the folder 'notion_content'
loader = NotionDirectoryLoader("notion_content")
documents = loader.load()
# Split the Notion content into smaller chunks
markdown_splitter = RecursiveCharacterTextSplitter( separators=["#","##", "###", "\\n\\n","\\n","."], chunk_size=1500, chunk_overlap=100)
docs = markdown_splitter.split_documents(documents)
# Initialize OpenAI embedding model
embeddings = OpenAIEmbeddings()
# Convert all chunks into vectors embeddings using OpenAI embedding model
# Store all vectors in FAISS index and save to local folder 'faiss_index'
db = FAISS.from_documents(docs, embeddings)
db.save_local("faiss_index")
print('Local FAISS index has been successfully saved.')Kodun üzerinden geçelim:
- NET'te depolanan OpenAI API anahtarını yükleyin .streamlit/secrets.toml.
- Klasörde bulunan Notion içeriğini notion_content kullanarak yükleyin NotionDirectoryLoader.
- kullanarak içeriği daha küçük metin parçalarına bölün RecursiveCharacterTextSplitter.
Metni bölmenin farklı yolları vardır.
Notion içeriğiniz, başlıklı ( #H1 için, ##H2 için, ###H3 için) işaretleme dosyalarından oluşur, dolayısıyla bu belirli karakterlere bölünmüştür. Bu, içeriği aynı paragrafın cümleleri arasında değil, paragraflar arasında en iyi yerden bölmenizi sağlar. Başlıklarda bölme yapılamıyorsa \n\n, \n, .cümleleri ayıran karakterlerde bölmeye çalışacaktır.
RecursiveCharacterTextSplittersağladığınız karakter listesinin sırasını takip eder; bu, parçalar yeterince küçük olana kadar listedeki bir sonraki karakteri kullanacağı anlamına gelir.
100'lük örtüşme ile 1500'lük bir yığın boyutu kullanın (farklı değerlerle deneme yapmaktan çekinmeyin):
- OpenAI yerleştirme modelini kullanarak her metin parçasını bir vektöre dönüştürün.
- Tüm vektörleri bir FAISS dizininde saklayın.
Notion içeriğiniz artık vektörlere dönüştürülmüş ve bir vektör veritabanında saklanmışken, onlarla nasıl etkileşim kurabileceğinizi keşfedelim!
3. Sorgu
Kullanıcının sorusuna bir yanıt bulmak için, bunu öncekiyle aynı gömme modelini kullanarak bir vektöre dönüştürün. Bu vektör daha sonra daha önce oluşturulan vektör veri tabanındaki benzer vektörlerle eşleştirilir. Bir yanıt oluşturmak için ilgili metin içeriğini kullanıcının sorusuyla birlikte OpenAI GPT'ye iletin.
Sohbet deneyimini geliştirmek için önceki mesajları sohbet geçmişinde saklayarak sohbet robotunuza
bellek ekleyin. Bu, sohbet robotunun konuşma sırasında sohbet geçmişine erişmesine olanak tanır.
3.1 Akış - Başlangıçta bir sohbet geçmişi oluşturulur. Kullanıcı sorular sordukça veya sohbet robotu yanıtlar sağladıkça bu mesajlar sohbet geçmişinde depolanır. Chatbot, konuşma ilerledikçe önceki mesajları takip ediyor ve bu da onun hafızası olarak görev yapıyor.
- Kullanıcı bir soru yazdığında bu soru sohbet geçmişine kaydedilir.
- Soru ve sohbet geçmişi bağımsız bir soru halinde birleştirilir.
- Bağımsız soru, Belge Besleme aşamasındakiyle aynı gömme modeli kullanılarak bir vektöre dönüştürülür.
- Vektör, vektör veritabanına geçer ve bir benzerlik araması (veya vektör araması) gerçekleştirir.
Kısacası, bir dizi vektör (kırmızı) ve sorgu vektörü (kullanıcının mavi sorusu) göz önüne alındığında, kullanıcının sorusuna en benzer öğeleri bulmanız gerekir. Aşağıdaki örnekte, sorgu vektörüne en yakın üç vektörü arayan
k -en yakın komşu aramasını (
k -NN) görebilirsiniz :
- Bulunan en benzer vektörlerle ilgili Notion içeriğini GPT için bağımsız bir soruya bağlayın.
- GPT, bir sistem isteminin yönergelerini temel alarak bir yanıt formüle eder.
- Chatbot, kullanıcıya GPT'den gelen yanıtla yanıt verir.
- Chatbotun cevabını sohbet geçmişine ekleyin.
- Bu işlemi tekrarlayın.
Mantıklı olmak? Güzel! Kodlamaya başlayalım.
3.2 Sorgu
İlk olarak, uygulamanızın beyni olarak hizmet verecek bir
LangChain Konuşmalı Erişim Zinciri oluşturun. Bunu yapmak için, Konuşmaya Dayalı Geri Alma Zinciri döndüren işlevi utils.py
içeren bir dosya oluşturun.
load_chain()
# **utils.py**
import streamlit as st
import openai
from langchain.chains import ConversationalRetrievalChain
from langchain.memory import ConversationBufferWindowMemory
from langchain.chat_models import ChatOpenAI
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from langchain.prompts import PromptTemplate
from langchain.prompts.chat import SystemMessagePromptTemplate
openai.api_key = st.secrets["OPENAI_API_KEY"]
@st.cache_resource
def load_chain():
""" The `load_chain()` function initializes and configures a conversational retrieval chain for answering user questions. :return: The `load_chain()` function returns a ConversationalRetrievalChain object. """
# Load OpenAI embedding model
embeddings = OpenAIEmbeddings()
# Load OpenAI chat model
llm = ChatOpenAI(temperature=0)
# Load our local FAISS index as a retriever
vector_store = FAISS.load_local("faiss_index", embeddings)
retriever = vector_store.as_retriever(search_kwargs={"k": 3})
# Create memory 'chat_history'
memory = ConversationBufferWindowMemory(k=3,memory_key="chat_history")
# Create system prompt
template = """ You are an AI assistant for answering questions about the Blendle Employee Handbook. You are given the following extracted parts of a long document and a question. Provide a conversational answer. If you don't know the answer, just say 'Sorry, I don't know ... 😔. Don't try to make up an answer. If the question is not about the Blendle Employee Handbook, politely inform them that you are tuned to only answer questions about the Blendle Employee Handbook. {context} Question: {question} Helpful Answer:"""
# Create the Conversational Chain
chain = ConversationalRetrievalChain.from_llm(llm=llm, retriever=retriever, memory=memory, get_chat_history=lambda h : h,
verbose=True)
# Add systemp prompt to chain
# Can only add it at the end for ConversationalRetrievalChain
QA_CHAIN_PROMPT = PromptTemplate(input_variables=["context", "question"],template=template)
chain.combine_docs_chain.llm_chain.prompt.messages[0] = SystemMessagePromptTemplate(prompt=QA_CHAIN_PROMPT)
return chainKodu inceleyelim:
- NET'te depolanan OpenAI API anahtarını yükleyin .streamlit/secrets.toml.
- load_chain()Bir döndüren işlevi oluşturun Conversational Retrieval Chain object. st.cache_resourceUygulamanızı daha verimli hale getirmek için kullanıyoruz . Bunu kullanarak, load_chain()işlevi en başta yalnızca bir kez çalıştırırsınız ve sonucu yerel bir önbellekte saklarsınız. Daha sonra herhangi bir değişiklik yapılmadığından yürütme işlemi atlanacaktır. Çok uygun!
- Kullanıcının sorgularını vektörlere dönüştüren OpenAI yerleştirme modelini yükleyin.
- Yanıtları oluşturan OpenAI sohbet modelini yükleyin. Bunu yapmak için bağımsız soruyu (kullanıcının sorusu ile sohbet geçmişini birleştirerek) ve ilgili belgeleri kullanır. Sıcaklığı 0 olarak belirtin; bu, modelin her zaman en yüksek olasılıklı kelimeyi seçeceği anlamına gelir. Daha yüksek bir sıcaklık, modelin biraz daha düşük olasılığa sahip bir kelimeyi seçebileceği anlamına gelir; bu da daha fazla varyasyona, rastgeleliğe ve yaratıcılığa yol açar. Sizin için en iyi neyin işe yaradığını görmek için onunla oynayın.
- Yerel FAISS indeksinizi, zincirin ilgili bilgileri aramak için kullandığı bir alıcı olarak yükleyin. Tanımla k=3vektör veritabanındaki en alakalı üç belgeyi arayın.
- Kullanarak chatbotunuzun hafızasını oluşturun ConversationBufferWindowMemory. Define k=3, yani chatbot, bağımsız soruyu oluştururken son üç etkileşime bakacaktır. Bu, arabelleğin çok fazla büyümemesi için en son etkileşimlerin kayan penceresini tutmak açısından kullanışlıdır.
- Sohbet robotumuz için kılavuz görevi gören sistem istemini oluşturun. Chatbot'un nasıl davranması gerektiğini ve bir yanıt bulamadığında veya kullanıcının sorusu kapsamı dışında olduğunda ne yapması gerektiğini belirtin.
- ConversationalRetrievalChainÖnceki tüm elemanları birbirine bağlayarak zinciri oluşturun . verbose=TrueZinciri çalıştırırken kaputun altında neler olduğunu görmek için ayarlayın . Bu, chatbotun kullanıcının sorularını yanıtlamak için hangi bilgileri kullandığını görmeyi kolaylaştırır.
- Sistem istemini zincire ekleyin. Şu anda, bunu yalnızca kullanırken zinciri tanımladıktan sonra ekleyebileceğiniz görülüyor ConversationalRetrievalChain.from_llm.
4. Chatbot uygulaması
Çevrimiçi olarak dağıtılabilen görsel olarak çekici bir sohbet uygulaması olan chatbot arayüzünü oluşturmak için Streamlit'i kullanın ve uygulamayı Notion sayfanıza ekleyin.
4.1 Streamlit uygulaması
Artık chatbotunuzun beynini oluşturduğunuza göre, hepsini Streamlit uygulamasına koyalım!
# **app.py**
import time
import streamlit as st
from utils import load_chain
# Custom image for the app icon and the assistant's avatar
company_logo = 'https://www.app.nl/wp-content/uploads/2019/01/Blendle.png'
# Configure Streamlit page
st.set_page_config( page_title="Your Notion Chatbot", page_icon=company_logo
)
# Initialize LLM chain
chain = load_chain()
# Initialize chat history
if 'messages' not in st.session_state: # Start with first message from assistant st.session_state['messages'] = [{"role": "assistant", "content": "Hi human! I am Blendle's smart AI. How can I help you today?"}]
# Display chat messages from history on app rerun
# Custom avatar for the assistant, default avatar for user
for message in st.session_state.messages: if message["role"] == 'assistant': with st.chat_message(message["role"], avatar=company_logo): st.markdown(message["content"]) else: with st.chat_message(message["role"]): st.markdown(message["content"])
# Chat logic
if query := st.chat_input("Ask me anything"): # Add user message to chat history st.session_state.messages.append({"role": "user", "content": query}) # Display user message in chat message container with st.chat_message("user"): st.markdown(query)
with st.chat_message("assistant", avatar=company_logo): message_placeholder = st.empty() # Send user's question to our chain result = chain({"question": query}) response = result['answer'] full_response = ""
# Simulate stream of response with milliseconds delay for chunk in response.split(): full_response += chunk + " " time.sleep(0.05) # Add a blinking cursor to simulate typing message_placeholder.markdown(full_response + "▌") message_placeholder.markdown(full_response)
# Add assistant message to chat history st.session_state.messages.append({"role": "assistant", "content": response})Kodu inceleyelim:
- Daha önce oluşturduğumuz Konuşmaya Dayalı Geri Alma Zincirini yüklemek için load_chain()şuradan içe aktarın .utils.py
- Sohbet uygulamasında uygulamanızın sayfa simgesi ve asistanınızın avatarı olarak kullanmak için URL'den bir resim yükleyin.
- Zincirinizi oturum durumunda başlatın.
- Kullanıcıyı karşılayan asistanın ilk mesajıyla sohbet geçmişini oturum durumunda başlatın.
- Asistan için özel bir avatar ve kullanıcı için varsayılan bir avatar belirleyerek sohbet geçmişindeki tüm mesajları görüntüleyin.
- Aşağıdakileri yapmak için sohbet mantığını oluşturun:
- Kullanıcının sorgusunu alın ve sohbet geçmişinde saklayın
- Kullanıcının sorgusunu sohbette görüntüleyin
- Kullanıcının sorgusunu kullanarak zincirinize iletinst.session_state['chain']({"question": query})
- Geri yanıt alın
- Yanıtın görüntülenmesini yavaşlatarak insan yazma hızını simüle ederek yanıtı sohbette görüntüleyin
- Yanıtı sohbet geçmişine kaydedin
4.2 Streamlit Community Cloud'da Dağıtım
Chatbot'unuzu test ettikten ve memnun kaldığınızda artık canlı yayına geçme zamanı!
Streamlit Community Cloud'da dağıtmak için:
requirements.txtGerekli bağımlılıkları depolamak için bir dosya oluşturun
# ****************requirements.txt****************
openai langchain faiss-cpu tiktoken
Uygulamayı dağıtın ve öğesine tıklayın Advanced settings. Buradan Python sürümünüzü ve OpenAI API anahtarınızı belirtin (yerel dosyanızdaki bilgilerle eşleşmelidirler secrets.toml).
4.3 Streamlit uygulamanızı Notion'a yerleştirme
- Uygulamanız dağıtıldıktan sonra URL'sini kopyalayın.
- Notion sayfanıza gidin.
- EmbedBlok seçeneklerinde seçim yaparak uygulamanızı ekleyin .
- Uygulamanızın URL'sini yapıştırın ve simgesine tıklayın Embed link.
- İşte! Yeni Notion sohbet robotunuzu kullanarak içeriğinizle etkileşimde bulunmanın tadını çıkarın!
Tebrikler! 🥳
Bu eğitimde şunları nasıl yapacağınızı öğrendiniz:
- OpenAI yerleştirme modelini kullanarak Notion içeriğinizi vektörlere dönüştürün ve bunları bir FAISS dizininde saklayın
- LangChain'i kullanarak özel bir istem ve bellekle bir Konuşma Alma Zinciri oluşturun
- En yeni sohbet özelliklerini kullanarak bir Streamlit sohbet uygulaması oluşturun ve dağıtın
- Streamlit sohbet uygulamasını Notion sayfanıza yerleştirin