Як створити медичного чат-бота на основі книги про медицину?

У цій статті ми розглянемо, як створити медичний чат-бот за допомогою Flask і LangChain, інтегрованого з Pinecone, OpenAI та медичною базою знань, щоб створити інтелектуального асистента, який може отримувати та обробляти інформацію з медичної книги. Розглянемо основні компоненти цієї реалізації.

Налаштування середовища

Перед тим як почати працювати з кодом, важливо чітко зрозуміти інструменти та бібліотеки, які ми будемо використовувати для роботи з медичним чат-ботом.

  1. Flask: Цей легкий веб-фреймворк використовується для створення бекенду чат-бота, який обробляє HTTP-запити.
  2. LangChain і LangGraph: Відкритий фреймворк, який допомагає зв'язувати мовні моделі та зовнішні інструменти, такі як Pinecone (векторна база даних), для виконання більш складних завдань, наприклад, отримання інформації.
  3. Pinecone: Векторна база даних, що використовується для зберігання та запитування великих документів або наборів даних, що є необхідним для отримання медичної інформації.
  4. OpenAI: Для реалізації можливостей обробки природної мови ми будемо використовувати модель GPT-4 від OpenAI для розуміння та генерування відповідей, схожих на людські.

Спочатку потрібно імпортувати необхідні бібліотеки:

from flask import Flask, render_template, request, jsonify  
import os  
from langchain_openai import ChatOpenAI, OpenAIEmbeddings  
from langchain_pinecone import PineconeVectorStore  
from langchain_core.messages import HumanMessage  
from langchain_core.tools import tool  
from langgraph.graph import MessagesState  
from langgraph.prebuilt import ToolNode  
from langgraph.checkpoint.memory import MemorySaver  
from langgraph.graph import StateGraph, END  
from langgraph.prebuilt import tools_condition  
from langchain_core.messages import SystemMessage  
from dotenv import load_dotenv

Далі потрібно налаштувати API-ключі та саму програму:

# Налаштування Flask додатку  
app = Flask(__name__)  

# Змінні середовища  
load_dotenv()  
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")  
os.environ["PINECONE_API_KEY"] = os.getenv("PINECONE_API_KEY")  
os.environ["LANGCHAIN_TRACING_V2"] = "true"  
os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"  
os.environ["LANGCHAIN_API_KEY"] = os.getenv("LANGCHAIN_API_KEY")  
os.environ["LANGCHAIN_PROJECT"] = "Medical Chatbot"

Це робимо окремо: Далі попередньо обробляємо книгу, щоб створити векторні embeddings у Pinecone для подальшого використання.

# Завантажуємо PDF документ  
loader = PyPDFLoader("Book of Medicine.pdf")  
documents = loader.load()  

# Розбиваємо документ на частини  
text_splitter = RecursiveCharacterTextSplitter(chunk_size = 1000, chunk_overlap = 200)  
chunks = text_splitter.split_documents(documents)  

# Налаштовуємо LLM та модель Embedding від OpenAI  
llm = ChatOpenAI()  
embeddings = OpenAIEmbeddings()  

# Налаштовуємо VectorStore  
pc = Pinecone()  
index = pc.create_index(  
 name = "medical-chatbot",  
 dimension = 1536,  
 metric = "cosine",  
 spec = ServerlessSpec(  
 cloud = "aws",  
 region = "us-east-1"  
 )  
)  
vector_store = PineconeVectorStore.from_documents(documents = chunks,  
 embedding = embeddings,  
 index_name = "medical-chatbot")

Після налаштування ключів, створюємо інструмент пошуку за допомогою LangChain. У цій функції ми будемо шукати найбільш релевантні документи в Pinecone на основі запиту користувача.
Функція потім серіалізує отриманий контент, який буде використано як контекст для моделі штучного інтелекту.

@tool(response_format="content_and_artifact")  
def retrieve(query: str):  
 """Отримати інформацію, що стосується запиту."""  
 retrieved_docs = vector_store.similarity_search(query, k=2)  
 serialized = "\n\n".join(  
 (f"Source: {doc.metadata}\n" f"Content: {doc.page_content}") for doc in retrieved_docs  
 )  
 return serialized, retrieved_docs

Далі ми створюємо функцію query або respond на основі оцінки GPT:

def query_or_respond(state: MessagesState):  
 """Генерація виклику інструмента для отримання даних або відповідь."""  
 llm_with_tools = llm.bind_tools([retrieve])  
 response = llm_with_tools.invoke(state["messages"])  
 return {"messages": [response]}

Далі йде функція generate:

def generate(state: MessagesState):  
 """Генерація відповіді"""  
 recent_tool_messages = []  
 for message in reversed(state["messages"]):  
 if message.type == "tool":  
 recent_tool_messages.append(message)  
 else:  
 break  
 tool_messages = recent_tool_messages[::-1]  

 docs_content = "\n\n".join(doc.content for doc in tool_messages)  
 system_message_content = (  
 "Ви — асистент для завдань з відповідями на питання. Використовуйте наступний контекст. "  
 "Якщо не знаєте, скажіть про це. Використовуйте максимум три речення та залишайтеся лаконічними."  
 "\n\n" + docs_content  
 )  
 prompt = [SystemMessage(system_message_content)] + state["messages"]  
 response = llm.invoke(prompt)  
 return {"messages": [response]}

Нарешті, ми компілюємо граф:

graph_builder = StateGraph(MessagesState)  
 graph_builder.add_node(query_or_respond)  
 graph_builder.add_node(tools := ToolNode([retrieve]))  
 graph_builder.add_node(generate)  
 graph_builder.set_entry_point("query_or_respond")  
 graph_builder.add_conditional_edges("query_or_respond", tools_condition, {END: END, "tools": "tools"})  
 graph_builder.add_edge("tools", "generate")  
 graph_builder.add_edge("generate", END)  
 return graph_builder.compile(checkpointer=MemorySaver())

Тепер переходимо до розробки основного додатку.
Я не буду вдаватися в деталі, оскільки у вас буде можливість коригувати це за бажанням:

new_thread_id = str(uuid.uuid4())  
config = {"configurable": {"thread_id": new_thread_id}}  
graph = initialize_graph()  

@app.route("/")  
def index():  
 """Відображення основного інтерфейсу для чат-бота."""  
 return render_template("index.html")  

@app.route("/new_chat", methods=["POST"])  
def new_chat():  
 """Почати новий чат, скидаючи ID потоку."""  
 new_thread_id = str(uuid.uuid4())  
 config["configurable"]["thread_id"] = new_thread_id  
 return jsonify({"message": "Новий чат розпочато", "thread_id": config["configurable"]["thread_id"]})  

@app.route("/chat_input", methods=["POST"])  
def chat_input():  
 """Обробка вводу користувача та генерація відповіді чат-бота."""  
 user_input = request.json.get("message", "")  
 if not user_input:  
 return jsonify({"error": "Ввід не надано."}), 400  

 input_message = HumanMessage(content=user_input)  
 response = []  
 for chunk in graph.stream({"messages": [input_message]}, config):  
 chunk  
 if "generate" in chunk:  
 response.append(chunk["generate"]["messages"][0].content)  
 elif "query_or_respond" in chunk:  
 response.append(chunk["query_or_respond"]["messages"][0].content)  
 return jsonify({"response": response})  

if __name__ == "__main__":  
 app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000)))

Ось HTML код:











Medical Chatbot
Чат-бот навчений за книгою з 3-го видання Gale Encyclopedia of Medicine (3-е видання).
Чат-бот навчений за допомогою RAG (Retrieval-Augmented Generation). Він використовує LLM від OpenAI та моделі вбудовування.
Векторні вбудовування книги зберігаються в Pinecone.
New Chat                Надіслати    
Надсилання вашого повідомлення...

       ```  Це все. Якщо у вас є питання, просто дайте знати в коментарях. Ви можете отримати доступ до реалізації на GitHub та її розгортання на Heroku за посиланням нижче:  Репозиторій на GitHub: [https://github.com/Rob-Christian/Medical-Chatbot](https://github.com/Rob-Christian/Medical-Chatbot)



Перекладено з: [How to build a Medical Chatbot based on a Medicine-based Book?](https://medium.com/@rmcaduyac1_30165/how-to-build-a-medical-chatbot-based-on-a-medicine-based-book-c1acc86e64f0)

Leave a Reply

Your email address will not be published. Required fields are marked *