使用Gradient和LlamaIndex对Llama2进行微调以获得更好的结构化输出¶
在这个笔记本中,我们将向您展示如何微调llama2-7b以更好地输出结构化结果。
我们将使用gradient.ai来实现这一目标。
这与我们的OpenAI函数微调笔记本的格式类似。
注意:这是我们关于使用Modal对llama2-7b进行微调的另一种选择的仓库/指南:https://github.com/run-llama/modal_finetune_sql
In [ ]:
Copied!
%pip install llama-index-llms-gradient
%pip install llama-index-llms-openai
%pip install llama-index-readers-file pymupdf
%pip install llama-index-finetuning
%pip install llama-index-llms-gradient
%pip install llama-index-llms-openai
%pip install llama-index-readers-file pymupdf
%pip install llama-index-finetuning
In [ ]:
Copied!
!pip install llama-index gradientai -q
!pip install llama-index gradientai -q
In [ ]:
Copied!
import os
from llama_index.llms.gradient import GradientBaseModelLLM
from llama_index.finetuning import GradientFinetuneEngine
import os
from llama_index.llms.gradient import GradientBaseModelLLM
from llama_index.finetuning import GradientFinetuneEngine
In [ ]:
Copied!
os.environ["GRADIENT_ACCESS_TOKEN"] = os.getenv("GRADIENT_API_KEY")
os.environ["GRADIENT_WORKSPACE_ID"] = "<insert_workspace_id>"
os.environ["GRADIENT_ACCESS_TOKEN"] = os.getenv("GRADIENT_API_KEY")
os.environ["GRADIENT_WORKSPACE_ID"] = ""
使用GPT-4 Pydantic程序进行微调¶
在本节中,我们将展示如何通过我们的低级Pydantic程序模块记录输入 + GPT-4生成的输出。我们将使用该数据集对llama2进行微调。
In [ ]:
Copied!
from pydantic import BaseModel
class Album(BaseModel):
"""专辑的数据模型。"""
name: str
artist: str
from pydantic import BaseModel
class Album(BaseModel):
"""专辑的数据模型。"""
name: str
artist: str
In [ ]:
Copied!
from llama_index.core.callbacks import CallbackManager, LlamaDebugHandler
from llama_index.llms.openai import OpenAI
from llama_index.llms.gradient import GradientBaseModelLLM
from llama_index.core.program import LLMTextCompletionProgram
from llama_index.core.output_parsers import PydanticOutputParser
openai_handler = LlamaDebugHandler()
openai_callback = CallbackManager([openai_handler])
openai_llm = OpenAI(model="gpt-4", callback_manager=openai_callback)
gradient_handler = LlamaDebugHandler()
gradient_callback = CallbackManager([gradient_handler])
base_model_slug = "llama2-7b-chat"
gradient_llm = GradientBaseModelLLM(
base_model_slug=base_model_slug,
max_tokens=300,
callback_manager=gradient_callback,
is_chat_model=True,
)
# HACK: set chat model
from llama_index.core.llms import LLMMetadata
# gradient_llm.metadata = LLMMetadata(
# context_window=1024,
# num_output=gradient_llm.max_tokens or 20,
# is_chat_model=True,
# is_function_calling_model=False,
# model_name=gradient_llm._model.id,
# )
from llama_index.core.callbacks import CallbackManager, LlamaDebugHandler
from llama_index.llms.openai import OpenAI
from llama_index.llms.gradient import GradientBaseModelLLM
from llama_index.core.program import LLMTextCompletionProgram
from llama_index.core.output_parsers import PydanticOutputParser
openai_handler = LlamaDebugHandler()
openai_callback = CallbackManager([openai_handler])
openai_llm = OpenAI(model="gpt-4", callback_manager=openai_callback)
gradient_handler = LlamaDebugHandler()
gradient_callback = CallbackManager([gradient_handler])
base_model_slug = "llama2-7b-chat"
gradient_llm = GradientBaseModelLLM(
base_model_slug=base_model_slug,
max_tokens=300,
callback_manager=gradient_callback,
is_chat_model=True,
)
# HACK: set chat model
from llama_index.core.llms import LLMMetadata
# gradient_llm.metadata = LLMMetadata(
# context_window=1024,
# num_output=gradient_llm.max_tokens or 20,
# is_chat_model=True,
# is_function_calling_model=False,
# model_name=gradient_llm._model.id,
# )
In [ ]:
Copied!
# 尝试通过LLMTextCompletionProgram运行两者
prompt_template_str = """\
生成一个示例专辑,包括一个艺术家和一组歌曲。\
以电影 {movie_name} 为灵感。\
"""
openai_program = LLMTextCompletionProgram.from_defaults(
output_parser=PydanticOutputParser(Album),
prompt_template_str=prompt_template_str,
llm=openai_llm,
verbose=True,
)
gradient_program = LLMTextCompletionProgram.from_defaults(
output_parser=PydanticOutputParser(Album),
prompt_template_str=prompt_template_str,
llm=gradient_llm,
verbose=True,
)
# 尝试通过LLMTextCompletionProgram运行两者
prompt_template_str = """\
生成一个示例专辑,包括一个艺术家和一组歌曲。\
以电影 {movie_name} 为灵感。\
"""
openai_program = LLMTextCompletionProgram.from_defaults(
output_parser=PydanticOutputParser(Album),
prompt_template_str=prompt_template_str,
llm=openai_llm,
verbose=True,
)
gradient_program = LLMTextCompletionProgram.from_defaults(
output_parser=PydanticOutputParser(Album),
prompt_template_str=prompt_template_str,
llm=gradient_llm,
verbose=True,
)
In [ ]:
Copied!
response = openai_program(movie_name="The Shining")
print(str(response))
response = openai_program(movie_name="The Shining")
print(str(response))
In [ ]:
Copied!
tmp = openai_handler.get_llm_inputs_outputs()
print(tmp[0][0].payload["messages"][0])
tmp = openai_handler.get_llm_inputs_outputs()
print(tmp[0][0].payload["messages"][0])
In [ ]:
Copied!
# 打印tmp[0][1]
# 打印tmp[0][1]
In [ ]:
Copied!
response = gradient_program(movie_name="The Shining")
print(str(response))
response = gradient_program(movie_name="The Shining")
print(str(response))
In [ ]:
Copied!
tmp = gradient_handler.get_llm_inputs_outputs()
print(tmp[0][0].payload["messages"][0])
tmp = gradient_handler.get_llm_inputs_outputs()
print(tmp[0][0].payload["messages"][0])
定义 Pydantic 模型 + 程序¶
在这里,我们定义了由 GPT-4 提供支持的函数调用程序,该程序将生成结构化输出到一个 Pydantic 对象(相册)中。
In [ ]:
Copied!
from llama_index.core.program import LLMTextCompletionProgram
from pydantic import BaseModel
from llama_index.llms.openai import OpenAI
from llama_index.core.callbacks import GradientAIFineTuningHandler
from llama_index.core.callbacks import CallbackManager
from llama_index.core.output_parsers import PydanticOutputParser
from typing import List
class Song(BaseModel):
"""歌曲的数据模型。"""
title: str
length_seconds: int
class Album(BaseModel):
"""专辑的数据模型。"""
name: str
artist: str
songs: List[Song]
finetuning_handler = GradientAIFineTuningHandler()
callback_manager = CallbackManager([finetuning_handler])
llm_gpt4 = OpenAI(model="gpt-4", callback_manager=callback_manager)
prompt_template_str = """\
生成一个示例专辑,包括一个艺术家和一组歌曲。\
以电影 {movie_name} 为灵感。\
"""
openai_program = LLMTextCompletionProgram.from_defaults(
output_parser=PydanticOutputParser(Album),
prompt_template_str=prompt_template_str,
llm=llm_gpt4,
verbose=True,
)
from llama_index.core.program import LLMTextCompletionProgram
from pydantic import BaseModel
from llama_index.llms.openai import OpenAI
from llama_index.core.callbacks import GradientAIFineTuningHandler
from llama_index.core.callbacks import CallbackManager
from llama_index.core.output_parsers import PydanticOutputParser
from typing import List
class Song(BaseModel):
"""歌曲的数据模型。"""
title: str
length_seconds: int
class Album(BaseModel):
"""专辑的数据模型。"""
name: str
artist: str
songs: List[Song]
finetuning_handler = GradientAIFineTuningHandler()
callback_manager = CallbackManager([finetuning_handler])
llm_gpt4 = OpenAI(model="gpt-4", callback_manager=callback_manager)
prompt_template_str = """\
生成一个示例专辑,包括一个艺术家和一组歌曲。\
以电影 {movie_name} 为灵感。\
"""
openai_program = LLMTextCompletionProgram.from_defaults(
output_parser=PydanticOutputParser(Album),
prompt_template_str=prompt_template_str,
llm=llm_gpt4,
verbose=True,
)
记录输入/输出¶
我们定义一些样本电影名称作为输入,并通过函数调用程序记录输出。
In [ ]:
Copied!
# 注意:我们需要至少10部电影来使用梯度微调
电影名称 = [
"闪灵",
"无间道",
"泰坦尼克号",
"盗亦有道",
"风月",
"小鬼当家",
"铁笼狂怒",
"剪刀手爱德华",
"全面回忆",
"幽灵",
"震撼",
"机器战警",
"洛基5",
]
# 注意:我们需要至少10部电影来使用梯度微调
电影名称 = [
"闪灵",
"无间道",
"泰坦尼克号",
"盗亦有道",
"风月",
"小鬼当家",
"铁笼狂怒",
"剪刀手爱德华",
"全面回忆",
"幽灵",
"震撼",
"机器战警",
"洛基5",
]
In [ ]:
Copied!
from tqdm.notebook import tqdm
for movie_name in tqdm(movie_names):
output = openai_program(movie_name=movie_name)
print(output.json())
from tqdm.notebook import tqdm
for movie_name in tqdm(movie_names):
output = openai_program(movie_name=movie_name)
print(output.json())
In [ ]:
Copied!
events = finetuning_handler.get_finetuning_events()
events = finetuning_handler.get_finetuning_events()
In [ ]:
Copied!
events
events
In [ ]:
Copied!
finetuning_handler.save_finetuning_events("mock_finetune_songs.jsonl")
finetuning_handler.save_finetuning_events("mock_finetune_songs.jsonl")
Wrote 14 examples to mock_finetune_songs.jsonl
In [ ]:
Copied!
!cat mock_finetune_songs.jsonl
!cat mock_finetune_songs.jsonl
在数据集上进行微调¶
现在我们定义一个微调引擎,并在模拟数据集上进行微调。
In [ ]:
Copied!
# 定义基础模型
base_model_slug = "llama2-7b-chat"
base_llm = GradientBaseModelLLM(
base_model_slug=base_model_slug, max_tokens=500, is_chat_model=True
)
# 定义基础模型
base_model_slug = "llama2-7b-chat"
base_llm = GradientBaseModelLLM(
base_model_slug=base_model_slug, max_tokens=500, is_chat_model=True
)
In [ ]:
Copied!
from llama_index.finetuning import GradientFinetuneEngine
finetune_engine = GradientFinetuneEngine(
base_model_slug=base_model_slug,
# model_adapter_id='805c6fd6-daa8-4fc8-a509-bebb2f2c1024_model_adapter',
name="movies_structured",
data_path="mock_finetune_songs.jsonl",
verbose=True,
max_steps=200,
batch_size=1,
)
from llama_index.finetuning import GradientFinetuneEngine
finetune_engine = GradientFinetuneEngine(
base_model_slug=base_model_slug,
# model_adapter_id='805c6fd6-daa8-4fc8-a509-bebb2f2c1024_model_adapter',
name="movies_structured",
data_path="mock_finetune_songs.jsonl",
verbose=True,
max_steps=200,
batch_size=1,
)
In [ ]:
Copied!
finetune_engine.model_adapter_id
finetune_engine.model_adapter_id
Out[ ]:
'1f810f84-c4b8-43b0-b6b0-10d2cbdaf92f_model_adapter'
In [ ]:
Copied!
# 根据需要调整epochs
epochs = 2
for i in range(epochs):
print(f"** EPOCH {i} **")
finetune_engine.finetune()
# 根据需要调整epochs
epochs = 2
for i in range(epochs):
print(f"** EPOCH {i} **")
finetune_engine.finetune()
In [ ]:
Copied!
ft_llm = finetune_engine.get_finetuned_model(
max_tokens=500, is_chat_model=True
)
# # 注意:与执行以下操作相同
from llama_index.llms.gradient import GradientModelAdapterLLM
# ft_llm = GradientModelAdapterLLM(
# model_adapter_id=finetune_engine.model_adapter_id,
# max_tokens=500
# )
ft_llm = finetune_engine.get_finetuned_model(
max_tokens=500, is_chat_model=True
)
# # 注意:与执行以下操作相同
from llama_index.llms.gradient import GradientModelAdapterLLM
# ft_llm = GradientModelAdapterLLM(
# model_adapter_id=finetune_engine.model_adapter_id,
# max_tokens=500
# )
试一试!¶
我们获得了经过微调的LLM,并将其与Pydantic程序一起使用。
In [ ]:
Copied!
# 尝试稍微修改prompt_template_str
new_prompt_template_str = """\
生成一个示例专辑,包括一个艺术家和一组歌曲。\
以电影 {movie_name} 为灵感。\
请只生成一个专辑。
"""
gradient_program = LLMTextCompletionProgram.from_defaults(
output_parser=PydanticOutputParser(Album),
# prompt_template_str=prompt_template_str,
prompt_template_str=new_prompt_template_str,
llm=ft_llm,
verbose=True,
)
# 尝试稍微修改prompt_template_str
new_prompt_template_str = """\
生成一个示例专辑,包括一个艺术家和一组歌曲。\
以电影 {movie_name} 为灵感。\
请只生成一个专辑。
"""
gradient_program = LLMTextCompletionProgram.from_defaults(
output_parser=PydanticOutputParser(Album),
# prompt_template_str=prompt_template_str,
prompt_template_str=new_prompt_template_str,
llm=ft_llm,
verbose=True,
)
In [ ]:
Copied!
gradient_program(movie_name="Goodfellas")
gradient_program(movie_name="Goodfellas")
Out[ ]:
Album(name='Wiseguy Melodies', artist='Tommy DeVito & The Gangsters', songs=[Song(title='Life in the Fast Lane', length_seconds=210), Song(title='Money and Power', length_seconds=240), Song(title='Goodfellas', length_seconds=270), Song(title='Betrayal', length_seconds=200), Song(title='Downfall', length_seconds=180)])
In [ ]:
Copied!
gradient_program(movie_name="Chucky")
gradient_program(movie_name="Chucky")
In [ ]:
Copied!
# 你无法通过普通的llama2-7b获得这个!
base_gradient_program = LLMTextCompletionProgram.from_defaults(
output_parser=PydanticOutputParser(Album),
prompt_template_str=prompt_template_str,
llm=base_llm,
verbose=True,
)
# 你无法通过普通的llama2-7b获得这个!
base_gradient_program = LLMTextCompletionProgram.from_defaults(
output_parser=PydanticOutputParser(Album),
prompt_template_str=prompt_template_str,
llm=base_llm,
verbose=True,
)
In [ ]:
Copied!
# 抛出一个错误
base_gradient_program(movie_name="Goodfellas")
# 抛出一个错误
base_gradient_program(movie_name="Goodfellas")
通过RAG系统对结构化输出进行微调¶
函数调用的一个用例是通过RAG系统获取结构化输出。
在这里,我们展示如何创建一个训练数据集,其中包括上下文增强的输入和未结构化文档上的结构化输出。然后,我们可以对LLM进行微调,并将其插入到RAG系统中,以执行检索和输出提取。
In [ ]:
Copied!
!mkdir data && wget --user-agent "Mozilla" "https://arxiv.org/pdf/2307.09288.pdf" -O "data/llama2.pdf"
!mkdir data && wget --user-agent "Mozilla" "https://arxiv.org/pdf/2307.09288.pdf" -O "data/llama2.pdf"
In [ ]:
Copied!
from pydantic import Field
from typing import List
class Citation(BaseModel):
"""引文类。"""
author: str = Field(
..., description="推断的第一作者(通常是姓氏)"
)
year: int = Field(..., description="推断的年份")
desc: str = Field(
...,
description=(
"从作者被引用的作品文本中推断的描述"
),
)
class Response(BaseModel):
"""作者引文列表。
从非结构化文本中提取。
"""
citations: List[Citation] = Field(
...,
description=(
"作者引文列表(按作者、年份和描述组织)。"
),
)
from pydantic import Field
from typing import List
class Citation(BaseModel):
"""引文类。"""
author: str = Field(
..., description="推断的第一作者(通常是姓氏)"
)
year: int = Field(..., description="推断的年份")
desc: str = Field(
...,
description=(
"从作者被引用的作品文本中推断的描述"
),
)
class Response(BaseModel):
"""作者引文列表。
从非结构化文本中提取。
"""
citations: List[Citation] = Field(
...,
description=(
"作者引文列表(按作者、年份和描述组织)。"
),
)
读取数据¶
In [ ]:
Copied!
from llama_index.readers.file import PyMuPDFReader
from llama_index.core import Document
from llama_index.core.node_parser import SimpleNodeParser
from pathlib import Path
from llama_index.core.callbacks import GradientAIFineTuningHandler
from llama_index.readers.file import PyMuPDFReader
from llama_index.core import Document
from llama_index.core.node_parser import SimpleNodeParser
from pathlib import Path
from llama_index.core.callbacks import GradientAIFineTuningHandler
In [ ]:
Copied!
loader = PyMuPDFReader()
docs0 = loader.load(file_path=Path("./data/llama2.pdf"))
loader = PyMuPDFReader()
docs0 = loader.load(file_path=Path("./data/llama2.pdf"))
In [ ]:
Copied!
doc_text = "\n\n".join([d.get_content() for d in docs0])
metadata = {
"paper_title": "Llama 2: Open Foundation and Fine-Tuned Chat Models"
}
docs = [Document(text=doc_text, metadata=metadata)]
doc_text = "\n\n".join([d.get_content() for d in docs0])
metadata = {
"paper_title": "Llama 2: Open Foundation and Fine-Tuned Chat Models"
}
docs = [Document(text=doc_text, metadata=metadata)]
In [ ]:
Copied!
chunk_size = 1024
node_parser = SimpleNodeParser.from_defaults(chunk_size=chunk_size)
nodes = node_parser.get_nodes_from_documents(docs)
chunk_size = 1024
node_parser = SimpleNodeParser.from_defaults(chunk_size=chunk_size)
nodes = node_parser.get_nodes_from_documents(docs)
In [ ]:
Copied!
len(nodes)
len(nodes)
Out[ ]:
89
In [ ]:
Copied!
# 设置 GPT-4 上下文 - 生成给定查询的“ground-truth”数据
finetuning_handler = GradientAIFineTuningHandler() # 微调处理程序
callback_manager = CallbackManager([finetuning_handler]) # 回调管理器
llm_gpt4 = OpenAI(model="gpt-4-0613", temperature=0.3) # 使用OpenAI的GPT-4模型
llm_gpt4.pydantic_program_mode = "llm" # 设置pydantic程序模式为“llm”
# 设置 gradient.ai 上下文
base_model_slug = "llama2-7b-chat" # 基础模型标识
base_llm = GradientBaseModelLLM(
base_model_slug=base_model_slug, max_tokens=500, is_chat_model=True
) # 基础LLM模型
base_llm.pydantic_program_mode = "llm" # 设置pydantic程序模式为“llm”
# 设置评估上下文(用于问题生成)
eval_llm = OpenAI(model="gpt-4-0613", temperature=0) # 使用OpenAI的GPT-4模型
# 设置 GPT-4 上下文 - 生成给定查询的“ground-truth”数据
finetuning_handler = GradientAIFineTuningHandler() # 微调处理程序
callback_manager = CallbackManager([finetuning_handler]) # 回调管理器
llm_gpt4 = OpenAI(model="gpt-4-0613", temperature=0.3) # 使用OpenAI的GPT-4模型
llm_gpt4.pydantic_program_mode = "llm" # 设置pydantic程序模式为“llm”
# 设置 gradient.ai 上下文
base_model_slug = "llama2-7b-chat" # 基础模型标识
base_llm = GradientBaseModelLLM(
base_model_slug=base_model_slug, max_tokens=500, is_chat_model=True
) # 基础LLM模型
base_llm.pydantic_program_mode = "llm" # 设置pydantic程序模式为“llm”
# 设置评估上下文(用于问题生成)
eval_llm = OpenAI(model="gpt-4-0613", temperature=0) # 使用OpenAI的GPT-4模型
生成数据集¶
这里我们展示如何在这些非结构化的块/节点上生成一个训练数据集。
我们生成问题来提取不同上下文中的引用。我们通过一个GPT-4 RAG pipeline运行这些问题,提取结构化的输出,并记录输入/输出。
In [ ]:
Copied!
# 设置数据集生成器
from llama_index.core.evaluation import DatasetGenerator
from llama_index.core import SummaryIndex
from llama_index.core import PromptTemplate
from tqdm.notebook import tqdm
from tqdm.asyncio import tqdm_asyncio
fp = open("data/qa_pairs.jsonl", "w")
question_gen_prompt = PromptTemplate(
"""
{query_str}
Context:
{context_str}
Questions:
"""
)
question_gen_query = """\
以下是给定的研究论文摘录。它包含引用。
请从文本中生成关于这些引用的问题。
例如,以下是一些示例问题:
哪些引用对应于变压器模型的相关工作?
告诉我关于推进 RLHF 的作者。
你能告诉我所有计算机视觉工作对应的引用吗?\
"""
qr_pairs = []
node_questions_tasks = []
for idx, node in enumerate(nodes[:39]):
num_questions = 1 # 更改此数字以增加节点数量
dataset_generator = DatasetGenerator(
[node],
question_gen_query=question_gen_query,
text_question_template=question_gen_prompt,
llm=eval_llm,
metadata_mode="all",
num_questions_per_chunk=num_questions,
)
task = dataset_generator.agenerate_questions_from_nodes(num=num_questions)
node_questions_tasks.append(task)
node_questions_lists = await tqdm_asyncio.gather(*node_questions_tasks)
# 设置数据集生成器
from llama_index.core.evaluation import DatasetGenerator
from llama_index.core import SummaryIndex
from llama_index.core import PromptTemplate
from tqdm.notebook import tqdm
from tqdm.asyncio import tqdm_asyncio
fp = open("data/qa_pairs.jsonl", "w")
question_gen_prompt = PromptTemplate(
"""
{query_str}
Context:
{context_str}
Questions:
"""
)
question_gen_query = """\
以下是给定的研究论文摘录。它包含引用。
请从文本中生成关于这些引用的问题。
例如,以下是一些示例问题:
哪些引用对应于变压器模型的相关工作?
告诉我关于推进 RLHF 的作者。
你能告诉我所有计算机视觉工作对应的引用吗?\
"""
qr_pairs = []
node_questions_tasks = []
for idx, node in enumerate(nodes[:39]):
num_questions = 1 # 更改此数字以增加节点数量
dataset_generator = DatasetGenerator(
[node],
question_gen_query=question_gen_query,
text_question_template=question_gen_prompt,
llm=eval_llm,
metadata_mode="all",
num_questions_per_chunk=num_questions,
)
task = dataset_generator.agenerate_questions_from_nodes(num=num_questions)
node_questions_tasks.append(task)
node_questions_lists = await tqdm_asyncio.gather(*node_questions_tasks)
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 39/39 [00:27<00:00, 1.41it/s]
In [ ]:
Copied!
len(node_questions_lists)
len(node_questions_lists)
Out[ ]:
39
In [ ]:
Copied!
node_questions_lists[1]
node_questions_lists[1]
Out[ ]:
['Which citations are mentioned in the section about RLHF Results?']
In [ ]:
Copied!
# [可选] 保存
import pickle
pickle.dump(node_questions_lists, open("llama2_questions.pkl", "wb"))
# [可选] 保存
import pickle
pickle.dump(node_questions_lists, open("llama2_questions.pkl", "wb"))
In [ ]:
Copied!
# [可选] 加载问题
node_questions_lists = pickle.load(open("llama2_questions.pkl", "rb"))
# [可选] 加载问题
node_questions_lists = pickle.load(open("llama2_questions.pkl", "rb"))
In [ ]:
Copied!
from llama_index.core import VectorStoreIndex
gpt4_index = VectorStoreIndex(nodes[:39], callback_manager=callback_manager)
gpt4_query_engine = gpt4_index.as_query_engine(
output_cls=Response, llm=llm_gpt4, similarity_top_k=1
)
from llama_index.core import VectorStoreIndex
gpt4_index = VectorStoreIndex(nodes[:39], callback_manager=callback_manager)
gpt4_query_engine = gpt4_index.as_query_engine(
output_cls=Response, llm=llm_gpt4, similarity_top_k=1
)
In [ ]:
Copied!
from json import JSONDecodeError
for idx, node in enumerate(tqdm(nodes[:39])):
node_questions_0 = node_questions_lists[idx]
for question in node_questions_0:
try:
# 注意:我们不需要使用响应,事件通过微调处理程序记录
gpt4_query_engine.query(question)
except Exception as e:
print(f"问题 {question} 出错, {repr(e)}")
pass
from json import JSONDecodeError
for idx, node in enumerate(tqdm(nodes[:39])):
node_questions_0 = node_questions_lists[idx]
for question in node_questions_0:
try:
# 注意:我们不需要使用响应,事件通过微调处理程序记录
gpt4_query_engine.query(question)
except Exception as e:
print(f"问题 {question} 出错, {repr(e)}")
pass
In [ ]:
Copied!
finetuning_handler.save_finetuning_events("llama2_citation_events.jsonl")
finetuning_handler.save_finetuning_events("llama2_citation_events.jsonl")
Wrote 39 examples to llama2_citation_events.jsonl
设置微调¶
我们开始对生成的数据集进行微调。
In [ ]:
Copied!
from llama_index.finetuning import GradientFinetuneEngine
finetune_engine = GradientFinetuneEngine(
base_model_slug=base_model_slug,
# model_adapter_id='23a71710-47b3-43be-9be2-58a3efbccf2b_model_adapter',
name="llama2_structured",
data_path="llama2_citation_events.jsonl",
verbose=True,
max_steps=200,
batch_size=1,
)
from llama_index.finetuning import GradientFinetuneEngine
finetune_engine = GradientFinetuneEngine(
base_model_slug=base_model_slug,
# model_adapter_id='23a71710-47b3-43be-9be2-58a3efbccf2b_model_adapter',
name="llama2_structured",
data_path="llama2_citation_events.jsonl",
verbose=True,
max_steps=200,
batch_size=1,
)
In [ ]:
Copied!
# 保存这个以备将来运行
finetune_engine.model_adapter_id
# 保存这个以备将来运行
finetune_engine.model_adapter_id
Out[ ]:
'23a71710-47b3-43be-9be2-58a3efbccf2b_model_adapter'
In [ ]:
Copied!
# 根据需要调整epochs
epochs = 2
for i in range(epochs):
print(f"** EPOCH {i} **")
finetune_engine.finetune()
# 根据需要调整epochs
epochs = 2
for i in range(epochs):
print(f"** EPOCH {i} **")
finetune_engine.finetune()
在RAG管道中使用¶
让我们将经过微调的LLM插入到一个完整的RAG管道中,以输出结构化的结果。
In [ ]:
Copied!
ft_llm = finetune_engine.get_finetuned_model(max_tokens=500)
ft_llm = finetune_engine.get_finetuned_model(max_tokens=500)
In [ ]:
Copied!
from llama_index.core import VectorStoreIndex
vector_index = VectorStoreIndex(nodes)
query_engine = vector_index.as_query_engine(
output_cls=Response, llm=ft_llm, similarity_top_k=1
)
from llama_index.core import VectorStoreIndex
vector_index = VectorStoreIndex(nodes)
query_engine = vector_index.as_query_engine(
output_cls=Response, llm=ft_llm, similarity_top_k=1
)
In [ ]:
Copied!
# 将基线设置为
base_index = VectorStoreIndex(nodes)
base_query_engine = base_index.as_query_engine(
output_cls=Response, llm=base_llm, similarity_top_k=1
)
# 将基线设置为
base_index = VectorStoreIndex(nodes)
base_query_engine = base_index.as_query_engine(
output_cls=Response, llm=base_llm, similarity_top_k=1
)
In [ ]:
Copied!
query_str = "在RLHF结果部分提到了哪些引用?"
# query_str = """\
# 哪个引用对应于在RLHF中代表经验抽样人类偏好的数据收集概念?\
# """
# query_str = "论文中讨论了Llama 2的开发和发布的哪些引用?"
# query_str = "在RLHF结果部分提到了哪些引用?"
# query_str = "哪个引用讨论了与AI硬件生产相关的碳排放?"
query_str = "在RLHF结果部分提到了哪些引用?"
# query_str = """\
# 哪个引用对应于在RLHF中代表经验抽样人类偏好的数据收集概念?\
# """
# query_str = "论文中讨论了Llama 2的开发和发布的哪些引用?"
# query_str = "在RLHF结果部分提到了哪些引用?"
# query_str = "哪个引用讨论了与AI硬件生产相关的碳排放?"
In [ ]:
Copied!
response = query_engine.query(query_str)
print(str(response))
response = query_engine.query(query_str)
print(str(response))
让我们来看一下资源
In [ ]:
Copied!
# 查看源代码
print(response.source_nodes[0].get_content())
# 查看源代码
print(response.source_nodes[0].get_content())
让我们与基准模型(基础llama2-7b模型)进行比较。请注意,查询引擎抛出了一个错误!
In [ ]:
Copied!
# 抛出一个错误!
base_response = base_query_engine.query(query_str)
print(str(base_response))
# 抛出一个错误!
base_response = base_query_engine.query(query_str)
print(str(base_response))
作为参考,让我们也与gpt-4进行比较。
In [ ]:
Copied!
# 作为参考,请查看GPT-4的响应
gpt4_response = gpt4_query_engine.query(query_str)
print(str(gpt4_response))
# 作为参考,请查看GPT-4的响应
gpt4_response = gpt4_query_engine.query(query_str)
print(str(gpt4_response))