[TOC]
# Langchain-對話02
https://python.langchain.com/docs/get_started/quickstart#diving-deeper-1
Retrieval(檢索):https://python.langchain.com/docs/modules/data_connection/
Chains(鏈):https://python.langchain.com/docs/modules/chains/#lcel-chains
## **基本流程:**
``` mermaid
graph LR;
Input-->Prompt;
Prompt-->LLM;
LLM-->Output;
```
```python=
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
OPENAI_API_KEY="sk-YOUR API KEY"
llm = ChatOpenAI(openai_api_key=OPENAI_API_KEY)
prompt = ChatPromptTemplate.from_messages([
("system", "你是世界一流的程式語言專家。"),
("user", "{input}")
])
messages = prompt.format_messages(input="使用Python寫一個經典的貪吃蛇遊戲")
print(llm.invoke(messages).content)
```
## **Retrieval Chain 流程:**
``` mermaid
graph LR;
Input-->Prompt;
Input-->Document_chain;
Document_chain-->Retrieval_chain;
Retrieval_chain-->Prompt;
Prompt-->LLM;
LLM-->Output;
```
`pip install faiss-cpu`
```python=
from langchain_core.documents import Document
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains import create_retrieval_chain
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.documents import Document
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
import os
OPENAI_API_KEY="sk-YOUR API KEY"
os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY
llm = ChatOpenAI(openai_api_key=OPENAI_API_KEY)
# First we need a prompt that we can pass into an LLM to generate this search query
docs = [
Document(page_content='本校大學部四年制學生須修習共同必修英文課程,即大一共同必修英文及多元英文必修課程, 共12學分,並應參加「入學英文分級會考」(以下簡稱會考)及通過「校定英文能力檢測」(0學分),始得畢業。'),
Document(page_content='會考於每年新生入學前舉行,其結果作為英文課程分級教學及編入修課模組之依據。'),
Document(page_content='學生依入學英檢成績,分別編入基礎、中階、進階修課模組,並依各模組規定修讀及抵免共同必修英文課程。大一共同必修英文課程 及 多元英文必 修 課程模組參照附錄二。'),
]
embeddings = OpenAIEmbeddings()
vectordb = FAISS.from_documents(docs, embeddings)
retriever = vectordb.as_retriever()
prompt = ChatPromptTemplate.from_messages([
('system', 'Answer the user\'s questions in Chinese, based on the context provided below:\n\n{context}'),
('user', 'Question: {input}'),
])
document_chain = create_stuff_documents_chain(llm, prompt)
retrieval_chain = create_retrieval_chain(retriever, document_chain)
context = [] #紀錄上一個LLM的對話答案
input_text = input('>>> ')
while input_text.lower() != 'exit':
response = retrieval_chain.invoke({
'input': input_text,
'context': context
})
print(response['answer'])
context = response['context']
input_text = input('>>> ')
```
**執行結果**
```
>>> 大學生有哪些英文規定?
大學生須修習共同必修英文課程,包括大一共同必修英文及多元英文必修課程,共12學分。此外,學生還需參加「入學英文分級會考」和通過「校定英文能力檢測」,方可畢業。根據入學英檢成績,學生將被分為基礎、中階、進階修課模組,並依各模組規定修讀及抵免共同必修英文課程。
```
### Retrieval Module(檢索模組)-使用embedding model將資料轉成向量儲存在FAISS中
https://python.langchain.com/docs/modules/data_connection/
將資料轉換成向量後,再與問題進行相似比對
* 文字
```
txt = [
'本校大學部四年制學生須修習共同必修英文課程,即大一共同必修英文及多元英文必修課程, 共12學分,並應參加「入學英文分級會考」(以下簡稱會考)及通過「校定英文能力檢測」(0學分),始得畢業。會考於每年新生入學前舉行,其結果作為英文課程分級教學及編入修課模組之依據。學生依入學英檢成績,分別編入基礎、中階、進階修課模組,並依各模組規定修讀及抵免共同必修英文課程。大一共同必修英文課程 及 多元英文必 修 課程模組參照附錄二。'
]
embeddings = OpenAIEmbeddings()
vectordb = FAISS.from_texts(txt, embeddings)
```
* 文件
```
docs = [
Document(page_content='本校大學部四年制學生須修習共同必修英文課程,即大一共同必修英文及多元英文必修課程, 共12學分,並應參加「入學英文分級會考」(以下簡稱會考)及通過「校定英文能力檢測」(0學分),始得畢業。'),
Document(page_content='會考於每年新生入學前舉行,其結果作為英文課程分級教學及編入修課模組之依據。'),
Document(page_content='學生依入學英檢成績,分別編入基礎、中階、進階修課模組,並依各模組規定修讀及抵免共同必修英文課程。大一共同必修英文課程 及 多元英文必 修 課程模組參照附錄二。'),
]
embeddings = OpenAIEmbeddings()
vectordb = FAISS.from_documents(docs, embeddings)
```
* 檔案
```
loader = PyPDFLoader("台科大英文畢業門檻.pdf")
pages = loader.load_and_split()
docs = [
pages[0],
pages[1],
pages[2],
pages[3],
pages[4],
]
embeddings = OpenAIEmbeddings()
vectordb = FAISS.from_documents(docs, embeddings)
```
### Retrieval Module(檢索模組)-document_chain與retrieval_chain
* **document_chain**:將資料轉成向量後,建立的文檔鏈(document_chain)。 [連結](https://api.python.langchain.com/en/latest/chains/langchain.chains.combine_documents.stuff.create_stuff_documents_chain.html#langchain.chains.combine_documents.stuff.create_stuff_documents_chain)
```python
response = document_chain.invoke({
'input': input_text,
'context': docs #文檔資料
})
```
* **retrieval_chain**:將資料轉成向量後,**先從資料中找出與問題(Input)最相關的資料**,再建立的檢索鏈(retrieval_chain)。 [連結](https://api.python.langchain.com/en/latest/chains/langchain.chains.retrieval.create_retrieval_chain.html#langchain.chains.retrieval.create_retrieval_chain)
* 這個答案應該會更準確!
```python
retrieval_chain = create_retrieval_chain(retriever, document_chain)
response = retrieval_chain.invoke({
'input': input_text,
'context': context #紀錄上一個LLM的對話答案(可略)
})
```
## **Conversation Retrieval Chain 流程:**
對話應該要考慮整個對話紀錄
``` mermaid
graph LR;
Input-->LLM;
ChatHistory-->LLM;
LLM-->NewQuestion;
NewQuestion-->Retrieval_Chain_Module;
Retrieval_Chain_Module-->Output;
```
```python=
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains import create_history_aware_retriever
from langchain_core.prompts import MessagesPlaceholder
from langchain_openai import ChatOpenAI
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain_core.messages import HumanMessage, AIMessage
from langchain_core.documents import Document
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains import create_retrieval_chain
import os
OPENAI_API_KEY="sk-YOUR API KEY"
os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY
llm = ChatOpenAI(openai_api_key=OPENAI_API_KEY)
docs = [
Document(page_content='本校大學部四年制學生須修習共同必修英文課程,即大一共同必修英文及多元英文必修課程, 共12學分,並應參加「入學英文分級會考」(以下簡稱會考)及通過「校定英文能力檢測」(0學分),始得畢業。'),
Document(page_content='會考於每年新生入學前舉行,其結果作為英文課程分級教學及編入修課模組之依據。'),
Document(page_content='學生依入學英檢成績,分別編入基礎、中階、進階修課模組,並依各模組規定修讀及抵免共同必修英文課程。大一共同必修英文課程 及 多元英文必 修 課程模組參照附錄二。'),
]
embeddings = OpenAIEmbeddings()
vectordb = FAISS.from_documents(docs, embeddings)
retriever = vectordb.as_retriever()
prompt = ChatPromptTemplate.from_messages([
('system', 'Answer the user\'s questions in Chinese, based on the context provided below:\n\n{context}'),
MessagesPlaceholder(variable_name="chat_history"),
('user', 'Question: {input}'),
])
chat_history = [HumanMessage(content="我是台灣科技大學的大學生"), AIMessage(content="我知道了!")]
document_chain = create_stuff_documents_chain(llm, prompt)
retriever_chain = create_history_aware_retriever(llm, retriever, prompt)
retrieval_chain = create_retrieval_chain(retriever_chain, document_chain)
context = [] #紀錄上一個LLM的對話答案
input_text = input('>>> ')
while input_text.lower() != 'exit':
response = retrieval_chain.invoke({
"chat_history": chat_history,
'input': input_text,
'context': context,
})
print(response['answer'])
context = response['context']
input_text = input('>>> ')
```
```
>>> 我是哪所大學?
你是台灣科技大學的大學生。
>>> 大學生有哪些英文規定?
根據您所提供的資訊,本校大學部四年制學生須修習共同必修英文課程,包括大一共同必修英文及多元英文必修課程,共12學分。此外,學生還需要參加「入學英文分
級會考」以及通過「校定英文能力檢測」,方可畢業。根據入學英檢成績,學生會被編入基礎、中階、進階修課模組,並依各模組規定修讀或抵免共同必修英文課程。
会考每年新生入學前舉行,其結果將影響學生在英文課程中的分級和修課模組。
>>> 我是哪所大學?
你是台灣科技大學的大學生。
```
### Retrieval(檢索模組)-conversation history
* **document_chain**:建立一個鏈,用於將文件清單傳遞給模型。[連結](https://api.python.langchain.com/en/latest/chains/langchain.chains.combine_documents.stuff.create_stuff_documents_chain.html#langchain.chains.combine_documents.stuff.create_stuff_documents_chain)
* **retriever_chain**:創建歷史對話的鏈,回傳問題(Input)相關文檔。 [連結](https://api.python.langchain.com/en/latest/chains/langchain.chains.history_aware_retriever.create_history_aware_retriever.html#langchain.chains.history_aware_retriever.create_history_aware_retriever)
* **retrieval_chain**:建立檢索鏈(文件和歷史資料)來檢索文件然後將它們傳遞給模型。[連結](https://api.python.langchain.com/en/latest/chains/langchain.chains.retrieval.create_retrieval_chain.html#langchain.chains.retrieval.create_retrieval_chain)
```python
document_chain = create_stuff_documents_chain(llm, prompt)
retriever_chain = create_history_aware_retriever(llm, retriever, prompt)
retrieval_chain = create_retrieval_chain(retriever_chain, document_chain)
```
## 參考資料
LangChain(#retrieval-chain):https://python.langchain.com/docs/get_started/quickstart#retrieval-chain
Tutorial: ChatGPT Over Your Data:https://blog.langchain.dev/tutorial-chatgpt-over-your-data/
## 延伸學習
LangChain 怎麼玩? Retrieval 篇,來做個聊天機器人(ChatBot)吧:https://myapollo.com.tw/blog/langchain-tutorial-retrieval/
LLM RAG:https://medium.com/@drjulija/what-are-naive-rag-advanced-rag-modular-rag-paradigms-edff410c202e
document_loaders:https://python.langchain.com/docs/modules/data_connection/document_loaders/