Skip to content

Commit

Permalink
Merge pull request #79 from iMountTai/main
Browse files Browse the repository at this point in the history
Add support for LangChain
  • Loading branch information
ymcui authored Aug 4, 2023
2 parents 411f19b + 07cb5c6 commit ffaff14
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@
| [**Colab Demo**](https://colab.research.google.com/drive/1yu0eZ3a66by8Zqm883LLtRQrguBAb9MR?usp=sharing) | 在Colab中启动交互界面 ||||||| [link](https://colab.research.google.com/drive/1yu0eZ3a66by8Zqm883LLtRQrguBAb9MR?usp=sharing) |
| [**仿OpenAI API调用**](https://platform.openai.com/docs/api-reference) | 仿OpenAI API接口的服务器Demo ||||||| [link](https://github.com/ymcui/Chinese-LLaMA-Alpaca-2/wiki/api_calls_zh) |
| [**text-generation-webui**](https://github.com/oobabooga/text-generation-webui) | 前端Web UI界面的部署方式 ||||||| [link](https://github.com/ymcui/Chinese-LLaMA-Alpaca-2/wiki/text-generation-webui_zh) |
| [**LangChain**](https://github.com/hwchase17/langchain) | 适合二次开发的大模型应用开源框架 | ✅<sup>†</sup> || ✅<sup>†</sup> |||| [link](https://github.com/ymcui/Chinese-LLaMA-Alpaca-2/wiki/langchain_zh) |

<sup>†</sup>: LangChain框架支持,但教程中未实现;详细说明请参考LangChain官方文档。

⚠️ 一代模型相关推理与部署支持将陆续迁移到本项目,届时将同步更新相关教程。

Expand Down
3 changes: 3 additions & 0 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ The models in this project mainly support the following quantization, inference,
| [**Colab Demo**](https://colab.research.google.com/drive/1yu0eZ3a66by8Zqm883LLtRQrguBAb9MR?usp=sharing) | Running a Gradio web demo in Colab ||||||| [link](https://colab.research.google.com/drive/1yu0eZ3a66by8Zqm883LLtRQrguBAb9MR?usp=sharing) |
| [**OpenAI API Calls**](https://platform.openai.com/docs/api-reference) | A server that implements OpenAI API ||||||| [link](https://github.com/ymcui/Chinese-LLaMA-Alpaca-2/wiki/api_calls_en) |
| [**text-generation-webui**](https://github.com/oobabooga/text-generation-webui) | A tool for deploying model as a web UI ||||||| [link](https://github.com/ymcui/Chinese-LLaMA-Alpaca-2/wiki/text-generation-webui_en) |
| [**LangChain**](https://github.com/hwchase17/langchain) | LLM application development framework, suitable for secondary development | ✅<sup>†</sup> || ✅<sup>†</sup> |||| [link](https://github.com/ymcui/Chinese-LLaMA-Alpaca-2/wiki/langchain_en) |

<sup>†</sup>: Supported by LangChain, but not implemented in the tutorial. Please refer to the official LangChain Documentation for details.

⚠️ Inference and deployment support related to the first-generation model will be gradually migrated to this project, and relevant tutorials will be updated later.

Expand Down
20 changes: 20 additions & 0 deletions scripts/langchain/doc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
李白[注 1](701年5月19日—762年11月30日),字太白,号青莲居士,中国唐朝诗人。李白自言祖籍陇西成纪(今甘肃静宁西南),汉飞将军李广后裔,西凉武昭王李暠之后,与李唐皇室同宗。
一说其幼时内迁,寄籍剑南道绵州昌隆(今四川省江油市青莲镇)。一说先人隋末被窜于碎叶,出生于碎叶,属唐安西都护府(今吉尔吉斯斯坦共和国楚河州托克马克市)。有“诗仙”、“诗侠”、“酒仙”、“谪仙人”等称呼,活跃于盛唐[1],为杰出的浪漫主义诗人。与杜甫合称“李杜”[注 2]。被贺知章呼为“天上谪仙”、“李谪仙”。
李白的诗歌在唐朝已被选进殷璠编选的《河岳英灵集》、于敦煌石室发现的《唐写本唐人选唐诗》、韦庄编选的《又玄集》和韦縠编选的《才调集》。唐文宗御封李白的诗歌、裴旻的剑舞、张旭的草书称为“三绝”[2]。其作品想像奇特丰富,风格雄奇浪漫,意境独特,清新俊逸;善于利用夸饰与譬喻等手法、自然优美的词句,表现出奔放的情感。诗句行云流水,浑然天成。李白诗篇传诵千年,众多诗句已成经典,清赵翼称:“李杜诗篇万口传”(例如“抽刀断水水更流,举杯消愁愁更愁”等,更被谱入曲)。李白在诗歌的艺术成就被认为是中国浪漫主义诗歌的巅峰。诗作在全唐诗收录于卷161至卷185。有《李太白集》传世。杜甫曾经这样评价过李白的文章:“笔落惊风雨,诗成泣鬼神”、“白也诗无敌,飘然思不群”。
生平
早年
据《新唐书》记载李白为兴圣皇帝(凉武昭王李暠)九世孙[3],如果按照这个说法李白与李唐诸王实际上同宗,应是唐太宗李世民的同辈族弟。亦有野史说其祖是李建成或李元吉,因为被李世民族灭而逃往西域;但此说缺乏佐证,且李建成、李元吉诸子尚在幼年即在玄武门之变后全数被害,留有亲生后嗣的可能性很小。据《旧唐书》记载,李白之父李客为任城尉。更为了学习而隐居。
李白于武则天大足元年(701年)[4]出生,关于其出生地有多种说法,现在主要有剑南道绵州昌隆县(今四川省江油市)[5]青莲乡(今青莲镇)和西域的碎叶(Suyab,位于今吉尔吉斯托克马克附近)[6]这两种说法,其中后一种说法认为李白直到四岁时(705年)才跟随他的父亲李客迁居蜀地,入籍绵州。李白自四岁(705年)接受启蒙教育,从景云元年(710年)开始,李白开始读诸子史籍[7],开元三年时十四岁(715年)——喜好作赋、剑术、奇书、神仙:“十五观奇书,做赋凌相如”。在青年时期开始在中国各地游历。开元五年左右,李白曾拜撰写《长短经》的赵蕤为师,学习一年有余,这段时期的学习对李白产生了深远的影响。开元六年,在戴天山(约在四川省昌隆县北五十里处)大明寺读书。二十五岁时只身出四川,开始了广泛漫游,南到洞庭湘江,东至吴、越,寓居在安陆(今湖北省安陆市)、应山(今湖北省广水市)。
中年
李白曾经在唐玄宗天宝元年(742年)供奉翰林。有一次皇帝因酒酣问李白说:“我朝与天后(武后)之朝何如?”白曰:“天后朝政出多门,国由奸幸,任人之道,如小儿市瓜,不择香味,惟拣肥大者;我朝任人如淘沙取金,剖石采用,皆得其精粹者。”玄宗听后大笑不止[8][9]。但是由于他桀骜不驯的性格,所以仅仅不到两年他就离开了长安。据说是因为他作的《清平调》得罪了当时宠冠后宫的杨贵妃(因李白命“力士脱靴”,高力士引以为大耻,因而以言语诱使杨贵妃认为“可怜飞燕倚新妆”几句是讽刺她)而不容于宫中[注 3]。天宝三年(745年)“恳求还山,帝赐金放还”,离开长安。
后在洛阳与另两位著名诗人杜甫、高适相识,并结为好友。
晚年
天宝十一年(752年)李白年届五十二岁,北上途中游广平郡邯郸、临洺、清漳等地。十月,抵幽州。初有立功边疆思想,在边地习骑射。后发现安禄山野心,登黄金台痛哭。不久即离幽州南下。
安史之乱爆发时,李白游华山,南下回宣城,后上庐山。756年12月,李白被三次邀请,下山赴寻阳入永王李璘幕僚[10]。永王触怒唐肃宗被杀后,李白也获罪入狱。幸得郭子仪力保,方得免死,改为流徙夜郎(今贵州关岭县一带),在途经巫山时遇赦,此时他已经59岁。(参见李璘之乱)
李白晚年在江南一带漂泊。在他61岁时,听到太尉李光弼率领大军讨伐安史叛军,于是他北上准备追随李光弼从军杀敌,但是中途因病折回。第二年,李白投奔他的族叔、当时在当涂(今属安徽省马鞍山)当县令的李阳冰。同年11月,李白病逝于寓所,终年61岁,葬当涂龙山。唐宪宗元和十二年(817年),宣歙观察使范传正根据李白生前“志在青山”的遗愿,将其墓迁至当涂青山。
去世
《新唐书》记载,唐代宗继位后以左拾遗召李白,但李白当时已去世。
李阳冰在《草堂集序》中说李白是病死的[11];皮日休在诗作中记载,李白是患“腐胁疾”而死的[12]。
《旧唐书》则记载,李白流放虽然遇赦,但因途中饮酒过度,醉死于宣城。中国民间有“太白捞月”的传说:李白在舟中赏月,饮酒大醉,想要跳下船至水里捞月而溺死[13][14][15];在民间的求签活动中亦有“太白捞月”一签文,乃是下下签[16]。
作品
李白一生创作大量的诗歌,绝大多数已散佚[17],流传至今的只有九百多首。他的诗歌创作涉及的中国古典诗歌的题材非常广泛,而且在许多题材都有名作出现,而且因为际遇的不同,每个时期的诗风都有所不同。
114 changes: 114 additions & 0 deletions scripts/langchain/langchain_qa.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import argparse
import os
parser = argparse.ArgumentParser()
parser.add_argument('--file_path', required=True, type=str)
parser.add_argument('--embedding_path', required=True, type=str)
parser.add_argument('--model_path', required=True, type=str)
parser.add_argument('--gpu_id', default="0", type=str)
parser.add_argument('--chain_type', default="refine", type=str)
args = parser.parse_args()
os.environ["CUDA_VISIBLE_DEVICES"] = args.gpu_id
file_path = args.file_path
embedding_path = args.embedding_path
model_path = args.model_path

import torch
from langchain import HuggingFacePipeline
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.document_loaders import TextLoader
from langchain.prompts import PromptTemplate
from langchain.chains import RetrievalQA
from langchain.embeddings.huggingface import HuggingFaceEmbeddings

prompt_template = (
"[INST] <<SYS>>\n"
"You are a helpful assistant. 你是一个乐于助人的助手。\n"
"<</SYS>>\n\n"
"{context}\n{question} [/INST]"
)

refine_prompt_template = (
"[INST] <<SYS>>\n"
"You are a helpful assistant. 你是一个乐于助人的助手。\n"
"<</SYS>>\n\n"
"这是原始问题: {question}\n"
"已有的回答: {existing_answer}\n"
"现在还有一些文字,(如果有需要)你可以根据它们完善现有的回答。"
"\n\n"
"{context_str}\n"
"\\nn"
"请根据新的文段,进一步完善你的回答。"
" [/INST]"
)

initial_qa_template = (
"[INST] <<SYS>>\n"
"You are a helpful assistant. 你是一个乐于助人的助手。\n"
"<</SYS>>\n\n"
"以下为背景知识:\n"
"{context_str}"
"\n"
"请根据以上背景知识, 回答这个问题:{question}。"
" [/INST]"
)


if __name__ == '__main__':
load_type = torch.float16
if not torch.cuda.is_available():
raise RuntimeError("No CUDA GPUs are available.")

loader = TextLoader(file_path)
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=600, chunk_overlap=100)
texts = text_splitter.split_documents(documents)

print("Loading the embedding model...")
embeddings = HuggingFaceEmbeddings(model_name=embedding_path)
docsearch = FAISS.from_documents(texts, embeddings)

print("loading LLM...")
model = HuggingFacePipeline.from_model_id(model_id=model_path,
task="text-generation",
device=0,
model_kwargs={
"torch_dtype" : load_type,
"low_cpu_mem_usage" : True,
"temperature": 0.2,
"max_length": 1000,
"repetition_penalty":1.1}
)

if args.chain_type == "stuff":
PROMPT = PromptTemplate(
template=prompt_template, input_variables=["context", "question"]
)
chain_type_kwargs = {"prompt": PROMPT}
qa = RetrievalQA.from_chain_type(
llm=model,
chain_type="stuff",
retriever=docsearch.as_retriever(search_kwargs={"k": 1}),
chain_type_kwargs=chain_type_kwargs)

elif args.chain_type == "refine":
refine_prompt = PromptTemplate(
input_variables=["question", "existing_answer", "context_str"],
template=refine_prompt_template,
)
initial_qa_prompt = PromptTemplate(
input_variables=["context_str", "question"],
template=initial_qa_template,
)
chain_type_kwargs = {"question_prompt": initial_qa_prompt, "refine_prompt": refine_prompt}
qa = RetrievalQA.from_chain_type(
llm=model, chain_type="refine",
retriever=docsearch.as_retriever(search_kwargs={"k": 1}),
chain_type_kwargs=chain_type_kwargs)

while True:
query = input("请输入问题:")
if len(query.strip())==0:
break
print(qa.run(query))
70 changes: 70 additions & 0 deletions scripts/langchain/langchain_sum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import argparse
import os
parser = argparse.ArgumentParser()
parser.add_argument('--file_path', required=True, type=str)
parser.add_argument('--model_path', required=True, type=str)
parser.add_argument('--gpu_id', default="0", type=str)
parser.add_argument('--chain_type', default="refine", type=str)
args = parser.parse_args()
os.environ["CUDA_VISIBLE_DEVICES"] = args.gpu_id
file_path = args.file_path
model_path = args.model_path

import torch
from langchain import HuggingFacePipeline
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.prompts import PromptTemplate
from langchain.chains.summarize import load_summarize_chain

prompt_template = (
"[INST] <<SYS>>\n"
"You are a helpful assistant. 你是一个乐于助人的助手。\n"
"<</SYS>>\n\n"
"请为以下文字写一段摘要:\n{text} [/INST]"
)
refine_template = (
"[INST] <<SYS>>\n"
"You are a helpful assistant. 你是一个乐于助人的助手。\n"
"<</SYS>>\n\n"
"已有一段摘要:{existing_answer}\n"
"现在还有一些文字,(如果有需要)你可以根据它们完善现有的摘要。"
"\n"
"{text}\n"
"\n"
"如果这段文字没有用,返回原来的摘要即可。请你生成一个最终的摘要。"
" [/INST]"
)


if __name__ == '__main__':
load_type = torch.float16
if not torch.cuda.is_available():
raise RuntimeError("No CUDA GPUs are available.")

text_splitter = RecursiveCharacterTextSplitter(chunk_size=600, chunk_overlap=100, length_function=len)
with open(file_path) as f:
text = f.read()
docs = text_splitter.create_documents([text])

print("loading LLM...")
model = HuggingFacePipeline.from_model_id(model_id=model_path,
task="text-generation",
device=0,
model_kwargs={
"torch_dtype" : load_type,
"low_cpu_mem_usage" : True,
"temperature": 0.2,
"max_length": 1000,
"repetition_penalty":1.1}
)

PROMPT = PromptTemplate(template=prompt_template, input_variables=["text"])
REFINE_PROMPT = PromptTemplate(
template=refine_template,input_variables=["existing_answer", "text"],
)

if args.chain_type == "stuff":
chain = load_summarize_chain(model, chain_type="stuff", prompt=PROMPT)
elif args.chain_type == "refine":
chain = load_summarize_chain(model, chain_type="refine", question_prompt=PROMPT, refine_prompt=REFINE_PROMPT)
print(chain.run(docs))

0 comments on commit ffaff14

Please sign in to comment.