Как стать автором
Обновить

Взаимодействие с документами с помощью DeepSeek и Ollama: локальный чатбот RAG для диалогов с учетом контекста

Уровень сложностиСредний
Время на прочтение7 мин
Количество просмотров683
Автор оригинала: Vikram Bhat
Революционное взаимодействие с документами с помощью DeepSeek и Ollama: локальный чатбот RAG для диалогов с учетом контекста
Революционное взаимодействие с документами с помощью DeepSeek и Ollama: локальный чатбот RAG для диалогов с учетом контекста

С ростом популярности модели deepseek-r1:1.5b опасения по поводу конфиденциальности облачных решений становятся как никогда актуальными. Этот проект делает еще один шаг вперед, демонстрируя, как построить продвинутую систему RAG локально, используя DeepSeek, LangChain и Streamlit. Используя мощные возможности DeepSeek, эта система гарантирует, что ваши личные данные останутся на вашем компьютере, обеспечивая повышенную конфиденциальность и контроль.

Чатбот предоставляет ответы с учетом контекста, включая содержимое документов и историю разговора, а возможность показать или скрыть обоснование ответов моделей DeepSeek добавляет уровень прозрачности, делая работу в целом более безопасной и надежной. Локальный запуск DeepSeek с помощью Ollama не только позволяет обойти проблемы облачного хранения данных, но и позволяет обеспечить более безопасное и конфиденциальное взаимодействие с пользователем.

Давайте рассмотрим, как создать этот безопасный, контекстно-ориентированный и ориентированный на конфиденциальность RAG-чатбот на вашем компьютере.

Github Repo: Полный код этого проекта доступен на GitHub. Читайте далее, чтобы разобраться в реализации проекта шаг за шагом.


Необходимые условия

  1. Python 3.10 или новее

Установите Python с сайта python.org. Для совместимости со всеми библиотеками рекомендуется использовать Python 3.10 или новее.

  1. Необходимые библиотеки

Установите необходимые библиотеки, используя команду:

pip install -r requirements.txt

  1. Для работы DeepSeek требуется установить Ollama

Инструкция по установке для Ollama и deepseek-r1:1.5b

  1. Скачайте Ollama

Перейдите на сайт Ollama, чтобы загрузить ее на свой компьютер.

  1. Распакуйте Zip-файл

Распакуйте загруженный zip-файл и найдите исполняемый файл Ollama.

  1. Запустите Ollama

После установки Ollama появится на панели задач, что указывает на то, что она работает через HTTP-порт 11434. Зайдите на сайт http://localhost:11434/, чтобы убедиться, что она работает.

  1. Запустите модель 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-файла:

  1. Загрузка PDF. PyPDFLoader считывает PDF-файл.

  2. Разбивка текста. Текст разбивается на более мелкие фрагменты с помощью RecursiveCharacterTextSplitter для эффективной обработки.

  3. Встраивание и хранение векторов. Мы используем модель 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), с возможностями учета истории:

  1. Извлечение контекста. History_aware_retriever гарантирует, что чатбот учтет всю историю разговора для получения контекста.

  2. Системные запросы. contextualize_q_system_prompt и system_prompt предоставляют чатботу инструкции для кратких и релевантных ответов.

  3. Управление историей. 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)

Интерфейс чата позволяет пользователям взаимодействовать с чатботом:

  1. Отображение сообщений. Предыдущие сообщения отображаются с помощью st.chat_message.

  2. Ввод вопросов. Пользователи могут вводить вопросы, которые добавляются в историю сессии.

  3. Генерация ответа. Чатбот обрабатывает запрос и отвечает на него в соответствии с системой 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, вы сможете создать сложную систему разговорного ИИ, которая будет уделять первостепенное внимание конфиденциальности пользователей и выдавать точные ответы с учетом контекста.

Друзья, буду рад, если вы подпишетесь на мой телеграм-канал про нейросети, чтобы не пропускать анонсы статей, и про генерацию изображений - я стараюсь делиться только полезной информацией.

Теги:
Хабы:
-2
Комментарии3

Публикации

Истории

Работа

Data Scientist
63 вакансии

Ближайшие события