本文想解决一个问题,理解Agent有啥具体的作用? 所谓读书千遍,不如动手一试,我们还是借助于上一篇,让AI给你写代码(四)—— 初步利用LangChain Agent根据输入生成,保存,执行,可以根据提示(prompt)生成代码的Agent,来解决本系列一开始的问题,提取股票信息的一些信息,例如当前股价。
一. 代码说明
我们对代码稍作修改,一个是支持多次人工输入,而不是一次性的预先输入,另一个是重点修改descrription描述,以指导agent以更快的方式生成代码,代码如下
import dashscope
import os
from langchain_community.llms import tongyi
from langchain.agents import initialize_agent
from langchain.tools import tool
from langchain.utilities.python import PythonREPL
import textwrap
from langchain.agents import (
Tool,
AgentExecutor,
agent,
)
import time
import random
dashscope.api_key="sk-bb1e64ed39b64aa49195280a8a52cfae"
#新增解析返回数据
def output_response(response: str) -> None:
if not response:
exit(0)
for line in textwrap.wrap(response, width=60):
for word in line.split():
for char in word:
print(char, end="", flush=True)
time.sleep(0.1) # Add a delay of 0.1 seconds between each character
print(" ", end="", flush=True) # Add a space between each word
print() # Move to the next line after each line is printed
print("----------------------------------------------------------------")
def saveFile(replyMessages: str):
print('... to save the file ...')
python_path="/home/cfets/eclipse-workspace/TestAI/testchain/"
now_time = time.strftime('%Y-%m-%d_%H:%M:%S', time.localtime())
i = random.randint(1, 100)
code_file = python_path + "pyAITest_" + now_time + '_' + str(i) + ".py"
# 保存至文件
res_content=False
try:
with open(code_file, 'w') as f:
f.write(replyMessages)
res_content =True
except Exception as e:
print('Error: %s' % e)
return res_content
@tool
def py_repl_tool(code: str):
"""Returns the result of execution."""
_, after = code.split("```python")
realcode = after.split("```")[0]
py_repl=PythonREPL()
#print('realcode: %s' % realcode)
#保存文件
if saveFile(realcode):
print('file is saved ... ')
return py_repl.run(realcode)
if __name__ == '__main__':
os.environ["DASHSCOPE_API_KEY"] = dashscope.api_key
tools = [
Tool(
name = "python_1",
func=py_repl_tool.run,
description="""请使用python,通过akshare接口获取市场行情,然后按指定的股票代码过滤该股票的行情,
要求:
1,请使用以em结尾的方法接口,不要使用新浪接口
2,返回字段使用中文“代码” 筛选,再按“最新价”
3,最后用print方法打印行情
代码格式为
e.g.:
```python
....
```"""
), #修改描述
]
agent = initialize_agent(
llm=tongyi.Tongyi(model_name="qwen-max",temperature=0),
tools=tools,
verbose=True,
max_iterations=5,
)
#agent.run("What is the 10th fibonacci number?")
#agent.run("股票300001现在的市场价格是多少?")
# 支持多次人工输入
while True:
try:
user_input = input("请输入6位股票代码 :")
response = agent.run(user_input)
output_response(response)
except KeyboardInterrupt:
break
我们重点看一下agent的description,根据之前踩坑的经验,告诉AI几条
1 用什么工具(python)什么库(akshare库),按什么规则解决什么问题(获取市场行情,然后按指定的股票代码过滤该股票的行情)
2 几条要求,实际上是避免踩坑
1) 要求其使用stock_zh_a_spot_em()接口(注意,如果直接写,可能更稳定一些)
2) 避免AI使用英语列名导致错误
3) 要打印结果
这更像是技术设计的描述,越接近于代码生成的代码越是准确,当然如果过度的话,那么自动生成代码的意义就不大了…
另外需要说明的是max_iterations=5 这个参数表示迭代次数(5次),从实际运用的角度看,就是如果一次生成后,py_repl.run(realcode)执行报异常,会再次生成代码并执行,直到不报异常; 每一轮执行都会生成一个代码并保存
二 执行验证
我们可以看一下执行结果
执行了两次,分别差了300015和002389
再执行生成保存的代码验证一下(002389)
这个应用看上去非常简单,那有没有实际意义呢?
我们通过直接执行通义千问试试,要求他按股票代码给出现在的股价,结果是不支持的… 原因也写了
通过这个案例,我们可以理解,直接应用大模型对话,大模型提供的回答实际上是基于数据空间,不一定是真实世界。 但如果应用Agent,则可以驱动大模型通过一定的工具在现实世界里找到答案…
是这样吗? 我再尝试一下文心一言,同样是找现实股票当下的股价
文心一言给出了答案… 那Agent能不能做到文心一言对话也做不到的任务呢?
继续,我们进一步要求,按股票代码按最近5天的K线数据,结果是… 做不到
我们看看Agent能否做到
description="""请使用python,通过akshare接口获取指定股票最近5天的行情
包括:
1,如果股票代码包含“300”,请转换为“sz300***”,如果股票包含“600”,请转换为“sh600***”
2,请先用最新历史行情接口,按个股获取最近5天的开盘价、收盘价,最高价,最低价,返回列表,并用print方法打印数据
代码格式为
e.g.:
```python
....
```"""
稍作说明,
- py_repl.run暂时不支持作图,所以仅要求提供5天的K线数据,包括开盘价、收盘价,最高价,最低价,
- 第一条要求主要是对应akshare相关历史行情接口,比较变态的入参要求 ak.stock_zh_a_daily(symbol=“sz000001”, start_date=“19910403”, end_date=“20231027”, adjust=“qfq”)
print(stock_zh_a_daily_qfq_df)
我们看执行效果和生成代码
AI折腾了几轮,终于折腾出结果…
说明: 仅有三组是因为最近5天包含了周末两天…
我们看一下最后自动生成的代码执行结果,完全一致
终于,大模型通过Agent,向我们张开双臂,欢迎走进现实世界,您现在可以用对话驱动现实世界干活了…
下一步的改进,应该是要解决几个问题,1 能否实现,先测试后存盘,即依据测试正确结果保存代码 2 进一步,输入现有的代码,在此基础上按新的需求进行修改,再测试,再存盘 3 更进一步,如何利用现有代码资产实现需求,如果现有代码不能满足需求,再生成新的代码 …