根据你提供的警告信息,langchain 的一些模块和类已经被迁移到 langchain_community 中。为了避免这些警告信息,我们需要更新导入路径。以下是优化后的代码:

import warnings
from langchain_community.document_loaders import TextLoader, PyPDFLoader, Docx2txtLoader
from langchain_community.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Milvus
from langchain_community.embeddings.base import Embeddings
from langchain_community.chains import RetrievalQA
from langchain_community.llms import Ollama
import os
import requests
from email import policy
from email.parser import BytesParser
from email import message_from_bytes
from extract_msg import Message  # 用于解析 .msg 文件


# docker pull milvusdb/milvus:v2.5.7

# 完全禁用所有警告(生产环境慎用)
warnings.filterwarnings("ignore")


# 使用 Ollama 的 nomic-embed-text 生成嵌入
class NomicEmbedText(Embeddings):
    def __init__(self, base_url="http://10.80.0.230:11434"):
        self.base_url = base_url

    def embed_query(self, text):
        response = requests.post(
            f"{self.base_url}/api/embeddings",
            json={"model": "nomic-embed-text:v1.5", "prompt": text}
        )
        if response.status_code != 200:
            raise ValueError(f"嵌入生成失败: {response.text}")
        return response.json()["embedding"]

    def embed_documents(self, texts):
        embeddings = []
        for text in texts:
            embedding = self.embed_query(text)
            embeddings.append(embedding)
        return embeddings


# 自定义 EML 文件加载器
class EMLoader:
    def __init__(self, file_path):
        self.file_path = file_path

    def load(self):
        with open(self.file_path, "rb") as f:
            msg = message_from_bytes(f.read(), policy=policy.default)

        # 提取邮件正文内容
        text = self._extract_email_content(msg)
        return [{"page_content": text, "metadata": {"source": self.file_path}}]

    def _extract_email_content(self, msg):
        """递归提取邮件内容"""
        if msg.is_multipart():
            # 如果是多部分邮件,遍历每个部分
            text = ""
            for part in msg.walk():
                content_type = part.get_content_type()
                if content_type in ["text/plain", "text/html"]:
                    # 提取文本或 HTML 内容
                    text += part.get_payload(decode=True).decode(part.get_content_charset() or "utf-8", errors="ignore")
            return text
        else:
            # 如果是单部分邮件,直接提取内容
            return msg.get_payload(decode=True).decode(msg.get_content_charset() or "utf-8", errors="ignore")


# 自定义 MSG 文件加载器
class MSGLoader:
    def __init__(self, file_path):
        self.file_path = file_path

    def load(self):
        msg = Message(self.file_path)
        text = msg.body
        return [{"page_content": text, "metadata": {"source": self.file_path}}]


# 加载并分割文档
def load_and_split_documents(file_path):
    # 检查文件路径是否有效
    if not file_path:
        raise ValueError("文件路径不能为空")
    if not os.path.isfile(file_path):
        raise FileNotFoundError(f"文件不存在: {file_path}")

    print(f"加载文件: {file_path}")
    if file_path.endswith('.pdf'):
        print("使用 PyPDFLoader")
        loader = PyPDFLoader(file_path)
    elif file_path.endswith('.docx'):
        print("使用 Docx2txtLoader")
        loader = Docx2txtLoader(file_path)
    elif file_path.endswith('.txt'):
        print("使用 TextLoader")
        loader = TextLoader(file_path)
    elif file_path.endswith('.eml'):
        print("使用 EMLoader")
        loader = EMLoader(file_path)
    elif file_path.endswith('.msg'):
        print("使用 MSGLoader")
        loader = MSGLoader(file_path)
    else:
        raise ValueError("不支持的文件格式")

    # 加载文档
    documents = loader.load()
    print(f"加载了 {len(documents)} 个文档块")

    # 文档分块
    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=500,  # 每块 500 字符
        chunk_overlap=50  # 块之间重叠 50 字符
    )
    chunks = text_splitter.split_documents(documents)
    print(f"分块后得到 {len(chunks)} 个块")
    return chunks


def create_milvus_vector_store(chunks, collection_name, file_doc_id, file_path):
    embeddings = NomicEmbedText()
    texts = [chunk.page_content for chunk in chunks]
    metadatas = [{"doc_id": file_doc_id, "file_path": file_path} for _ in range(len(texts))]

    # 连接 Milvus
    vector_store = Milvus.from_texts(
        texts=texts,
        embedding=embeddings,
        metadatas=metadatas,
        collection_name=collection_name,
        connection_args={"host": "10.80.0.230", "port": "19530"}
    )
    return vector_store


# 设置 RAG 管道
def setup_rag_pipeline(vector_store):
    llm = Ollama(model="deepseek-r1:1.5b", base_url="http://10.80.0.230:11434")
    qa_pipeline = RetrievalQA.from_chain_type(
        llm=llm,
        chain_type="stuff",
        retriever=vector_store.as_retriever(search_kwargs={"k": 3})
    )
    return qa_pipeline


def main():
    # file_path = r"C:\Leon\python_project\oceanxecm\2025\04\20250409-ai-演示\pdf\company_law.pdf"
    # file_path = r"C:\Leon\python_project\oceanxecm\2025\04\20250409-ai-演示\word\ISO14001-2015标准的七个实质性变化.docx"

    file_path = r"/root/leon/oceanx-ai/demo-5-ai-demonstration/word/ISO14001-2015标准的七个实质性变化.docx"

    chunks = load_and_split_documents(file_path)
    collection_name = "oceanx_ecm_04091556"
    file_doc_id = 666
    create_milvus_vector_store(chunks, collection_name, file_doc_id, file_path)
    print(f"milvus_nomic_embed_text_rag success.")


if __name__ == "__main__":
    main()

主要改动:

  1. 导入路径更新
    • 将 langchain.document_loaders 替换为 langchain_community.document_loaders
    • 将 langchain.vectorstores 替换为 langchain_community.vectorstores
    • 将 langchain.chains 替换为 langchain_community.chains
    • 将 langchain.llms 替换为 langchain_community.llms

  2. 禁用警告
    • 使用 warnings.filterwarnings("ignore") 来禁用所有警告信息。如果你希望在生产环境中使用,建议谨慎使用此方法,最好是通过更新代码来避免警告。

其他建议:

• 如果你希望更彻底地解决警告问题,可以按照警告提示使用 langchain CLI 工具自动升级导入路径。你可以通过以下命令安装 langchain-cli 并升级代码:

pip install langchain-cli
langchain migrate

这将自动更新你的代码中的导入路径,避免手动修改。

• 确保你已经安装了 langchain_community 包,可以通过以下命令安装:

pip install -U langchain-community
Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐