С ростом популярности модели deepseek-r1:1.5b опасения по поводу конфиденциальности облачных решений становятся как никогда актуальными. Этот проект делает еще один шаг вперед, демонстрируя, как построить продвинутую систему RAG локально, используя DeepSeek, LangChain и Streamlit. Используя мощные возможности DeepSeek, эта система гарантирует, что ваши личные данные останутся на вашем компьютере, обеспечивая повышенную конфиденциальность и контроль.
Чатбот предоставляет ответы с учетом контекста, включая содержимое документов и историю разговора, а возможность показать или скрыть обоснование ответов моделей DeepSeek добавляет уровень прозрачности, делая работу в целом более безопасной и надежной. Локальный запуск DeepSeek с помощью Ollama не только позволяет обойти проблемы облачного хранения данных, но и позволяет обеспечить более безопасное и конфиденциальное взаимодействие с пользователем.
Давайте рассмотрим, как создать этот безопасный, контекстно-ориентированный и ориентированный на конфиденциальность RAG-чатбот на вашем компьютере.
Github Repo: Полный код этого проекта доступен на GitHub. Читайте далее, чтобы разобраться в реализации проекта шаг за шагом.
Необходимые условия
Python 3.10 или новее
Установите Python с сайта python.org. Для совместимости со всеми библиотеками рекомендуется использовать Python 3.10 или новее.
Необходимые библиотеки
Установите необходимые библиотеки, используя команду:
pip install -r requirements.txt
Для работы DeepSeek требуется установить Ollama
Инструкция по установке для Ollama и deepseek-r1:1.5b
Скачайте Ollama
Перейдите на сайт Ollama, чтобы загрузить ее на свой компьютер.
Распакуйте Zip-файл
Распакуйте загруженный zip-файл и найдите исполняемый файл Ollama.
Запустите Ollama
После установки Ollama появится на панели задач, что указывает на то, что она работает через HTTP-порт 11434. Зайдите на сайт http://localhost:11434/, чтобы убедиться, что она работает.
Запустите модель deepseek-r1:1.5b
Откройте командную строку и выполните команду:
ollama run deepseek-r1:1.5b
Описание кода
В этом разделе мы разберем код нашего чатбота RAG на основе PDF-файлов с использованием DeepSeek и Ollama, интегрированного со Streamlit для создания удобного пользовательского интерфейса. Давайте рассмотрим функциональность шаг за шагом:
1. Импорт и начальная настройка
import streamlit as st
from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.embeddings import HuggingFaceEmbeddings
from langchain_ollama import OllamaLLM
import os
import re
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.chat_history import BaseChatMessageHistory
from langchain.chains import create_history_aware_retriever
Начнем с импорта необходимых библиотек. Ключевыми из них являются streamlit
для пользовательского интерфейса, langchain
для загрузки, разделения и встраивания документов, а также OllamaLLM
для использования локально запускаемой модели DeepSeek.
Инициализация состояния сессии
# Initialize session state for chat history
if "messages" not in st.session_state:
st.session_state.messages = []
Здесь мы инициализируем session_state
для хранения истории чата, чтобы обеспечить сохранение диалога между взаимодействиями пользователей.
2. Обработка PDF
def process_pdf(pdf_path):
st.info("Processing PDF... ⏳")
loader = PyPDFLoader(pdf_path)
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=256)
split_docs = text_splitter.split_documents(docs)
embedding_model = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
vectorstore = FAISS.from_documents(split_docs, embedding_model)
return vectorstore
Функция process_pdf
выполняет основную задачу по обработке загруженного PDF-файла:
Загрузка PDF. PyPDFLoader считывает PDF-файл.
Разбивка текста. Текст разбивается на более мелкие фрагменты с помощью RecursiveCharacterTextSplitter для эффективной обработки.
Встраивание и хранение векторов. Мы используем модель HuggingFaceEmbeddings для встраивания фрагментов текста и хранения их в индексе FAISS, что позволяет быстро находить их при запросах.
3. Создание цепочки разговоров
def get_conversation_chain(retriever):
llm = OllamaLLM(model=llm_model)
contextualize_q_system_prompt = (
"Given the chat history and the latest user question, "
"provide a response that directly addresses the user's query based on the provided documents. "
"Do not rephrase the question or ask follow-up questions."
)
contextualize_q_prompt = ChatPromptTemplate.from_messages(
[
("system", contextualize_q_system_prompt),
MessagesPlaceholder("chat_history"),
("human", "{input}"),
]
)
history_aware_retriever = create_history_aware_retriever(
llm, retriever, contextualize_q_prompt
)
system_prompt = (
"As a personal chat assistant, provide accurate and relevant information based on the provided documents. "
"Limit answers to 2-3 sentences and 50 words max. "
"Do not form standalone questions, suggest selections, or ask further questions."
"\n\nContext:\n{context}"
)
qa_prompt = ChatPromptTemplate.from_messages(
[
("system", system_prompt),
MessagesPlaceholder("chat_history"),
("human", "{input}"),
]
)
question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
rag_chain = create_retrieval_chain(history_aware_retriever, question_answer_chain)
store = {}
def get_session_history(session_id: str) -> BaseChatMessageHistory:
if session_id not in store:
store[session_id] = ChatMessageHistory()
return store[session_id]
conversational_rag_chain = RunnableWithMessageHistory(
rag_chain,
get_session_history,
input_messages_key="input",
history_messages_key="chat_history",
output_messages_key="answer",
)
print("Conversational chain created ✅")
return conversational_rag_chain
Эта функция создает цепочку генерации, дополненную извлечением (RAG), с возможностями учета истории:
Извлечение контекста.
History_aware_retriever
гарантирует, что чатбот учтет всю историю разговора для получения контекста.Системные запросы.
contextualize_q_system_prompt
иsystem_prompt
предоставляют чатботу инструкции для кратких и релевантных ответов.Управление историей.
get_session_history
помогает отслеживать историю чата, чтобы ответы были контекстными на основе прошлых сообщений.
Обработка тегов рассуждения
def extract_think_content(text):
match = re.search(r'<think>(.*?)</think>', text, flags=re.DOTALL)
return match.group(1).strip() if match else ""
Эта функция извлекает рассуждения, содержащиеся в тегах <think>
в выходных данных модели. Это гарантирует, что рассуждения чатбота могут быть показаны при желании.
Приведенная выше функция удаляет из окончательного ответа все рассуждения внутри тегов <think>
, оставляя только очищенный ответ.
4. Пользовательский интерфейс Streamlit
st.set_page_config(page_title="Chat with Documents", layout="wide")
st.title("📄 Chat with Your PDF using RAG 💬")
st.sidebar.header("Upload Your PDF")
uploaded_file = st.sidebar.file_uploader("Choose a PDF file", type=["pdf"])
if uploaded_file:
pdf_path = os.path.join("uploads", uploaded_file.name)
os.makedirs("uploads", exist_ok=True)
with open(pdf_path, "wb") as f:
f.write(uploaded_file.getbuffer())
vectorstore = process_pdf(pdf_path)
retriever = vectorstore.as_retriever()
st.session_state.chatbot = get_conversation_chain(retriever)
st.success("PDF uploaded and processed! ✅ Start asking questions below.")
Интерфейс Streamlit
позволяет пользователям загружать PDF-файлы, обрабатывать их и создавать векторное хранилище для запросов. После загрузки файла он обрабатывается, сохраняется локально в папке uploads
, и чатбот готов к взаимодействию.
5. Интерфейс чата и обработка ответов
show_think_content = st.sidebar.checkbox("Show Reasoning")
st.subheader("Chat with the PDF 🤖")
if st.session_state.messages:
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.write(message["content"])
if prompt := st.chat_input("Ask a question about your document"):
st.session_state.messages.append({"role": "user", "content": prompt})
try:
response = st.session_state.chatbot.invoke(
{"input": prompt, "chat_history": st.session_state.messages},
{"configurable": {"session_id": "user_session"}}
)
answer = response["answer"]
think_content = extract_think_content(answer)
answer = remove_think_content(answer)
if "I could not find relevant information" in answer:
st.warning("⚠️ No relevant information found in the uploaded PDF.")
except Exception as e:
answer = f"An error occurred: {e}"
think_content = ""
st.session_state.messages.append({"role": "assistant", "content": answer})
with st.chat_message("user"):
st.write(prompt)
with st.chat_message("assistant"):
st.write(answer)
if show_think_content and think_content:
with st.expander("🤔 Show/Hide Reasoning"):
st.write(think_content)
Интерфейс чата позволяет пользователям взаимодействовать с чатботом:
Отображение сообщений. Предыдущие сообщения отображаются с помощью
st.chat_message
.Ввод вопросов. Пользователи могут вводить вопросы, которые добавляются в историю сессии.
Генерация ответа. Чатбот обрабатывает запрос и отвечает на него в соответствии с системой RAG. Он также отображает аргументацию, если пользователь желает просмотреть ее, если функция активирована в чекбоксе.
В этой статье я рассказал о том, как создать локально размещаемый чатбот Retrieval-Augmented Generation (RAG) с помощью модели DeepSeek deepseek-r1:1.5b, LangChain и Streamlit. Используя передовые возможности DeepSeek, можно гарантировать, что ваши личные данные останутся на вашем компьютере, что повышает уровень конфиденциальности и безопасности. Чатбот отвечает с учетом контекста, предоставляя пользователям релевантную информацию на основе загруженного PDF-файла. Кроме того, возможность показать или скрыть «мысли» модели позволяет сделать процесс работы более прозрачным и настраиваемым.
Модель deepseek-r1:1.5b от компании DeepSeek в последнее время привлекает к себе большое внимание. Благодаря открытому исходному коду и расширенным возможностям рассуждений она стала сильным соперником в сфере ИИ, являясь альтернативой другим моделям, таким как модели GPT от OpenAI. Возможность запускать эту модель локально еще больше повышает ее привлекательность, предоставляя пользователям больший контроль над собственными данными и действиями.
Это приложение является прекрасным началом для создания более сложных систем взаимодействия с документами и может быть легко доработано для поддержки более широкого спектра сценариев использования, от бизнес-отчетов до научных работ. Интегрировав модель DeepSeek deepseek-r1:1.5b в свой локальный чатбот RAG, вы сможете создать сложную систему разговорного ИИ, которая будет уделять первостепенное внимание конфиденциальности пользователей и выдавать точные ответы с учетом контекста.
Друзья, буду рад, если вы подпишетесь на мой телеграм-канал про нейросети, чтобы не пропускать анонсы статей, и про генерацию изображений - я стараюсь делиться только полезной информацией.