Mesop으로 PDF와 채팅하기
Mesop으로 PDF와 채팅하기 (Mistral)
mesop를 사용해 채팅과 PDF 읽기 기능을 갖춘 챗봇을 만드는 기본기를 소개하는 가이드예요. Mistral로 대화 인터페이스를 만들고, PDF에서 텍스트를 추출해 간단한 RAG로 문서와 대화할 수 있게 합니다.
출처: 문서
본문
채팅 인터페이스 (Chat Interface)
먼저 간단한 채팅 인터페이스를 구현합니다. 이를 위해 mesop, mesop.labs, mistralai 라이브러리와 mistralai.models.chat_completion의 ChatMessage가 필요해요.
pip install mesop mistralai
이 데모는 mesop===0.9.3과 mistralai===0.4.0을 사용합니다.
import mesop as me
import mesop.labs as mel
from mistralai.client import MistralClient
from mistralai.models.chat_completion import ChatMessage
Mistral API 키로 MistralClient 인스턴스를 만듭니다.
mistral_api_key = "api_key"
cli = MistralClient(api_key = mistral_api_key)
mesop로 인터페이스를 만들 때는 mel.chat 함수를 이용합니다.
def ask_mistral(message: str, history: list[mel.ChatMessage]):
messages = [ChatMessage(role=m.role, content=m.content) for m in history[:-1]]
for chunk in cli.chat_stream(model = "open-mistral-7b", messages = messages, max_tokens = 1024):
yield chunk.choices[0].delta.content
@me.page(title="Talk to Mistral")
def page():
mel.chat(ask_mistral, title="Ask Mistral", bot_user="Mistral")
이제 mesop chat.py 명령만 실행하면 됩니다!
PDF와 채팅하기 (Chatting with PDFs)
모델이 PDF를 읽게 하려면 내용을 변환·텍스트 추출하고, Mistral의 임베딩 모델을 사용해 문서의 청크를 검색해 모델에 제공해야 해요. 간단한 RAG(Retrieval-Augmented Generation)를 구현하는 셈이죠.
이 작업에는 faiss, PyPDF2와 그 외 라이브러리가 필요합니다.
pip install numpy PyPDF2 faiss
CPU 전용이라면 faiss-cpu를 설치하세요. 이 데모는 numpy===1.26.4, PyPDF2===0.4.0, faiss-cpu===1.8.0을 사용합니다.
import io
import mesop as me
import mesop.labs as mel
from mistralai.client import MistralClient
from mistralai.models.chat_completion import ChatMessage
import numpy as np
import PyPDF2
import faiss
인터페이스에서 파일 업로드를 지원하려면 page 함수에 업로더를 추가해야 해요.
@me.page(title="Talk to Mistral")
def page():
with me.box(style=me.Style(height = "100%", display="flex", flex_direction="column", align_items="center",padding=me.Padding(top = 0, left = 30, right = 30, bottom = 0))):
with me.box(style=me.Style(padding=me.Padding(top = 16), position="fixed")):
me.uploader(
label="Upload PDF",
accepted_file_types=["file/pdf"],
on_upload=handle_upload,
)
with me.box(style=me.Style(width="100%")):
mel.chat(ask_mistral, title="Ask Mistral", bot_user="Mistral")
이제 인터페이스가 파일도 받습니다. 다음 단계는 파일을 처리하고 PDF에서 텍스트를 추출하는 것입니다.
@me.stateclass
class State:
content: str
def handle_upload(event: me.UploadEvent):
state = me.state(State)
reader = PyPDF2.PdfReader(io.BytesIO(event.file.getvalue()))
txt = ""
for page in reader.pages:
txt += page.extract_text()
state.content = txt
PDF를 읽고 RAG를 구현할 준비가 됐어요. PDF들의 관련 텍스트 청크를 단일 문자열로 가져오는 함수가 필요합니다. 이를 위해 Mistral의 임베딩을 사용합니다. 텍스트를 임베딩으로 변환하는 함수를 먼저 만들게요.
def get_text_embedding(input: str):
embeddings_batch_response = cli.embeddings(
model = "mistral-embed",
input = input
)
return embeddings_batch_response.data[0].embedding
이제 모든 RAG를 처리하고 적절한 청크를 검색하는 rag_pdf를 만들 수 있습니다.
def rag_pdf(pdfs: list, question: str) -> str:
chunk_size = 4096
chunks = []
for pdf in pdfs:
chunks += [pdf[i:i + chunk_size] for i in range(0, len(pdf), chunk_size)]
text_embeddings = np.array([get_text_embedding(chunk) for chunk in chunks])
d = text_embeddings.shape[1]
index = faiss.IndexFlatL2(d)
index.add(text_embeddings)
question_embeddings = np.array([get_text_embedding(question)])
D, I = index.search(question_embeddings, k = 4)
retrieved_chunk = [chunks[i] for i in I.tolist()[0]]
text_retrieved = "\n\n".join(retrieved_chunk)
return text_retrieved
이 함수는 PDF 파일을 같은 크기의 청크로 자르고, 임베딩을 얻어 faiss로 벡터 검색해 가장 좋은 4개 청크를 가져옵니다. 마지막 단계는 이를 모델과 통합하는 것이에요.
def ask_mistral(message: str, history: list[mel.ChatMessage]):
messages = [ChatMessage(role=m.role, content=m.content) for m in history[:-1]]
state = me.state(State)
if state.content:
retrieved_text = rag_pdf([state.content], message)
messages[-1] = ChatMessage(role = "user", content = retrieved_text + "\n\n" +messages[-1].content)
for chunk in cli.chat_stream(model = "open-mistral-7b", messages = messages, max_tokens = 1024):
yield chunk.choices[0].delta.content
이제 준비가 끝났어요! mesop chat_with_pdfs.py 명령으로 스크립트를 실행할 수 있습니다.
더 알아보기 (Learn more)
- Mesop 공식 문서 — Google의 Python 웹 UI 프레임워크
mel.chat/me.uploader— Mesop의 채팅·파일 업로드 컴포넌트faiss.IndexFlatL2— 유사도 검색용 FAISS 인덱스- 모델:
open-mistral-7b,mistral-embed