0929 作业 使用langchain实现一个Rag #295

Open
opened 2024-10-26 00:24:27 +08:00 by 11389216958cs · 1 comment

基本效果如下:

[2024-10-26 00:16:11] 聊天机器人已启动,输入 exit退出
用户提问:你好啊
[2024-10-26 00:16:22] AI的回答是 你好!有什么我可以帮助你的吗?
用户提问:缘分居网站什么时候上线的
[2024-10-26 00:17:32] AI的回答是 缘份居网站上线于2020年。
用户提问:他的主要功能是什么
[2024-10-26 00:18:08] AI的回答是 缘份居的主要功能包括:"八字精算","八字合婚","未来运势","摇卦占卜","周公解梦","择吉时","紫微排盘","奇门排盘"等。
用户提问:能占卜么
[2024-10-26 00:18:48] AI的回答是 可以,缘份居提供多种占卜功能,包括摇卦占卜、一张牌占卜法、塔罗洗牌、多牌阵占卜法、小六壬占卜等。
用户提问:exit
程序已退出。

代码如下,参考了老师的讲课内容,也参考了 官网 (https://python.langchain.com/v0.1/docs/use_cases/chatbots/retrieval/#document-chains):

from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS, Chroma
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_core.messages import HumanMessage, AIMessage
import datetime

memoryList = []

# 加载线上文档
loader = WebBaseLoader("https://doc.yuanfenju.com/")
data = loader.load()

text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)
all_splits = text_splitter.split_documents(data)

# 文档内容向量化
vectorstore = Chroma.from_documents(documents=all_splits, embedding=OpenAIEmbeddings())

# k is the number of chunks to retrieve
retriever = vectorstore.as_retriever(k=4)


def log(*args):
    # 获取当前时间并格式化为字符串
    current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    # 将所有传入的参数连接成一个字符串
    message = " ".join(map(str, args))
    # 打印时间戳和日志消息
    print(f"[{current_time}] {message}")


def ask(question):
    memoryList.append(HumanMessage(question))

    docs = retriever.invoke(question)

    SYSTEM_TEMPLATE = """
    基于上下文来回答问题,如果上下文中没有提及,你不要瞎扯,直接说“不知道”即可。

    <context>
    {context}
    </context>
    """

    question_answering_prompt = ChatPromptTemplate.from_messages(
        [
            (
                "system",
                SYSTEM_TEMPLATE,
            ),
            MessagesPlaceholder(variable_name="messages"),
        ]
    )
    chat = ChatOpenAI(model="gpt-4o-mini")
    document_chain = create_stuff_documents_chain(chat, question_answering_prompt)
    log("AI正在思考......")
    result = document_chain.invoke(
        {
            "context": docs,
            "messages": memoryList,
        }
    )

    log("AI的回答是", result)
    memoryList.append(AIMessage(result))


if __name__ == "__main__":
    log("聊天机器人已启动,输入 exit退出")
    while True:
        # 接收用户输入
        user_input = input("用户提问:")

        # 检查用户输入是否为 "exit"
        if user_input.lower() == "exit":
            print("程序已退出。")
            break
        ask(user_input)

有一点遗憾,还没找到聊天记录自动管理的解决方案,上面的代码还是用的手动管理。

基本效果如下: ``` [2024-10-26 00:16:11] 聊天机器人已启动,输入 exit退出 用户提问:你好啊 [2024-10-26 00:16:22] AI的回答是 你好!有什么我可以帮助你的吗? 用户提问:缘分居网站什么时候上线的 [2024-10-26 00:17:32] AI的回答是 缘份居网站上线于2020年。 用户提问:他的主要功能是什么 [2024-10-26 00:18:08] AI的回答是 缘份居的主要功能包括:"八字精算","八字合婚","未来运势","摇卦占卜","周公解梦","择吉时","紫微排盘","奇门排盘"等。 用户提问:能占卜么 [2024-10-26 00:18:48] AI的回答是 可以,缘份居提供多种占卜功能,包括摇卦占卜、一张牌占卜法、塔罗洗牌、多牌阵占卜法、小六壬占卜等。 用户提问:exit 程序已退出。 ``` 代码如下,参考了老师的讲课内容,也参考了 官网 (https://python.langchain.com/v0.1/docs/use_cases/chatbots/retrieval/#document-chains): ```python from langchain_community.document_loaders import WebBaseLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_community.vectorstores import FAISS, Chroma from langchain.chains.combine_documents import create_stuff_documents_chain from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_openai import ChatOpenAI, OpenAIEmbeddings from langchain_core.messages import HumanMessage, AIMessage import datetime memoryList = [] # 加载线上文档 loader = WebBaseLoader("https://doc.yuanfenju.com/") data = loader.load() text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0) all_splits = text_splitter.split_documents(data) # 文档内容向量化 vectorstore = Chroma.from_documents(documents=all_splits, embedding=OpenAIEmbeddings()) # k is the number of chunks to retrieve retriever = vectorstore.as_retriever(k=4) def log(*args): # 获取当前时间并格式化为字符串 current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 将所有传入的参数连接成一个字符串 message = " ".join(map(str, args)) # 打印时间戳和日志消息 print(f"[{current_time}] {message}") def ask(question): memoryList.append(HumanMessage(question)) docs = retriever.invoke(question) SYSTEM_TEMPLATE = """ 基于上下文来回答问题,如果上下文中没有提及,你不要瞎扯,直接说“不知道”即可。 <context> {context} </context> """ question_answering_prompt = ChatPromptTemplate.from_messages( [ ( "system", SYSTEM_TEMPLATE, ), MessagesPlaceholder(variable_name="messages"), ] ) chat = ChatOpenAI(model="gpt-4o-mini") document_chain = create_stuff_documents_chain(chat, question_answering_prompt) log("AI正在思考......") result = document_chain.invoke( { "context": docs, "messages": memoryList, } ) log("AI的回答是", result) memoryList.append(AIMessage(result)) if __name__ == "__main__": log("聊天机器人已启动,输入 exit退出") while True: # 接收用户输入 user_input = input("用户提问:") # 检查用户输入是否为 "exit" if user_input.lower() == "exit": print("程序已退出。") break ask(user_input) ``` 有一点遗憾,还没找到聊天记录自动管理的解决方案,上面的代码还是用的手动管理。
Author

另外,我发现,通过LCEL创建的chain,在invoke的时候只能接收字符串形式的参数,而通过 create_stuff_documents_chain 创建的chain,可以接受dict类型的参数,是我的错觉么?

另外,我发现,通过LCEL创建的chain,在invoke的时候只能接收字符串形式的参数,而通过 create_stuff_documents_chain 创建的chain,可以接受dict类型的参数,是我的错觉么?
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: HswOAuth/llm_course#295
No description provided.