# [LangChain] 範例-飲食敘述分類
日期:2023/09/19
## 敘述
- 主題:StructuredOutputParser()、ResponseSchema()
- 使用情境:讓程式自行將描述的飲食種類,根據六大類食物進行分類。利用GPT模型對文字的理解能力,自行分類描述的食物,讓食物種類確認這件事變簡單。
- 輸入:飲食敘述。例如:我今天吃了兩塊巧克力、一塊pizza。
- 輸出:將輸入中提及的飲食根據食物六大類進行分類。
備註:
此篇範例將作為下一個範例的其中一個功能。
## 目錄
- [1. 主程式](#1-主程式)
- [2. 輸入輸出](#2-輸入輸出)
____________________
## 1. 主程式
導入套件
```python=
from dotenv import load_dotenv
load_dotenv()
from langchain.chat_models import ChatOpenAI
from langchain.prompts import (
PromptTemplate
)
from langchain import LLMChain
from langchain.output_parsers import StructuredOutputParser, ResponseSchema
llm = ChatOpenAI(temperature=0)
llm_model = "gpt-3.5-turbo"
```
在本次的範例中,預期將輸入的飲食敘述進行處理,抓出飲食相關的描述並分類到對應的六大類食物分類中。
首先,透過以下程式碼建立希望的輸出格式。每個ResponseSchema()將對應到六大類食物的各個類別,其中name為自定義類別名稱,description為類別的敘述,model將會根據這個敘述確認應該如何分類。定義好的六個ResponseSchema()將放入一個串列中。
實際上制定類別或者說輸出架構的過程,就是在定義一個要輸入到model中的prompt。
可從本段程式碼的輸出確認定義好的prompt。
```python=
#定義輸出架構
response_schemas = [
ResponseSchema(name='CER', description='請將<五穀類>的食物放到此處。'),
ResponseSchema(name='VEG', description='請將<蔬菜類>的食物放到此處。'),
ResponseSchema(name='FRU', description='請將<水果類>的食物放到此處。'),
ResponseSchema(name='M&L', description='請將<肉類和豆類>的食物放到此處。'),
ResponseSchema(name='DAIRY', description='請將<奶製品類>的食物放到此處。'),
ResponseSchema(name='F&N', description='請將<油脂和堅果類>的食物放到此處。'),
]
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
print(output_parser.get_format_instructions())
```
:::success
The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "\```json" and "```":
\```json
{
"CER": string // 請將<五穀類>的食物放到此處。
"VEG": string // 請將<蔬菜類>的食物放到此處。
"FRU": string // 請將<水果類>的食物放到此處。
"M&L": string // 請將<肉類和豆類>的食物放到此處。
"DAIRY": string // 請將<奶製品類>的食物放到此處。
"F&N": string // 請將<油脂和堅果類>的食物放到此處。
}
\```
:::
除了建立輸出格式外,下一步還需要將此格式加入到PromptTemplate()中,並提供給chain。
```python=
#將前面定義好的輸出架構提供PromptTemplate(),再提供給chain
format_instructions = output_parser.get_format_instructions()
template="answer the users question as best as possible.\n{format_instructions}\n{question}"
prompt = PromptTemplate(
template=template,
input_variables=["question"],
partial_variables={"format_instructions": format_instructions},
output_parser=output_parser
)
llm_chain = LLMChain(prompt=prompt, llm=llm)
```
## 2. 輸入輸出
```python=
input_text = '''請判斷<>中包含的飲食或料理,根據六大類食物進行分類。
<我今天早上吃了十顆哈密瓜、兩個蘋果派,十分過癮;而下午時,吃了一片巧克力蛋糕、一個素食便當。>'''
output = llm_chain.predict(question=input_text)
print(output)
print('-'*30)
output = llm_chain.predict_and_parse(question=input_text)
print('使用.predict_and_parse():')
print(output)
```
:::success
\```json
{
"CER": "",
"VEG": "一個素食便當",
"FRU": "十顆哈密瓜、兩個蘋果派",
"M&L": "",
"DAIRY": "",
"F&N": "一片巧克力蛋糕"
}
\```
\------------------------------
使用.predict_and_parse():
{'CER': '', 'VEG': '一個素食便當', 'FRU': '十顆哈密瓜、兩個蘋果派', 'M&L': '', 'DAIRY': '', 'F&N': '一片巧克力蛋糕'}
:::
透過LangChain中OutputParser的功能,可將不具有結構的文字敘述變成結構化的輸出,如上。經過整理過的資訊,會更方便進行後續的運用。