大模型Agent速成技巧:最简明易懂的教程

大模型相关目录

大模型,包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容
从0起步,扬帆起航。

  1. 大模型应用向开发路径及一点个人思考
  2. 大模型应用开发实用开源项目汇总
  3. 大模型问答项目问答性能评估方法
  4. 大模型数据侧总结
  5. 大模型token等基本概念及参数和内存的关系
  6. 大模型应用开发-华为大模型生态规划
  7. 从零开始的LLaMA-Factory的指令增量微调
  8. 基于实体抽取-SMC-语义向量的大模型能力评估通用算法(附代码)
  9. 基于Langchain-chatchat的向量库构建及检索(附代码)
  10. 一文教你成为合格的Prompt工程师
  11. 最简明的大模型agent教程


一、Agent简介

大模型Agent是结合了大规模神经网络模型和自主计算实体的技术,它具备强大的表达、学习和交互能力,能够在无人干预的情况下,根据环境信息自主决策和控制行为。

简单而言之,agent是增强大模型能力的技术方案路径。主要包括:工具、工具选择方案,大模型工具应用3个部分。运行大体流程:

1用户给出一个任务(Prompt) -> 2思考(Thought) -> 3行动(Action) -> 4观察(Observation)
在这里插入图片描述

二、langchain-chatchat下的Agent开发

更详细地流程可参考GitHub wiki介绍

于tools_select.py_预设新增的工具、工具描述等信息_。
在这里插入图片描述

于下述路径下新增同名新工具py文件,并进行工具内容定义。

在这里插入图片描述
_工具样例_如下:

from pydantic import BaseModel, Field
import requests
from configs.kb_config import SENIVERSE_API_KEY

def weather(location: str, api_key: str):
    url = f"https://api.seniverse.com/v3/weather/now.json?key={api_key}&location={location}&language=zh-Hans&unit=c"
    response = requests.get(url)
    if response.status_code == 200:
        data = response.json()
        weather = {
            "temperature": data["results"][0]["now"]["temperature"],
            "description": data["results"][0]["now"]["text"],
        }
        return weather
    else:
        raise Exception(
            f"Failed to retrieve weather: {response.status_code}")

def weathercheck(location: str):
    return weather(location, SENIVERSE_API_KEY)

class WeatherInput(BaseModel):
    location: str = Field(description="City name,include city and county")

但我们仍不知道大模型、langchain框架选择工具、使用工具、进行输出等过程的_调度原理_,可参考如下代码:

from langchain.utilities import ArxivAPIWrapper
from langchain_experimental.tools import PythonAstREPLTool

from typing import Dict, Tuple
import os
import json

arxiv = ArxivAPIWrapper()
python=PythonAstREPLTool()

class ElectricityBillTool:
    def run(self, name, start_date, end_date):
        # 假设这里执行了某些操作来查询电费
        # 为了简化,我们直接返回一条测试信息
        return f"电费查询结果:姓名:{name}, 期间:{start_date} 到 {end_date}, 电费:100元"

def tool_wrapper_for_model(tool, expects_kwargs=True):
    def tool_(args_json):
        args = json.loads(args_json)
        if expects_kwargs:
            return tool.run(**args)  # 使用 **args 将字典展开为关键字参数
        else:
            # 如果 run 方法期望位置参数,我们假设所有参数都聚合在一个叫 'query' 的键下
            return tool.run(args['query'])  # 使用位置参数调用
    return tool_


electricity_bill_tool = ElectricityBillTool()

# 以下是给模型看的工具描述:
TOOLS = [
    {
        'name_for_human':
            'arxiv',
        'name_for_model':
            'Arxiv',
        'description_for_model':
            'A wrapper around Arxiv.org Useful for when you need to answer questions about Physics, Mathematics, Computer Science, Quantitative Biology, Quantitative Finance, Statistics, Electrical Engineering, and Economics from scientific articles on arxiv.org.',
        'parameters': [{
            "name": "query",
            "type": "string",
            "description": "the document id of arxiv to search",
            'required': True
        }], 
        'tool_api': tool_wrapper_for_model(arxiv, expects_kwargs=False)
    },
    {
        'name_for_human':
            'python',
        'name_for_model':
            'python',
        'description_for_model':
            "A Python shell. Use this to execute python commands. When using this tool, sometimes output is abbreviated - Make sure it does not look abbreviated before using it in your answer. "
            "Don't add comments to your python code.",
        'parameters': [{
            "name": "query",
            "type": "string",
            "description": "a valid python command.",
            'required': True
        }],
        'tool_api': tool_wrapper_for_model(python, expects_kwargs=False)
    },
    {
    'name_for_human': 'electricity_bill',
    'name_for_model': 'ElectricityBill',
    'description_for_model': '查询电费工具,根据姓名、开始时间和结束时间查询电费。',
    'parameters': [
        {"name": "name", "type": "string", "description": "姓名", 'required': True},
        {"name": "start_date", "type": "string", "description": "开始时间", 'required': True},
        {"name": "end_date", "type": "string", "description": "结束时间", 'required': True}
    ],
    'tool_api': tool_wrapper_for_model(electricity_bill_tool, expects_kwargs=True)
    }

]

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

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

def get_model_response(prompt, stop):
    from openai import OpenAI
    client = OpenAI()

    completion = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "user", "content": prompt}
        ],
        stream=False,
        stop = stop,
    )
    response = completion.choices[0].message.content
    return response

def main(query, choose_tools):
    prompt = build_planning_prompt(choose_tools, query) # 组织prompt
    stop = ["Observation:", "Observation:\n"]
    print(prompt)
    response = get_model_response(prompt, stop)

    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 = get_model_response(prompt, stop)

    print("\033[32m" + response + "\033[0m")

if __name__ == "__main__":
    query = "查一下张三2024年1月的电费" # 所提问题
    choose_tools = TOOLS # 选择备选工具
    print("=" * 10)
    main(query, choose_tools)


三、langchain的Agent开发

主控:

prompt = get_tools_agent_prompt(query)
agent = get_tools_agent()
response = agent.run(prompt)

get_tools_agent_prompt:

def get_tools_agent_prompt(query, history=None):
        from datetime import datetime

        current_time = datetime.now()

        prompt = (
                f"""
            如果查询未指定年/月,请参考当前时刻:{current_time}。

            请用中文思考及回复。

            优先考虑使用工具解决问题,当工具无法解决时,尝试根据经验直接回答。

            最终回复时若内容较多需要注意保持可读性,添加合理的换行。

            下面是用户问题:

            """
            
                + query
            )
        return prompt

get_tools_agent

def get_tools_agent():
    llm = get_llm()
    tools = get_tools()
    agent = initialize_agent(
            tools, 
            llm, 
            agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, 
            verbose=True, 
            max_iterations=5,
            handle_parsing_errors=True,
        )
    return agent

# 获取llm
def get_llm():
        
    api_key = os.getenv("PROXY_API_KEY")
    api_url = os.getenv("PROXY_SERVER_URL")
    api_url = api_url.split('/chat')[0]
    model = os.getenv("PROXYLLM_BACKEND")

    if "openai" in api_url:
        llm = ChatOpenAI(temperature=0,model=model,openai_api_base=api_url,openai_api_key=api_key,)
    elif "bigmodel" in api_url:
        llm = ChatZhipuAI(temperature=0.01,api_key=api_key,model="glm-4",)
    elif "dashscope" in api_url:
        from langchain_community.chat_models.tongyi import ChatTongyi
        llm = ChatTongyi(model="qwen-max",top_p=0.01,streaming=True,dashscope_api_key=api_key)

    return llm

def get_tools():
    llm=get_llm()
    tools = [
        Tool(
            name="查询负荷数据及同比环比",
            func=calculate_growth, 
            description="""
            当你想要查询某地负荷(最大值、最小值、平均值),查询最大/最小值发生时间,或者查询同比或环比变化的时候很有用,该工具返回某地负荷数据及同比变化率。
            输入应该包括地区(公司)名(如果未指定,则默认为直供区)、时间(仅允许YYYY,YYYY-QQ,YYYY-MM,YYYY-MM-DD,YYYY-节气五种格式,也即年、年-季度、年-月、年-月-日,年-节气)、最大/最小/平均(若未明确提及,默认为平均)、同比/环比(可以不输入),以|分隔。
            查询某一年时,仅输入年份即可。
            例如:上海|2023|最大|环比、广州|2023-Q2|最小|环比、深圳|2021-07|平均、北京|2023-05-01|最大。
            """,
        )
    ]
    tools.append(
        Tool(
            name="查询负荷新高(低)",
            func=find_record_breaking_loads, 
            description="""
            当你想要查询某地负荷几创新高或几创新低的时候很有用,该工具返回创下新高/低的次数,及对应的详细信息。
            输入应该包括地区(公司)名(如果未指定,则默认为直供区)、基础时间(仅允许YYYY,YYYY-QQ,YYYY-MM,YYYY-MM-DD,YYYY-节气五种格式,也即年、年-季度、年-月、年-月-日,年-节气)、对比时间(如未指定,默认与基础时间的前一年做对比,时间类型同前者)、高/低,以|分隔。
            例如:上海|2023-Q1|2022-Q1|高、广州|2023-寒露|2021-寒露|低、深圳|2023|2021|高。
            """,
        ),
    )
    return tools

def calculate_growth(context):
    # 读取CSV文件
    # df = pd.read_csv('./data/load.csv')

    # 分割输入参数
    params = context.split("|")

    # 确保至少有三个参数
    if len(params) < 3:
        return "至少需要三个参数(region, time_period, compare_type)。"

    # 提取参数,如果缺少第四个参数,则默认为"同比"
    elif len(params) == 3:
        region, time_period, compare_type = params[:3]
        growth_type = None
    elif len(params) == 4:
        region, time_period, compare_type, growth_type = context.split("|")
    else:
        return "您输入的参数数量不匹配,请仔细核对。"

def find_record_breaking_loads(context):
    # 分割输入参数
    params = context.split("|")

    if len(params) not in [3, 4]:
        return "您输入的参数数量不匹配,请仔细核对。"

    region = params[0]
    current_time_period = params[1]
    high_low = params[-1]
    # compare_time_period = params[2] if len(params) == 4 else None
    compare_time_period = params[2] if len(params) == 4 else str(int(params[1][:4])-1) + params[1][4:]

    # 筛选指定地区的数据
    df_region = df[df['公司'] == region]

    # 解析当前时间段
    try:
        current_period_parsed = parse_time_period(df, current_time_period)
    except ValueError as e:
        return f"当前时间段解析错误:{e}"

    # 解析对比时间段,如果有
    if compare_time_period:
        try:
            compare_period_parsed = parse_time_period(df, compare_time_period)
        except ValueError as e:
            return f"对比时间段解析错误:{e}"
    else:
        compare_period_parsed = None

    # 根据时间段获取数据
    if isinstance(current_period_parsed, tuple):
        current_start_date, current_end_date = current_period_parsed
        df_current = df_region[(df_region['时间'] >= current_start_date) & (df_region['时间'] < current_end_date)]

        if compare_period_parsed:
            compare_start_date, compare_end_date = compare_period_parsed
            df_compare = df_region[(df_region['时间'] >= compare_start_date) & (df_region['时间'] < compare_end_date)]
        else:
            # 默认比较去年同期
            year = int(current_start_date.split('-')[0])
            previous_year = year - 1
            df_compare = df_region[(df_region['时间'] >= f"{previous_year}-{current_start_date[5:]}") & (df_region['时间'] < f"{previous_year}-{current_end_date[5:]}")]

    # 比较负荷值
    if high_low == '高':
        reference_load = df_compare['负荷'].max()
    else:
        reference_load = df_compare['负荷'].min()

    # 计算创纪录的次数
    if high_low == '高':
        df_records = df_current[df_current['负荷'] > reference_load]
    else:
        df_records = df_current[df_current['负荷'] < reference_load]

    # 结果处理
    if not df_records.empty:
        record_count = len(df_records)
        top_record = df_records.sort_values(by="负荷", ascending=(high_low != '高')).iloc[0]
        return f"{region}在{current_time_period}相较{compare_time_period}共有{record_count}次创下新{high_low},其中最{high_low}负荷为{top_record['负荷']}MW,时间为{top_record['时间']}。"
    else:
        return f"{region}在{current_time_period}相较{compare_time_period}未创新{high_low}。"


最后介绍一下 AgentType.ZERO_SHOT_REACT_DESCRIPTION

首先介绍一些常见的关键词:

ReAct:由单词“Reason”和“Act”组合而成,前者对应于推理,即大模型的通用文本逻辑判断能力,或者说是对问题进行思考和拆解的能力;后者对应于行动,即具备专业知识的特定领域精确回答能力,或者说是调用外部工具的能力。ReAct顾名思义就是把思考和行动相结合,通过二者的依次迭代执行完成任务。
Zero-shot:零样本,或者说是无记忆。在运行时,只考虑与当前代理的一次交互,不保留对话历史。
Conversational:引入了对话历史,因为有记忆了,所以需要初始化代理时引入memory参数。其一个缺点是可能无法执行复杂的Tool调用任务。
Chat:常规情况下以OpenAI方式初始化LLM,此类Agent可以以ChatOpenAI方式初始化模型。前者是更通用的接口,用于与不同类型的语言模型进行交互,可以与各种LLM模型集成。ChatOpenAI接口是对其的高级封装,更专注于对话式交互。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

如何学习AI大模型?

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

在这里插入图片描述

👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

在这里插入图片描述

1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

在这里插入图片描述

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值