Bootstrap

langchain+rag在线api部署

一直作为java开发工作者,突然被公司安排调研python大模型,一开始我是拒绝的,所以我开始研究java版本的大模型并有了一定的成就,可惜奈何公司认为java的不稳定(java用的是langchain4j,有兴趣的可以私聊我交流),所以开始调研python版本的,走过了很多的弯路,所以在这里记录一下,让大家一起避坑。

直接链接大模型然后用的呢种我就不介绍了,太low了,我直接展示rag版本的大模型。

模型class

class It(LLM):

    def _llm_type(self) -> str:
        """Return type of LLM."""
        return "kimillm"

    def _call(
            self,
            prompt: str,
            **kwargs: Any,
    ) -> str:
        try:
            client = OpenAI(
                api_key="your-api-key",  # 替换为实际的 API 密钥
                base_url="用大模型的url或者自己公司的url",
            )
            completion = client.chat.completions.create(
                model="Qwen/Qwen1.5-72B-Chat",
                messages=[
                    {"role": "system", "content": "你是 IT,由研发中心 AI 提供的人工智能助手。"},
                    {"role": "user", "content": prompt}
                ],
                temperature=0.3,  # 使用直接配置的 temperature
            )
            return completion.choices[0].message.content
        except Exception as e:
            logging.error(f"Error in kimi: {e}", exc_info=True)
            return "对不起,处理请求时发生错误。"

文档读取(简单操作直接用text)

    text = ("4月15号西晴"
            "4月16号西下雨"
            "4月17号西晴"
            "4月19号西下雨"
            "4月20号西晴"
            "4月21号西晴")
    # 分割文档
    text_splitter = CharacterTextSplitter(separator="\n", chunk_size=50, chunk_overlap=10)
    texts = text_splitter.split_text(text)

加载模型

由于langchain默认用的一个外国网站的embeddings,国内最近访问不到了,所以我建议把模型下载到本地。国内有对应的源网站(有需要可以评论)。

    model_path = 'D:/data/all-MiniLM-L6-v2'
    # 加载本地模型
    embeddings = HuggingFaceEmbeddings(model_name=model_path)
    # 向量化
    db = Chroma.from_texts(
        texts, embeddings, persist_directory="D:/data/embedding"
    )

获取文档

    # 获取相关文档
    retriever = db.as_retriever()
    docs = retriever.get_relevant_documents("几号下雨")
    p_info = "".join(doc.page_content for doc in docs)

prompt模板

    prompt_template = """
    你是一个问答机器人。
    你的人物是根据下述给定的信息回答用户问题。
    确保你的回复完全依赖下述已知的信息,不要编造答案。
    如果下述已知信息不足以回答用户的问题,请直接回复“我无法回答您的问题”。


    已知信息:
    {info}


    用户问题:
    {question}


    """
    template = PromptTemplate.from_template(prompt_template)
    prompt = template.format(info=p_info, question="4月中旬西安几号下雨")

初始化并调用LLM

    # 初始化并调用 LLM
    llm = It()
    output = llm._call(prompt)
    print(output)

给出完整代码

import logging
from typing import Any
from langchain.text_splitter import CharacterTextSplitter
from langchain_community.vectorstores.chroma import Chroma
from langchain_huggingface import HuggingFaceEmbeddings
from langchain.prompts import PromptTemplate
from langchain_core.language_models import LLM
from openai import OpenAI

class It(LLM):

    def _llm_type(self) -> str:
        """Return type of LLM."""
        return "kimillm"

    def _call(
            self,
            prompt: str,
            **kwargs: Any,
    ) -> str:
        try:
            client = OpenAI(
                api_key="your-api-key",  # 替换为实际的 API 密钥
                base_url="你用的大模型的url或者公司自己的url",
            )
            completion = client.chat.completions.create(
                model="Qwen/Qwen1.5-72B-Chat",
                messages=[
                    {"role": "system", "content": "你是 IT,由研发中心 AI 提供的人工智能助手。"},
                    {"role": "user", "content": prompt}
                ],
                temperature=0.3,  # 使用直接配置的 temperature
            )
            return completion.choices[0].message.content
        except Exception as e:
            logging.error(f"Error in kimi: {e}", exc_info=True)
            return "对不起,处理请求时发生错误。"

def main():
    # 加载文档
    # loader = TextLoader('D:/data/tianqi.txt')
    # documents = loader.load()

    text = ("4月15号西晴"
            "4月16号西下雨"
            "4月17号西晴"
            "4月19号西下雨"
            "4月20号西晴"
            "4月21号西晴")
    # 分割文档
    text_splitter = CharacterTextSplitter(separator="\n", chunk_size=50, chunk_overlap=10)
    texts = text_splitter.split_text(text)

    model_path = 'D:/data/all-MiniLM-L6-v2'
    # 加载本地模型
    embeddings = HuggingFaceEmbeddings(model_name=model_path)
    # 向量化
    db = Chroma.from_texts(
        texts, embeddings, persist_directory="D:/data/embedding"
    )

    # 获取相关文档
    retriever = db.as_retriever()
    docs = retriever.get_relevant_documents("几号下雨")
    p_info = "".join(doc.page_content for doc in docs)

    # prompt 模板
    prompt_template = """
    你是一个问答机器人。
    你的人物是根据下述给定的信息回答用户问题。
    确保你的回复完全依赖下述已知的信息,不要编造答案。
    如果下述已知信息不足以回答用户的问题,请直接回复“我无法回答您的问题”。


    已知信息:
    {info}


    用户问题:
    {question}


    """
    template = PromptTemplate.from_template(prompt_template)
    prompt = template.format(info=p_info, question="4月中旬西安几号下雨")

    # 初始化并调用 LLM
    llm = It()
    output = llm._call(prompt)
    print(output)

if __name__ == "__main__":
    main()

其中的坑都是血和泪的教训,不过最终还是成功用了rag的检索。

;