> 백엔드 개발 > 파이썬 튜토리얼 > 기록 인식 검색기는 어떻게 작동하나요?

기록 인식 검색기는 어떻게 작동하나요?

PHPz
풀어 주다: 2024-09-03 15:33:34
원래의
400명이 탐색했습니다.

How a history-aware retriever works?

이 게시물에서 논의되는 기록 인식 검색기는 LangChain 패키지의 create_history_aware_retriever 함수에 의해 반환되는 것입니다. 이 함수는 생성자에서 다음 입력을 받도록 설계되었습니다.

  • LLM(질의를 받고 답변을 반환하는 언어 모델)
  • 벡터 스토어 검색기(쿼리를 수신하고 관련 문서 목록을 반환하는 모델)
  • 채팅 기록(일반적으로 인간과 AI 간의 메시지 상호 작용 목록).

호출되면 기록 인식 검색기가 사용자 쿼리를 입력으로 받아 관련 문서 목록을 출력합니다. 관련 문서는 채팅 기록에서 제공되는 컨텍스트와 쿼리를 결합하여 작성됩니다.

마지막으로 작업 흐름을 요약하겠습니다.

설정하기

from langchain.chains import create_history_aware_retriever
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_chroma import Chroma
from dotenv import load_dotenv
import bs4

load_dotenv() # To get OPENAI_API_KEY
로그인 후 복사
def create_vectorsore_retriever():
    """
    Returns a vector store retriever based on the text of a specific web page.
    """
    URL = r'https://lilianweng.github.io/posts/2023-06-23-agent/'
    loader = WebBaseLoader(
        web_paths=(URL,),
        bs_kwargs=dict(
            parse_only=bs4.SoupStrainer(class_=("post-content", "post-title", "post-header"))
        ))
    docs = loader.load()
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0, add_start_index=True)
    splits = text_splitter.split_documents(docs)
    vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())
    return vectorstore.as_retriever()
로그인 후 복사
def create_prompt():
    """
    Returns a prompt instructed to produce a rephrased question based on the user's
    last question, but referencing previous messages (chat history).
    """
    system_instruction = """Given a chat history and the latest user question \
        which might reference context in the chat history, formulate a standalone question \
        which can be understood without the chat history. Do NOT answer the question, \
        just reformulate it if needed and otherwise return it as is."""

    prompt = ChatPromptTemplate.from_messages([
        ("system", system_instruction),
        MessagesPlaceholder("chat_history"),
        ("human", "{input}")])
    return prompt
로그인 후 복사
llm = ChatOpenAI(model='gpt-4o-mini')
vectorstore_retriever = create_vectorsore_retriever()
prompt = create_prompt()
로그인 후 복사
history_aware_retriever = create_history_aware_retriever(
    llm,
    vectorstore_retriever,
    prompt
)
로그인 후 복사

그것을 사용하여

여기서는 채팅 기록이 없는 질문이므로 검색자는 마지막 질문과 관련된 문서로만 응답합니다.

chat_history = []

docs = history_aware_retriever.invoke({'input': 'what is planning?', 'chat_history': chat_history})
for i, doc in enumerate(docs):
    print(f'Chunk {i+1}:')
    print(doc.page_content)
    print()
로그인 후 복사
Chunk 1:
Planning is essentially in order to optimize believability at the moment vs in time.
Prompt template: {Intro of an agent X}. Here is X's plan today in broad strokes: 1)
Relationships between agents and observations of one agent by another are all taken into consideration for planning and reacting.
Environment information is present in a tree structure.

Chunk 2:
language. Essentially, the planning step is outsourced to an external tool, assuming the availability of domain-specific PDDL and a suitable planner which is common in certain robotic setups but not in many other domains.

Chunk 3:
Another quite distinct approach, LLM+P (Liu et al. 2023), involves relying on an external classical planner to do long-horizon planning. This approach utilizes the Planning Domain Definition Language (PDDL) as an intermediate interface to describe the planning problem. In this process, LLM (1) translates the problem into “Problem PDDL”, then (2) requests a classical planner to generate a PDDL plan based on an existing “Domain PDDL”, and finally (3) translates the PDDL plan back into natural

Chunk 4:
Planning

Subgoal and decomposition: The agent breaks down large tasks into smaller, manageable subgoals, enabling efficient handling of complex tasks.
Reflection and refinement: The agent can do self-criticism and self-reflection over past actions, learn from mistakes and refine them for future steps, thereby improving the quality of final results.


Memory
로그인 후 복사

이제 리트리버는 채팅 기록을 기반으로 인간이 계획뿐만 아니라 작업 분해에 대해서도 알고 싶어한다는 것을 알고 있습니다. 따라서 두 테마를 모두 참조하는 텍스트 덩어리로 응답합니다.

chat_history = [
    ('human', 'when I ask about planning I want to know about Task Decomposition too.')]

docs = history_aware_retriever.invoke({'input': 'what is planning?', 'chat_history': chat_history})
for i, doc in enumerate(docs):
    print(f'Chunk {i+1}:')
    print(doc.page_content)
    print()
로그인 후 복사
Chunk 1:
Task decomposition can be done (1) by LLM with simple prompting like "Steps for XYZ.\n1.", "What are the subgoals for achieving XYZ?", (2) by using task-specific instructions; e.g. "Write a story outline." for writing a novel, or (3) with human inputs.

Chunk 2:
Fig. 1. Overview of a LLM-powered autonomous agent system.
Component One: Planning#
A complicated task usually involves many steps. An agent needs to know what they are and plan ahead.
Task Decomposition#

Chunk 3:
Planning

Subgoal and decomposition: The agent breaks down large tasks into smaller, manageable subgoals, enabling efficient handling of complex tasks.
Reflection and refinement: The agent can do self-criticism and self-reflection over past actions, learn from mistakes and refine them for future steps, thereby improving the quality of final results.


Memory

Chunk 4:
Challenges in long-term planning and task decomposition: Planning over a lengthy history and effectively exploring the solution space remain challenging. LLMs struggle to adjust plans when faced with unexpected errors, making them less robust compared to humans who learn from trial and error.
로그인 후 복사

이제 모든 질문은 채팅 기록을 기반으로 합니다. 그리고 올바른 개념을 참조하는 텍스트 덩어리로 응답하는 것을 볼 수 있습니다.

chat_history = [
    ('human', 'What is ReAct?'),
    ('ai', 'ReAct integrates reasoning and acting within LLM by extending the action space to be a combination of task-specific discrete actions and the language space')]

docs = history_aware_retriever.invoke({'input': 'It is a way of doing what?', 'chat_history': chat_history})
for i, doc in enumerate(docs):
    print(f'Chunk {i+1}:')
    print(doc.page_content)
    print()
로그인 후 복사
Chunk 1:<br>
ReAct (Yao et al. 2023) integrates reasoning and acting within LLM by extending the action space to be a combination of task-specific discrete actions and the language space. The former enables LLM to interact with the environment (e.g. use Wikipedia search API), while the latter prompting LLM to generate reasoning traces in natural language.<br>
The ReAct prompt template incorporates explicit steps for LLM to think, roughly formatted as:<br>
Thought: ...<br>
Action: ...<br>
Observation: ...

<p>Chunk 2:<br>
Fig. 2.  Examples of reasoning trajectories for knowledge-intensive tasks (e.g. HotpotQA, FEVER) and decision-making tasks (e.g. AlfWorld Env, WebShop). (Image source: Yao et al. 2023).<br>
In both experiments on knowledge-intensive tasks and decision-making tasks, ReAct works better than the Act-only baseline where Thought: … step is removed.</p>

<p>Chunk 3:<br>
The LLM is provided with a list of tool names, descriptions of their utility, and details about the expected input/output.<br>
It is then instructed to answer a user-given prompt using the tools provided when necessary. The instruction suggests the model to follow the ReAct format - Thought, Action, Action Input, Observation.</p>

<p>Chunk 4:<br>
Case Studies#<br>
Scientific Discovery Agent#<br>
ChemCrow (Bran et al. 2023) is a domain-specific example in which LLM is augmented with 13 expert-designed tools to accomplish tasks across organic synthesis, drug discovery, and materials design. The workflow, implemented in LangChain, reflects what was previously described in the ReAct and MRKLs and combines CoT reasoning with tools relevant to the tasks:<br>
</p>
로그인 후 복사




결론

결론적으로, 기록 인식 검색기의 작업 흐름은 .invoke({'input': '...', 'chat_history': '...'}) 호출 시 다음과 같이 작동합니다.

  • 프롬프트의 입력 및 chat_history 자리 표시자를 지정된 값으로 대체하여 기본적으로 "이 채팅 기록과 마지막 입력을 가져와서 마지막 입력을 바꿔보세요"라는 즉시 사용 가능한 새로운 프롬프트를 생성합니다. 채팅내역을 보지 않고도 누구나 이해할 수 있도록 말이죠.
  • 새 프롬프트를 LLM으로 보내고 다시 표현된 입력을 받습니다.
  • 그런 다음 다시 표현된 입력을 벡터 저장소 검색기로 보내고 이 다시 표현된 입력과 관련된 문서 목록을 받습니다.
  • 마지막으로 관련 문서 목록이 반환됩니다.

Obs.: 텍스트를 벡터로 변환하는 데 사용되는 임베딩은 Chroma.from_documents가 호출될 때 지정된 임베딩이라는 점에 유의하는 것이 중요합니다. 아무것도 지정되지 않은 경우(현재의 경우) 기본 크로마 임베딩이 사용됩니다.

위 내용은 기록 인식 검색기는 어떻게 작동하나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿