微信扫码
与创始人交个朋友
我要投稿
“Reason Only”(向内求索):COT 类型的 Prompt,希望模型一步一步思考去解决问题。这类型 Prompt 非常擅长逻辑推理,能将问题拆解成一个一个小问题,逐一解决。但是没有灵活运用外部工具和外部知识的能力。向内求索型人格:像一个思维严谨,思考问题很深入,但是不够开放,不喜欢接触新知识的人。
“Act Only”(向外探索):工具使用 Prompt,非常擅长借助外部工具和外部知识去解决问题,但是逻辑推理能力不强。向外探索人格:像一个思维开放,非常喜欢探索新知识,尝试新工具,但是思想深度不够的人。
“ReAct”(内外兼修) :就是将“Reason Only”(向内求索)和“Act Only”(向外探索)这两者相结合,
将严谨思维和探索的心态结合起来,优势互补,成为一个内外兼修的人。
直观的理解就是,ReAct 就是结合了的 推理能力 + 工具使用能力/外部知识能力,利用大模型去解决难问题。
在 ReAct Prompting 中,使用 LLMs 以交错的方式生成推理轨迹和特定于任务的操作,从而实现两者之间更大的协同作用:
接下来深入研究 ReAct 框架的代码实现的工作原理,总共分三步。
TOOL_DESC = """{name_for_model}: Call this tool to interact with the {name_for_human} API. What is the {name_for_human} API useful for? {description_for_model} Parameters: {parameters} Format the arguments as a JSON object."""
REACT_PROMPT = """Answer the following questions as best you can. You have access to the following tools:
{tool_descs}
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can be repeated zero or more times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: {query}"""
def build_planning_prompt(TOOLS, query):
tool_descs = []
tool_names = []
for info in TOOLS:
tool_descs.append(
TOOL_DESC.format(
name_for_model=info['name_for_model'],
name_for_human=info['name_for_human'],
description_for_model=info['description_for_model'],
parameters=json.dumps(
info['parameters'], ensure_ascii=False),
)
)
tool_names.append(info['name_for_model'])
tool_descs = '\n\n'.join(tool_descs)
tool_names = ','.join(tool_names)
prompt = REACT_PROMPT.format(tool_descs=tool_descs, tool_names=tool_names, query=query)
return prompt
prompt_1 = build_planning_prompt(TOOLS[0:1], query="加拿大2023年人口统计数字是多少?")
print(prompt_1)
Answer the following questions as best you can. You have access to the following tools:
Search: Call this tool to interact with the google search API. What is the google search API useful for? useful for when you need to answer questions about current events. Parameters: [{"name": "query", "type": "string", "description": "search query of google", "required": true}] Format the arguments as a JSON object.
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [Search]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can be repeated zero or more times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: 加拿大2023年人口统计数字是多少?
# 国内连 hugginface 网络不好,这段代码可能需要多重试
checkpoint = "Qwen/Qwen-7B-Chat"
TOKENIZER = AutoTokenizer.from_pretrained(checkpoint, trust_remote_code=True)
MODEL = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto", trust_remote_code=True).eval()
MODEL.generation_config = GenerationConfig.from_pretrained(checkpoint, trust_remote_code=True)
MODEL.generation_config.do_sample = False # greedy
stop = ["Observation:", "Observation:\n"]
react_stop_words_tokens = [TOKENIZER.encode(stop_) for stop_ in stop]
response_1, _ = MODEL.chat(TOKENIZER, prompt_1, history=None, stop_words_ids=react_stop_words_tokens)
print(response_1)
模型在预测到要生成的下一个词是 "Observation" 时马上停止生成,此时这个 prompt 后会生成如下的结果
Thought: 我应该使用搜索工具帮助我完成任务。search api能完成搜索的任务。
Action: Search
Action Input: {"query": "加拿大 2023年人口统计数字"}
Observation:
def parse_latest_plugin_call(text: str) -> Tuple[str, str]:
i = text.rfind('\nAction:')
j = text.rfind('\nAction Input:')
k = text.rfind('\nObservation:')
if 0 <= i < j: # If the text has `Action` and `Action input`,
if k < j: # but does not contain `Observation`,
# then it is likely that `Observation` is ommited by the LLM,
# because the output text may have discarded the stop word.
text = text.rstrip() + '\nObservation:' # Add it back.
k = text.rfind('\nObservation:')
if 0 <= i < j < k:
plugin_name = text[i + len('\nAction:'):j].strip()
plugin_args = text[j + len('\nAction Input:'):k].strip()
return plugin_name, plugin_args
return '', ''
def use_api(tools, response):
use_toolname, action_input = parse_latest_plugin_call(response)
if use_toolname == "":
return "no tool founds"
used_tool_meta = list(filter(lambda x: x["name_for_model"] == use_toolname, tools))
if len(used_tool_meta) == 0:
return "no tool founds"
api_output = used_tool_meta[0]["tool_api"](action_input)
return api_output
api_output = use_api(TOOLS, response_1)
print(api_output)
根据加拿大统计局预测,加拿大人口今天(2023年6月16日)预计将超过4000万。 联邦统计局使用模型来实时估计加拿大的人口,该计数模型预计加拿大人口将在北美东部时间今天下午3点前达到4000万。 加拿大的人口增长率目前为2.7%。
拼接上述返回答案,形成新的prompt,并获得生成最终结果
prompt_2 = prompt_1 + response_1 + ' ' + api_output
stop = ["Observation:", "Observation:\n"]
react_stop_words_tokens = [TOKENIZER.encode(stop_) for stop_ in stop]
response_2, _ = MODEL.chat(TOKENIZER, prompt_2, history=None, stop_words_ids=react_stop_words_tokens)
print(prompt_2, response_2)
按照 ReAct 格式继续生成 Thought 和 Final Answer,得到最终答案。
Answer the following questions as best you can. You have access to the following tools:
Search: Call this tool to interact with the google search API. What is the google search API useful for? useful for when you need to answer questions about current events. Parameters: [{"name": "query", "type": "string", "description": "search query of google", "required": true}] Format the arguments as a JSON object.
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [Search]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can be repeated zero or more times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: 加拿大2023年人口统计数字是多少?Thought: 我应该使用搜索工具帮助我完成任务。search api能完成搜索的任务。
Action: Search
Action Input: {"query": "加拿大 2023年人口统计数字"}
Observation: 根据加拿大统计局预测,加拿大人口今天(2023年6月16日)预计将超过4000万。 联邦统计局使用模型来实时估计加拿大的人口,该计数模型预计加拿大人口将在北美东部时间今天下午3点前达到4000万。 加拿大的人口增长率目前为2.7%。
Thought: I now know the final answer.
Final Answer: 加拿大2023年人口统计数字预计为4000万。
def main(query, choose_tools):
# 组织 prompt
prompt = build_planning_prompt(choose_tools, query)
# 设置 stop word,模型停止生成
stop = ["Observation:", "Observation:\n"]
react_stop_words_tokens = [TOKENIZER.encode(stop_) for stop_ in stop]
response, _ = MODEL.chat(TOKENIZER, prompt, history=None, stop_words_ids=react_stop_words_tokens)
while "Final Answer:" not in response: # 出现final Answer时结束
api_output = use_api(choose_tools, response) # 抽取入参并执行api
api_output = str(api_output) # 部分api工具返回结果非字符串格式需进行转化后输出
if "no tool founds" == api_output:
break
print("\033[32m" + response + "\033[0m" + "\033[34m" + ' ' + api_output + "\033[0m")
prompt = prompt + response + ' ' + api_output # 合并api输出
response, _ = MODEL.chat(TOKENIZER, prompt, history=None, stop_words_ids=react_stop_words_tokens) # 继续生成
print("\033[32m" + response + "\033[0m")
Final Answer:
,获得最终答案。53AI,企业落地应用大模型首选服务商
产品:大模型应用平台+智能体定制开发+落地咨询服务
承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-03-30
2024-04-26
2024-05-10
2024-04-12
2024-05-28
2024-04-25
2024-05-14
2024-07-18
2024-08-13
2024-04-26