見出し画像

RAG DAY3 Query Translation

Query Translation

今日はRAGの手法の種類の一つであるQuery Translationを学んでいきます。

Query Translation

Query Translationとは一言でまとめると、入力された質問をそのまま使わずにベクトル検索で使いやすい文章に変換してからベクトル検索するという手法です。

Query Translationにはいろんな方法が考えだされており、例えばRewrite-Retrieve-Readという手法だと、入力をウェブ検索に適した文章に変換します。

例:社長の名前は何ですか→社長 名前

今日はStep back promptingとRewrite-Retrieve-Read の二つのQueryTranslationの手法と複数のクエリ生成するMulti Queryを紹介します。

下準備

Document loadからretriever作成までは前回までと同じです。

from langchain_community.document_loaders import DirectoryLoader
from langchain.text_splitter import MarkdownHeaderTextSplitter,RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain

#Document load
loader = DirectoryLoader("../datasets/company_documents_dataset_1/", glob="**/*.txt",recursive=True)
raw_docs = loader.load()

# Document split
headers_to_split_on = [
    ("#", "Header 1"),
    ("##", "Header 2"),
    ("###", "Header 3"),
]
markdown_splitter = MarkdownHeaderTextSplitter(
    headers_to_split_on=headers_to_split_on, 
    return_each_line=False,
    strip_headers = False 
)
docs = []
for raw_doc in raw_docs:
    source = raw_doc.metadata["source"]
    spilited_docs = markdown_splitter.split_text(raw_doc.page_content)
    for doc in spilited_docs:
        doc.metadata["source"] = source#metadataにsourceを加える
    docs = docs + spilited_docs
markdown_splited_docs = docs
text_splitter = RecursiveCharacterTextSplitter(chunk_size = 300,chunk_overlap=50)
docs = text_splitter.split_documents(docs)

# Embd
vectorstore = Chroma.from_documents(persist_directory="./vecstore/index", documents=docs, embedding=OpenAIEmbeddings())

 #llm llm = ChatOpenAI(model_name="gpt-3.5-turbo",temperature=0)

# retriever
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

Step back prompting

まずは,Step back promptingについて解説していきます。

step back promptingはTake a step backという論文に書かれた手法で、ユーザーの質問をより広い視野(Step back)で捉えた文章に変換してRetrieverに渡す方法です。

例えば、「たとえば○○の誕生日を教えて」という質問に対し、「○○のこれまでの人生を教えて」といったように書き換えます。

具体的なコードは次のようになります。

bfrom langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
from langchain_core.output_parsers import StrOutputParser
from langchain.callbacks.tracers import ConsoleCallbackHandler

# rewrite chain
rewrite_prompt=PromptTemplate.from_template(
"""
次の質問を、広い視野で見た内容に書き換えて下さい。
たとえば"○○さんの誕生日はいつですか?"のような質問の場合は"○○さんのこれまでの人生を教えて下さい"の様にします。

###質問###
{question}

書き換えた質問:
"""
)
llm = ChatOpenAI(model_name="gpt-3.5-turbo",temperature=0)
rewrite_chain = rewrite_prompt|llm|StrOutputParser()

# rag chain
rag_prompt = PromptTemplate(
    input_variables=["context","question"],
    template="""以下の参考用のテキストの一部を参照して、Questionに回答してください。もし参考用のテキストの中に回答に役立つ情報が含まれていなければ、分からない、と答えてください。
{context}
Question: {question}
Answer: """
)
llm = ChatOpenAI(model_name="gpt-3.5-turbo",temperature=0)
rag_chain = (
    {
        "question":RunnablePassthrough(),
        "context":rewrite_chain|retriever #rewirte_chainで生成した文章を使う
    }
    |rag_prompt
    |llm
    |StrOutputParser()
  
)



question = "時間外手当の計算方法は?"
print("【rewrite_chainの動作確認】")
print(rewrite_chain.invoke({"question":question}))
print("")
handler = ConsoleCallbackHandler()
answer = rag_chain.invoke({"question":question},{"callbacks":[handler]})
print("【質問と回答】")
print(f"question:{question},  answer:{answer}")

output

【rewrite_chainの動作確認】
労働時間外の活動や成果について教えてください。

[chain/start] [1:chain:RunnableSequence] Entering Chain run with input:
{
  "question": "時間外手当の計算方法は?"
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context>] Entering Chain run with input:
{
  "question": "時間外手当の計算方法は?"
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 3:chain:RunnablePassthrough] Entering Chain run with input:
{
  "question": "時間外手当の計算方法は?"
}
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 3:chain:RunnablePassthrough] [1ms] Exiting Chain run with output:
{
  "question": "時間外手当の計算方法は?"
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence] Entering Chain run with input:
{
  "question": "時間外手当の計算方法は?"
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 5:prompt:PromptTemplate] Entering Prompt run with input:
{
  "question": "時間外手当の計算方法は?"
}
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 5:prompt:PromptTemplate] [0ms] Exiting Prompt run with output:
{
  "lc": 1,
  "type": "constructor",
  "id": [
    "langchain",
    "prompts",
    "base",
    "StringPromptValue"
  ],
  "kwargs": {
    "text": "\n次の質問を、広い視野で見た内容に書き換えて下さい。\nたとえば\"○○さんの誕生日はいつですか?\"のような質問の場合は\"○○さんのこれまでの人生を教えて下さい\"の様にします。\n\n###質問###\n時間外手当の計算方法は?\n\n書き換えた質問:\n"
  }
}
[llm/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 6:llm:ChatOpenAI] Entering LLM run with input:
{
  "prompts": [
    "Human: \n次の質問を、広い視野で見た内容に書き換えて下さい。\nたとえば\"○○さんの誕生日はいつですか?\"のような質問の場合は\"○○さんのこれまでの人生を教えて下さい\"の様にします。\n\n###質問###\n時間外手当の計算方法は?\n\n書き換えた質問:"
  ]
}
[llm/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 6:llm:ChatOpenAI] [1.22s] Exiting LLM run with output:
{
  "generations": [
    [
      {
        "text": "労働時間外の活動や成果について教えてください。",
        "generation_info": {
          "finish_reason": "stop",
          "logprobs": null
        },
        "type": "ChatGeneration",
        "message": {
          "lc": 1,
          "type": "constructor",
          "id": [
            "langchain",
            "schema",
            "messages",
            "AIMessage"
          ],
          "kwargs": {
            "content": "労働時間外の活動や成果について教えてください。",
            "additional_kwargs": {}
          }
        }
      }
    ]
  ],
  "llm_output": {
    "token_usage": {
      "completion_tokens": 22,
      "prompt_tokens": 124,
      "total_tokens": 146
    },
    "model_name": "gpt-3.5-turbo",
    "system_fingerprint": "fp_69829325d0"
  },
  "run": null
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 7:parser:StrOutputParser] Entering Parser run with input:
[inputs]
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 7:parser:StrOutputParser] [0ms] Exiting Parser run with output:
{
  "output": "労働時間外の活動や成果について教えてください。"
}
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence] [1.59s] Exiting Chain run with output:
[outputs]
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context>] [1.59s] Exiting Chain run with output:
[outputs]
[chain/start] [1:chain:RunnableSequence > 9:prompt:PromptTemplate] Entering Prompt run with input:
[inputs]
[chain/end] [1:chain:RunnableSequence > 9:prompt:PromptTemplate] [0ms] Exiting Prompt run with output:
{
  "lc": 1,
  "type": "constructor",
  "id": [
    "langchain",
    "prompts",
    "base",
    "StringPromptValue"
  ],
  "kwargs": {
    "text": "以下の参考用のテキストの一部を参照して、Questionに回答してください。もし参考用のテキストの中に回答に役立つ情報が含まれていなければ、分からない、と答えてください。\n[Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'})]\nQuestion: {'question': '時間外手当の計算方法は?'}\nAnswer: "
  }
}
[llm/start] [1:chain:RunnableSequence > 10:llm:ChatOpenAI] Entering LLM run with input:
{
  "prompts": [
    "Human: 以下の参考用のテキストの一部を参照して、Questionに回答してください。もし参考用のテキストの中に回答に役立つ情報が含まれていなければ、分からない、と答えてください。\n[Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='## 5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', metadata={'Header 1': '第8条(給与の計算期間・支払日)', 'Header 2': '5. 給与計算期間における時間外労働・休日労働・深夜労働の各時間数の集計については、30分未満は切捨て、30分以上は1時間に切上げます。', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'})]\nQuestion: {'question': '時間外手当の計算方法は?'}\nAnswer:"
  ]
}
[llm/end] [1:chain:RunnableSequence > 10:llm:ChatOpenAI] [2.07s] Exiting LLM run with output:
{
  "generations": [
    [
      {
        "text": "30分未満は切捨て、30分以上は1時間に切上げる方法で計算されます。",
        "generation_info": {
          "finish_reason": "stop",
          "logprobs": null
        },
        "type": "ChatGeneration",
        "message": {
          "lc": 1,
          "type": "constructor",
          "id": [
            "langchain",
            "schema",
            "messages",
            "AIMessage"
          ],
          "kwargs": {
            "content": "30分未満は切捨て、30分以上は1時間に切上げる方法で計算されます。",
            "additional_kwargs": {}
          }
        }
      }
    ]
  ],
  "llm_output": {
    "token_usage": {
      "completion_tokens": 34,
      "prompt_tokens": 2419,
      "total_tokens": 2453
    },
    "model_name": "gpt-3.5-turbo",
    "system_fingerprint": "fp_69829325d0"
  },
  "run": null
}
[chain/start] [1:chain:RunnableSequence > 11:parser:StrOutputParser] Entering Parser run with input:
[inputs]
[chain/end] [1:chain:RunnableSequence > 11:parser:StrOutputParser] [0ms] Exiting Parser run with output:
{
  "output": "30分未満は切捨て、30分以上は1時間に切上げる方法で計算されます。"
}
[chain/end] [1:chain:RunnableSequence] [3.66s] Exiting Chain run with output:
{
  "output": "30分未満は切捨て、30分以上は1時間に切上げる方法で計算されます。"
}
【質問と回答】
question:時間外手当の計算方法は?,  answer:30分未満は切捨て、30分以上は1時間に切上げる方法で計算されます。


処理とoutputについて重要なところを解説していきます。

rewrite_prompt

rewrite_prompt=PromptTemplate.from_template(
"""
次の質問を、広い視野で見た内容に書き換えて下さい。
たとえば"○○さんの誕生日はいつですか?"のような質問の場合は"○○さんのこれまでの人生を教えて下さい"の様にします。

###質問###
{question}

書き換えた質問:
"""
)
llm = ChatOpenAI(model_name="gpt-3.5-turbo",temperature=0)
rewrite_chain = rewrite_prompt|llm|StrOutputParser()

このchainによって、ユーザーの入力を変換します。

例えば、"会社の住所は?"という質問は、"会社の立地や拠点について教えてください。"といった文章にこのchainによって変換されました

このコードを見て分かる通り、変換にgpt-3.5-turboが使われています。


rag_chain

rag_chain = (
    {
        "question":RunnablePassthrough(),
        "context":rewrite_chain|retriever #rewirte_chainで生成した文章を使う
    }
    |rag_prompt
    |llm
    |StrOutputParser()
  
)

rag_chainのcontextに先ほど宣言したrewrite_chain|retrieverが渡されてるのがわかります。

これによって、rewrite_chainで変換された文章がretrieverの検索に使われるようになります。

ConsoleCallbackHandler()

handler = ConsoleCallbackHandler()
answer = rag_chain.invoke({"question":question},{"callbacks":[handler]})

ConsoleCallbackHandlerを使うことによって、角chainの処理を順番に見ることができます。

出力が長くなりますが、簡単に使える上に処理がわかりやすいので非常に便利です。


output解説

まずoutput真ん中の方にある、rewrite_chainの出力で質問が
"時間外手当の計算方法は?"から"労働時間外の活動や成果について教えてください。"に変わっているのがわかります。

[inputs]
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 7:parser:StrOutputParser] [0ms] Exiting Parser run with output:
{
  "output": "労働時間外の活動や成果について教えてください。"
}

しかし、最後に質問と回答を出力していますが、こちらは正しくありません。

【質問と回答】
question:時間外手当の計算方法は?,  answer:30分未満は切捨て、30分以上は1時間に切上げる方法で計算されます。

今回、こちらで作成した社内ドキュメントに対していくつか質問を出してみましたが、step by promptingで精度は良くなる傾向は見られませんでした。

ちゃんと検証はできてないので、文章のチャンク戦略等が悪かった可能性もあります。


Rewrite-Retrieve-Read

次はRewrite-Retrieve-Readについてです。

Rewrite-Retrieve-Readはユーザーの質問をウェブ検索に適した文章に書き換える方法こちらの論文にて紹介されました。

例えば、会社の住所は?という質問は"会社 住所"といったふうに変換されます。

社内ドキュメントをインターネット検索の形式に直すのが、向いてるかはわかりませんが、とりあえず試しにやってみます。

ソースコードはこちらです。

from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
from langchain_core.output_parsers import StrOutputParser
from langchain.callbacks.tracers import ConsoleCallbackHandler


rewrite_prompt=PromptTemplate.from_template(
"""
Provide a better search query for web search engine to answer the given question, \
just 1 answer, no quote, end the each queries with ’**’.
Question: 
{question}
Answer:
"""
)
llm = ChatOpenAI(model_name="gpt-3.5-turbo",temperature=0)
rewrite_chain = rewrite_prompt|llm|StrOutputParser()

# rag chain
rag_prompt = PromptTemplate(
    input_variables=["context","question"],
    template="""以下の参考用のテキストの一部を参照して、Questionに回答してください。もし参考用のテキストの中に回答に役立つ情報が含まれていなければ、分からない、と答えてください。
{context}
Question: {question}
Answer: """
)
llm = ChatOpenAI(model_name="gpt-3.5-turbo",temperature=0)
rag_chain = (
    {
        "question":RunnablePassthrough(),
        "context":rewrite_chain|retriever #rewirte_chainで生成した文章を使う
    }
    |rag_prompt
    |llm
    |StrOutputParser()
  
)


#question = "社長の名前は?"
question = "時間外手当の計算方法は?"

print("【rewrite_chainの動作確認】")
print(rewrite_chain.invoke({"question":question}))
print("")
handler = ConsoleCallbackHandler()
answer = rag_chain.invoke({"question":question},{"callbacks":[handler]})
print("【質問と回答】")
print(f"question:{question},  answer:{answer}")

output

【rewrite_chainの動作確認】
時間外手当 計算方法**

[chain/start] [1:chain:RunnableSequence] Entering Chain run with input:
{
  "question": "時間外手当の計算方法は?"
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context>] Entering Chain run with input:
{
  "question": "時間外手当の計算方法は?"
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 3:chain:RunnablePassthrough] Entering Chain run with input:
{
  "question": "時間外手当の計算方法は?"
}
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 3:chain:RunnablePassthrough] [0ms] Exiting Chain run with output:
{
  "question": "時間外手当の計算方法は?"
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence] Entering Chain run with input:
{
  "question": "時間外手当の計算方法は?"
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 5:prompt:PromptTemplate] Entering Prompt run with input:
{
  "question": "時間外手当の計算方法は?"
}
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 5:prompt:PromptTemplate] [0ms] Exiting Prompt run with output:
{
  "lc": 1,
  "type": "constructor",
  "id": [
    "langchain",
    "prompts",
    "base",
    "StringPromptValue"
  ],
  "kwargs": {
    "text": "\nProvide a better search query for web search engine to answer the given question, just 1 answer, no quote, end the each queries with ’**’.\nQuestion: \n時間外手当の計算方法は?\nAnswer:\n"
  }
}
[llm/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 6:llm:ChatOpenAI] Entering LLM run with input:
{
  "prompts": [
    "Human: \nProvide a better search query for web search engine to answer the given question, just 1 answer, no quote, end the each queries with ’**’.\nQuestion: \n時間外手当の計算方法は?\nAnswer:"
  ]
}
[llm/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 6:llm:ChatOpenAI] [1.33s] Exiting LLM run with output:
{
  "generations": [
    [
      {
        "text": "時間外手当 計算方法**",
        "generation_info": {
          "finish_reason": "stop",
          "logprobs": null
        },
        "type": "ChatGeneration",
        "message": {
          "lc": 1,
          "type": "constructor",
          "id": [
            "langchain",
            "schema",
            "messages",
            "AIMessage"
          ],
          "kwargs": {
            "content": "時間外手当 計算方法**",
            "additional_kwargs": {}
          }
        }
      }
    ]
  ],
  "llm_output": {
    "token_usage": {
      "completion_tokens": 10,
      "prompt_tokens": 55,
      "total_tokens": 65
    },
    "model_name": "gpt-3.5-turbo",
    "system_fingerprint": "fp_69829325d0"
  },
  "run": null
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 7:parser:StrOutputParser] Entering Parser run with input:
[inputs]
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 7:parser:StrOutputParser] [1ms] Exiting Parser run with output:
{
  "output": "時間外手当 計算方法**"
}
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence] [1.75s] Exiting Chain run with output:
[outputs]
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context>] [1.75s] Exiting Chain run with output:
[outputs]
[chain/start] [1:chain:RunnableSequence > 9:prompt:PromptTemplate] Entering Prompt run with input:
[inputs]
[chain/end] [1:chain:RunnableSequence > 9:prompt:PromptTemplate] [1ms] Exiting Prompt run with output:
{
  "lc": 1,
  "type": "constructor",
  "id": [
    "langchain",
    "prompts",
    "base",
    "StringPromptValue"
  ],
  "kwargs": {
    "text": "以下の参考用のテキストの一部を参照して、Questionに回答してください。もし参考用のテキストの中に回答に役立つ情報が含まれていなければ、分からない、と答えてください。\n[Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'})]\nQuestion: {'question': '時間外手当の計算方法は?'}\nAnswer: "
  }
}
[llm/start] [1:chain:RunnableSequence > 10:llm:ChatOpenAI] Entering LLM run with input:
{
  "prompts": [
    "Human: 以下の参考用のテキストの一部を参照して、Questionに回答してください。もし参考用のテキストの中に回答に役立つ情報が含まれていなければ、分からない、と答えてください。\n[Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'}), Document(page_content='# 第6条(時間外手当・休日手当・深夜手当)  \\n## 時間外手当  \\n社員に、所定労働時間を超えて労働をさせたときは、次の計算により時間外手当を支払います。  \\n(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数', metadata={'Header 1': '第6条(時間外手当・休日手当・深夜手当)', 'Header 2': '時間外手当', 'source': '../datasets/company_documents_dataset_1/規定及び規則/給与規則.txt'})]\nQuestion: {'question': '時間外手当の計算方法は?'}\nAnswer:"
  ]
}
[llm/end] [1:chain:RunnableSequence > 10:llm:ChatOpenAI] [2.10s] Exiting LLM run with output:
{
  "generations": [
    [
      {
        "text": "時間外手当の計算方法は、(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数である。",
        "generation_info": {
          "finish_reason": "stop",
          "logprobs": null
        },
        "type": "ChatGeneration",
        "message": {
          "lc": 1,
          "type": "constructor",
          "id": [
            "langchain",
            "schema",
            "messages",
            "AIMessage"
          ],
          "kwargs": {
            "content": "時間外手当の計算方法は、(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数である。",
            "additional_kwargs": {}
          }
        }
      }
    ]
  ],
  "llm_output": {
    "token_usage": {
      "completion_tokens": 50,
      "prompt_tokens": 2089,
      "total_tokens": 2139
    },
    "model_name": "gpt-3.5-turbo",
    "system_fingerprint": "fp_69829325d0"
  },
  "run": null
}
[chain/start] [1:chain:RunnableSequence > 11:parser:StrOutputParser] Entering Parser run with input:
[inputs]
[chain/end] [1:chain:RunnableSequence > 11:parser:StrOutputParser] [0ms] Exiting Parser run with output:
{
  "output": "時間外手当の計算方法は、(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数である。"
}
[chain/end] [1:chain:RunnableSequence] [3.85s] Exiting Chain run with output:
{
  "output": "時間外手当の計算方法は、(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数である。"
}
【質問と回答】
question:時間外手当の計算方法は?,  answer:時間外手当の計算方法は、(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数である。

コードとoutputの解説です。

rewrite_prompt

rewrite_prompt=PromptTemplate.from_template(
"""
Provide a better search query for web search engine to answer the given question, \
just 1 answer, no quote, end the each queries with ’**’.
Question: 
{question}
Answer:
"""
)

まずは、rewrite promptです。

このrewrite_promptは論文にあったものをそのまま流用しています。

このプロンプトによってoutputから質問文が時間外手当 計算方法**に変換されています。


rag_chain

rag_chain = (
    {
        "question":RunnablePassthrough(),
        "context":rewrite_chain|retriever #rewirte_chainで生成した文章を使う
    }
    |rag_prompt
    |llm
    |StrOutputParser()
  
)

step by promptingと同じです。

retrieverにクエリを入れる前にrewrite_chainを入れることで変換をしています。


output

【質問と回答】
question:時間外手当の計算方法は?,  answer:時間外手当の計算方法は、(基本給/1か月の平均所定労働時間数)×1.25×時間外労働時間数である。

今回はちゃんと正解らしきものが出力されていました。


Query expansion(Multi-query retriever)

最後に紹介するのが、Query expansionです。

ユーザーが与えた質問の別のバージョンを いくつか作成し、それを使ってベクトル検索をする手法です。

例えば、会社の住所を教えてという質問は、

"1. 会社の所在地はどこですか?",
"2. 会社の場所を教えてください。",
"3. 会社の住所は何処ですか?",
"4. 会社の位置を知りたいです。",
"5. 会社の所在地を教えていただけますか?"

といった質問に変換され、それら全てを使ってベクトル検索を行います。

ソースコードを見ていきます。
今回は少し複雑なので、順番に見ていきます。

generate_queries

from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.callbacks.tracers import ConsoleCallbackHandler

template = """AI言語モデルアシスタントとして、与えられたユーザーの質問から関連するドキュメントをベクトルデータベースから検索するために、その質問の異なる5つのバージョンを生成することがあなたの任務です。質問に対する複数の視点を生成することで、距離ベースの類似性検索のいくつかの制限を克服するのをユーザーに助けます。
これらの代替質問を改行で区切って提供してください。オリジナルの質問: {question}"""
prompt_perspectives = ChatPromptTemplate.from_template(template)

generate_queries = (
    prompt_perspectives 
    | ChatOpenAI(temperature=0) 
    | StrOutputParser() 
    | (lambda x: x.split("\n"))#改行コードごとにsplitで区切ってリストにする
)

#動作確認
question = "会社の住所を教えて"
handler = ConsoleCallbackHandler()
result = generate_queries.invoke({"question":question},{"callbacks":[handler]})
print("結果:",result)

まずは、クエリを言い換えをした複数の質問に変換するチェーンです。

このチェーンによって、入力された質問は複数のクエリとなります。

最後の(lambda x: x.split("\n")によって次の入力であるlist型に変換されています。

Retrieve

from langchain.load import dumps, loads

def get_unique_union(documents: list[list]):
    """ 重複しているdocumentを削除する """
    flattened_docs = [dumps(doc) for sublist in documents for doc in sublist]
    unique_docs = list(set(flattened_docs))
    return [loads(doc) for doc in unique_docs]

question = "会社の休日はどのように設定されているか教えて"
retrieval_chain = generate_queries | retriever.map() | get_unique_union#retireve.map()にする理由はretrieveはstrしか受け入れられないため。generate_queriesのoutputはlistである。
handler = ConsoleCallbackHandler()
docs = retrieval_chain.invoke({"question":question},{"callbacks":[handler]})
print(docs)

retrieveをするchainです。

このchainでは、複数の質問を使った検索を行っています。

チェーンの最後のget_unique_union関数によって、重複した質問を削除することで、無駄をなくしています。

rag_chain

from operator import itemgetter
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnablePassthrough


# rag chain
rag_prompt = PromptTemplate(
    input_variables=["context","question"],
    template="""以下の参考用のテキストの一部を参照して、Questionに回答してください。もし参考用のテキストの中に回答に役立つ情報が含まれていなければ、分からない、と答えてください。
{context}
Question: {question}
Answer: """
)
llm = ChatOpenAI(model_name="gpt-3.5-turbo",temperature=0)
rag_chain = (
    {
        "question":itemgetter("question"),
        "context":retrieval_chain
    }
    |rag_prompt
    |llm
    |StrOutputParser()
  
)
question = "会社の住所を教えて"
handler = ConsoleCallbackHandler()
rag_chain.invoke({"question":question},{"callbacks":[handler]})

これら全てをまとめたchainです。

outputは次のようになりました。

[chain/start] [1:chain:RunnableSequence] Entering Chain run with input:
{
  "question": "会社の住所を教えて"
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context>] Entering Chain run with input:
{
  "question": "会社の住所を教えて"
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 3:chain:RunnableLambda] Entering Chain run with input:
{
  "question": "会社の住所を教えて"
}
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 3:chain:RunnableLambda] [0ms] Exiting Chain run with output:
{
  "output": "会社の住所を教えて"
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence] Entering Chain run with input:
{
  "question": "会社の住所を教えて"
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 5:prompt:ChatPromptTemplate] Entering Prompt run with input:
{
  "question": "会社の住所を教えて"
}
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 5:prompt:ChatPromptTemplate] [0ms] Exiting Prompt run with output:
{
  "lc": 1,
  "type": "constructor",
  "id": [
    "langchain",
    "prompts",
    "chat",
    "ChatPromptValue"
  ],
  "kwargs": {
    "messages": [
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "messages",
          "HumanMessage"
        ],
        "kwargs": {
          "content": "AI言語モデルアシスタントとして、与えられたユーザーの質問から関連するドキュメントをベクトルデータベースから検索するために、その質問の異なる5つのバージョンを生成することがあなたの任務です。質問に対する複数の視点を生成することで、距離ベースの類似性検索のいくつかの制限を克服するのをユーザーに助けます。\nこれらの代替質問を改行で区切って提供してください。オリジナルの質問: 会社の住所を教えて",
          "additional_kwargs": {}
        }
      }
    ]
  }
}
[llm/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 6:llm:ChatOpenAI] Entering LLM run with input:
{
  "prompts": [
    "Human: AI言語モデルアシスタントとして、与えられたユーザーの質問から関連するドキュメントをベクトルデータベースから検索するために、その質問の異なる5つのバージョンを生成することがあなたの任務です。質問に対する複数の視点を生成することで、距離ベースの類似性検索のいくつかの制限を克服するのをユーザーに助けます。\nこれらの代替質問を改行で区切って提供してください。オリジナルの質問: 会社の住所を教えて"
  ]
}
[llm/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 6:llm:ChatOpenAI] [2.93s] Exiting LLM run with output:
{
  "generations": [
    [
      {
        "text": "- 会社の所在地はどこですか?\n- 会社の場所を教えてください。\n- 会社の住所は何処ですか?\n- 会社の位置を教えてください。\n- 会社の所在地を教えてください。",
        "generation_info": {
          "finish_reason": "stop",
          "logprobs": null
        },
        "type": "ChatGeneration",
        "message": {
          "lc": 1,
          "type": "constructor",
          "id": [
            "langchain",
            "schema",
            "messages",
            "AIMessage"
          ],
          "kwargs": {
            "content": "- 会社の所在地はどこですか?\n- 会社の場所を教えてください。\n- 会社の住所は何処ですか?\n- 会社の位置を教えてください。\n- 会社の所在地を教えてください。",
            "additional_kwargs": {}
          }
        }
      }
    ]
  ],
  "llm_output": {
    "token_usage": {
      "completion_tokens": 71,
      "prompt_tokens": 207,
      "total_tokens": 278
    },
    "model_name": "gpt-3.5-turbo",
    "system_fingerprint": "fp_69829325d0"
  },
  "run": null
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 7:parser:StrOutputParser] Entering Parser run with input:
[inputs]
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 7:parser:StrOutputParser] [0ms] Exiting Parser run with output:
{
  "output": "- 会社の所在地はどこですか?\n- 会社の場所を教えてください。\n- 会社の住所は何処ですか?\n- 会社の位置を教えてください。\n- 会社の所在地を教えてください。"
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 8:chain:RunnableLambda] Entering Chain run with input:
{
  "input": "- 会社の所在地はどこですか?\n- 会社の場所を教えてください。\n- 会社の住所は何処ですか?\n- 会社の位置を教えてください。\n- 会社の所在地を教えてください。"
}
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 8:chain:RunnableLambda] [0ms] Exiting Chain run with output:
{
  "output": [
    "- 会社の所在地はどこですか?",
    "- 会社の場所を教えてください。",
    "- 会社の住所は何処ですか?",
    "- 会社の位置を教えてください。",
    "- 会社の所在地を教えてください。"
  ]
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 9:chain:RunnableEach<VectorStoreRetriever>] Entering Chain run with input:
{
  "input": [
    "- 会社の所在地はどこですか?",
    "- 会社の場所を教えてください。",
    "- 会社の住所は何処ですか?",
    "- 会社の位置を教えてください。",
    "- 会社の所在地を教えてください。"
  ]
}
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 9:chain:RunnableEach<VectorStoreRetriever>] [466ms] Exiting Chain run with output:
{
  "output": [
    [
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 所在地  \n東京都中央区架空町1ー1ー1",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "所在地",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 所在地  \n東京都中央区架空町1ー1ー1",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "所在地",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 所在地  \n東京都中央区架空町1ー1ー1",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "所在地",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 所在地  \n東京都中央区架空町1ー1ー1",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "所在地",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 所在地  \n東京都中央区架空町1ー1ー1",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "所在地",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 所在地  \n東京都中央区架空町1ー1ー1",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "所在地",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 所在地  \n東京都中央区架空町1ー1ー1",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "所在地",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 所在地  \n東京都中央区架空町1ー1ー1",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "所在地",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 所在地  \n東京都中央区架空町1ー1ー1",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "所在地",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      }
    ],
    [
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "## 注意点  \n1. *  \n作業環境の整備:*  \n静かで快適な作業スペースを確保してください。必要な機材や文房具は事前に準備しておきます。  \n2. *  \nセキュリティの確保:*  \n会社から支給されたVPNを通じて業務にアクセスし、個人情報や機密情報の取り扱いには最大限の注意を払ってください。  \n3. *  \n定期的なコミュニケーション:*  \nチームメンバーや上司との定期的な連絡を心がけ、進捗状況や問題点を共有します。",
          "metadata": {
            "Header 1": "リモートワークマニュアル",
            "Header 2": "注意点",
            "source": "../datasets/company_documents_dataset_1/マニュアル/リモートワークガイドライン.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      }
    ],
    [
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      }
    ],
    [
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      }
    ],
    [
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "document",
          "Document"
        ],
        "kwargs": {
          "page_content": "### 従業員数  \n約50名",
          "metadata": {
            "Header 1": "株式会社架空ブラック 会社情報",
            "Header 2": "会社概要",
            "Header 3": "従業員数",
            "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
          }
        }
      }
    ]
  ]
}
[chain/start] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 15:chain:get_unique_union] Entering Chain run with input:
[inputs]
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence > 15:chain:get_unique_union] [2ms] Exiting Chain run with output:
{
  "output": [
    {
      "lc": 1,
      "type": "constructor",
      "id": [
        "langchain",
        "schema",
        "document",
        "Document"
      ],
      "kwargs": {
        "page_content": "## 注意点  \n1. *  \n作業環境の整備:*  \n静かで快適な作業スペースを確保してください。必要な機材や文房具は事前に準備しておきます。  \n2. *  \nセキュリティの確保:*  \n会社から支給されたVPNを通じて業務にアクセスし、個人情報や機密情報の取り扱いには最大限の注意を払ってください。  \n3. *  \n定期的なコミュニケーション:*  \nチームメンバーや上司との定期的な連絡を心がけ、進捗状況や問題点を共有します。",
        "metadata": {
          "Header 1": "リモートワークマニュアル",
          "Header 2": "注意点",
          "source": "../datasets/company_documents_dataset_1/マニュアル/リモートワークガイドライン.txt"
        }
      }
    },
    {
      "lc": 1,
      "type": "constructor",
      "id": [
        "langchain",
        "schema",
        "document",
        "Document"
      ],
      "kwargs": {
        "page_content": "### 従業員数  \n約50名",
        "metadata": {
          "Header 1": "株式会社架空ブラック 会社情報",
          "Header 2": "会社概要",
          "Header 3": "従業員数",
          "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
        }
      }
    },
    {
      "lc": 1,
      "type": "constructor",
      "id": [
        "langchain",
        "schema",
        "document",
        "Document"
      ],
      "kwargs": {
        "page_content": "### 所在地  \n東京都中央区架空町1ー1ー1",
        "metadata": {
          "Header 1": "株式会社架空ブラック 会社情報",
          "Header 2": "会社概要",
          "Header 3": "所在地",
          "source": "../datasets/company_documents_dataset_1/マニュアル/会社情報.txt"
        }
      }
    }
  ]
}
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context> > 4:chain:RunnableSequence] [3.40s] Exiting Chain run with output:
[outputs]
[chain/end] [1:chain:RunnableSequence > 2:chain:RunnableParallel<question,context>] [3.41s] Exiting Chain run with output:
[outputs]
[chain/start] [1:chain:RunnableSequence > 16:prompt:PromptTemplate] Entering Prompt run with input:
[inputs]
[chain/end] [1:chain:RunnableSequence > 16:prompt:PromptTemplate] [0ms] Exiting Prompt run with output:
{
  "lc": 1,
  "type": "constructor",
  "id": [
    "langchain",
    "prompts",
    "base",
    "StringPromptValue"
  ],
  "kwargs": {
    "text": "以下の参考用のテキストの一部を参照して、Questionに回答してください。もし参考用のテキストの中に回答に役立つ情報が含まれていなければ、分からない、と答えてください。\n[Document(page_content='## 注意点  \\n1. *  \\n作業環境の整備:*  \\n静かで快適な作業スペースを確保してください。必要な機材や文房具は事前に準備しておきます。  \\n2. *  \\nセキュリティの確保:*  \\n会社から支給されたVPNを通じて業務にアクセスし、個人情報や機密情報の取り扱いには最大限の注意を払ってください。  \\n3. *  \\n定期的なコミュニケーション:*  \\nチームメンバーや上司との定期的な連絡を心がけ、進捗状況や問題点を共有します。', metadata={'Header 1': 'リモートワークマニュアル', 'Header 2': '注意点', 'source': '../datasets/company_documents_dataset_1/マニュアル/リモートワークガイドライン.txt'}), Document(page_content='### 従業員数  \\n約50名', metadata={'Header 1': '株式会社架空ブラック 会社情報', 'Header 2': '会社概要', 'Header 3': '従業員数', 'source': '../datasets/company_documents_dataset_1/マニュアル/会社情報.txt'}), Document(page_content='### 所在地  \\n東京都中央区架空町1ー1ー1', metadata={'Header 1': '株式会社架空ブラック 会社情報', 'Header 2': '会社概要', 'Header 3': '所在地', 'source': '../datasets/company_documents_dataset_1/マニュアル/会社情報.txt'})]\nQuestion: 会社の住所を教えて\nAnswer: "
  }
}
[llm/start] [1:chain:RunnableSequence > 17:llm:ChatOpenAI] Entering LLM run with input:
{
  "prompts": [
    "Human: 以下の参考用のテキストの一部を参照して、Questionに回答してください。もし参考用のテキストの中に回答に役立つ情報が含まれていなければ、分からない、と答えてください。\n[Document(page_content='## 注意点  \\n1. *  \\n作業環境の整備:*  \\n静かで快適な作業スペースを確保してください。必要な機材や文房具は事前に準備しておきます。  \\n2. *  \\nセキュリティの確保:*  \\n会社から支給されたVPNを通じて業務にアクセスし、個人情報や機密情報の取り扱いには最大限の注意を払ってください。  \\n3. *  \\n定期的なコミュニケーション:*  \\nチームメンバーや上司との定期的な連絡を心がけ、進捗状況や問題点を共有します。', metadata={'Header 1': 'リモートワークマニュアル', 'Header 2': '注意点', 'source': '../datasets/company_documents_dataset_1/マニュアル/リモートワークガイドライン.txt'}), Document(page_content='### 従業員数  \\n約50名', metadata={'Header 1': '株式会社架空ブラック 会社情報', 'Header 2': '会社概要', 'Header 3': '従業員数', 'source': '../datasets/company_documents_dataset_1/マニュアル/会社情報.txt'}), Document(page_content='### 所在地  \\n東京都中央区架空町1ー1ー1', metadata={'Header 1': '株式会社架空ブラック 会社情報', 'Header 2': '会社概要', 'Header 3': '所在地', 'source': '../datasets/company_documents_dataset_1/マニュアル/会社情報.txt'})]\nQuestion: 会社の住所を教えて\nAnswer:"
  ]
}
[llm/end] [1:chain:RunnableSequence > 17:llm:ChatOpenAI] [844ms] Exiting LLM run with output:
{
  "generations": [
    [
      {
        "text": "東京都中央区架空町1ー1ー1",
        "generation_info": {
          "finish_reason": "stop",
          "logprobs": null
        },
        "type": "ChatGeneration",
        "message": {
          "lc": 1,
          "type": "constructor",
          "id": [
            "langchain",
            "schema",
            "messages",
            "AIMessage"
          ],
          "kwargs": {
            "content": "東京都中央区架空町1ー1ー1",
            "additional_kwargs": {}
          }
        }
      }
    ]
  ],
  "llm_output": {
    "token_usage": {
      "completion_tokens": 18,
      "prompt_tokens": 590,
      "total_tokens": 608
    },
    "model_name": "gpt-3.5-turbo",
    "system_fingerprint": "fp_69829325d0"
  },
  "run": null
}
[chain/start] [1:chain:RunnableSequence > 18:parser:StrOutputParser] Entering Parser run with input:
[inputs]
[chain/end] [1:chain:RunnableSequence > 18:parser:StrOutputParser] [0ms] Exiting Parser run with output:
{
  "output": "東京都中央区架空町1ー1ー1"
}
[chain/end] [1:chain:RunnableSequence] [4.25s] Exiting Chain run with output:
{
  "output": "東京都中央区架空町1ー1ー1"
}
'東京都中央区架空町1ー1ー1'

前回までは取れなかった住所が取れていますね。

Query expansionの可視化

rag_chain.get_graph().print_ascii()
     +---------------------------------+                        
                   | Parallel<question,context>Input |                        
                   +---------------------------------+                        
                        ****                  ****                            
                    ****                          ****                        
                  **                                  ****                    
   +--------------------+                                 **                  
   | ChatPromptTemplate |                                  *                  
   +--------------------+                                  *                  
              *                                            *                  
              *                                            *                  
              *                                            *                  
       +------------+                                      *                  
       | ChatOpenAI |                                      *                  
       +------------+                                      *                  
              *                                            *                  
              *                                            *                  
              *                                            *                  
    +-----------------+                                    *                  
    | StrOutputParser |                                    *                  
    +-----------------+                                    *                  
              *                                            *                  
              *                                            *                  
              *                                            *                  
      +-------------+                                      *                  
      | Lambda(...) |                                      *                  
      +-------------+                                      *                  
              *                                            *                  
              *                                            *                  
              *                                            *                  
  +----------------------+                                 *                  
  | VectorStoreRetriever |                                 *                  
  +----------------------+                                 *                  
              *                                            *                  
              *                                            *                  
              *                                            *                  
+--------------------------+              +--------------------------------+  
| Lambda(get_unique_union) |              | Lambda(itemgetter('question')) |  
+--------------------------+              +--------------------------------+  
                        ****                  ****                            
                            ****          ****                                
                                **      **                                    
                  +----------------------------------+                        
                  | Parallel<question,context>Output |                        
                  +----------------------------------+                        
                                    *                                         
                                    *                                         
                                    *                                         
                            +----------------+                                
                            | PromptTemplate |                                
                            +----------------+                                
                                    *                                         
                                    *                                         
                                    *                                         
                              +------------+                                  
                              | ChatOpenAI |                                  
                              +------------+                                  
                                    *                                         
                                    *                                         
                                    *                                         
                           +-----------------+                                
                           | StrOutputParser |                                
                           +-----------------+                                
                                    *                                         
                                    *                                         
                                    *                                         
                        +-----------------------+                             
                        | StrOutputParserOutput |                             
                        +-----------------------+                     

最後に可視化してみました。

今日はここまでです。

読んでくれた方ありがとうございました。


この記事が気に入ったらサポートをしてみませんか?