《大模型+爬虫》落地实战之12306查票

557 阅读5分钟

大语言模型,例如 GPT-4,拥有强大的知识储备和语言理解能力,能够进行流畅的对话、创作精彩的故事,甚至编写代码。然而,它们也面临着一些难以克服的困境,就像一个空有知识却无法行动的巨人

  • 信息滞后: 知识库的更新速度有限,无法获取最新的实时信息,例如天气、股价等。这意味着它可能告诉你昨天的天气,或者一个小时前的股价,而这些信息可能已经过时了。就像一本印刷好的百科全书,内容固定,无法实时更新。
  • 缺乏行动力: 就像被困在虚拟世界中的大脑,只能提供信息,无法直接与现实世界互动。例如,它可以告诉你如何煮咖啡,但无法帮你磨咖啡豆、煮咖啡、甚至递给你一杯咖啡。 这就好比一位博学的教授,可以讲解复杂的理论知识,但却无法在实验室进行实际操作

大模型为什么需要连接外部世界

其实大模型也不是万能的,它有三大缺陷:

  • 训练数据不可能涵盖所有信息。垂直、非公开数据必有欠缺。
  • 不知道最新信息。大模型的训练周期很长,且更新一次耗资巨大。所以它不可能实时训练。GPT-3.5 的知识截至 2022 年 1 月,GPT-4 是 2023 年 4 月。
  • 没有「真逻辑」。它表现出的逻辑、推理,是训练文本的统计规律,而不是真正的逻辑。也就是说,它的结果都是有一定不确定性的,这对于需要精确和确定结果的领域,如数学等,是灾难性的,基本是不可用的。

Function Calling 的特点

Function Calling 是一种让 Chat Completion 模型调用外部函数的能力,可以让模型不仅仅根据自身的数据库知识进行回答,而是可以额外挂载一个函数库,然后根据用户提问去函数库检索,按照实际需求调用外部函数并获取函数运行结果,再基于函数运行结果进行回答。

Function Calling 可以被应用于各种场景,例如:

  • 调用天气 API 获取实时天气信息: 不再局限于提供过时的天气预报,而是可以告诉你此时此刻的天气状况,就像你打开手机上的天气应用一样。
  • 调用订票网站 API 预订机票: 不再只是告诉你如何订票,而是可以直接帮你完成订票操作,就像一个专业的旅行代理一样。
  • 调用日历 API 安排会议: 不再只是提醒你会议时间,而是可以直接帮你安排会议,并发送邀请给参会者,就像一个高效的私人助理一样。
  • 调用数据库查询信息: 可以访问和查询数据库中的信息,例如产品信息、用户信息等,就像一个专业的数据库管理员一样。
  • 调用代码执行程序: 可以执行代码来完成各种任务,例如数据分析、图像处理等,就像一个经验丰富的程序员一样。

但是我们完成一些需求的时候,没有官方的API,那怎么办?这时候就是爬虫登场的时候,我们可不可以用爬虫来找到接口,然后让大模型去调用呢?

这样一来,大模型的能力就提升了很多!!!我们以查票来举例,官方是没有这方面的API的,那么就只能靠爬虫来了

def check_tick(date, start, end):
    url = 'https://kyfw.12306.cn/otn/leftTicket/queryG?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes=ADULT'.format(
        date, start, end)
    headers = {
        "Accept": "*/*",
        "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
        "Cache-Control": "no-cache",
        "Connection": "keep-alive",
        "If-Modified-Since": "0",
        "Pragma": "no-cache",
        "Referer": "https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-origin",
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
        "X-Requested-With": "XMLHttpRequest",
        "sec-ch-ua": ""Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"",
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": ""macOS""
    }
    
    # 需要换成自己的
    cookies = {
        "_uab_collina": "",
        "JSESSIONID": "",
        "BIGipServerotn": ".50210.0000",
        "BIGipServerpassport": ".50215.0000",
        "guidesStatus": "",
        "highContrastMode": "",
        "cursorStatus": "",
        "route": "",
        "_jc_save_fromStation": "%u5317%u4EAC%2CBJP",
        "_jc_save_toStation": "%u6210%u90FD%2CCDW",
        "_jc_save_fromDate": "2024-09-21",
        "_jc_save_toDate": "2024-09-21",
        "_jc_save_wfdc_flag": "dc"
    }

    session = requests.session()
    res = session.get(url, headers=headers, cookies=cookies)

    data = res.json()

    # 这是一个列表
    result = data["data"]["result"]

    lis = []
    for index in result:
        index_list = index.replace('有', 'Yes').replace('无', 'No').split('|')
        # print(index_list)
        train_number = index_list[3]  # 车次

        if 'G' in train_number:
            time_1 = index_list[8]  # 出发时间
            time_2 = index_list[9]  # 到达时间
            prince_seat = index_list[25]  # 特等座
            first_class_seat = index_list[31]  # 一等座
            second_class = index_list[30]  # 二等座
            dit = {
                '车次': train_number,
                '出发时间': time_1,
                '到站时间': time_2,
                "是否可以预定": index_list[11],
           
            }
            lis.append(dit)
        else:
            
            dit = {
                '车次': train_number,
                '出发时间': time_1,
                '到站时间': time_2,
                "是否可以预定": index_list[11],
                
            }
            lis.append(dit)
    # print(lis)
    content = pd.DataFrame(lis)
    # print(content)
    return content

定义一个模型回复的方法


def get_completion(messages, model="gpt-3.5-turbo"):
    response = client.chat.completions.create(
        model=model,
        messages=messages,
        temperature=0,
        max_tokens=1024,
        tools=[
            {
                "type": "function",
                "function": {
                    "name": "check_tick",
                    "description": "给定日期查询有没有票",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "date": {
                                "type": "string",
                                "description": "日期",
                            },
                            "start": {
                                "type": "string",
                                #
                                "description": "出发站 北京是BJP",
                            },
                            "end": {
                                "type": "string",
                                #
                                "description": "终点站 天津是TJP",
                            }

                        },

                    }
                }
            },
            {
                "type": "function",
                "function": {
                    "name": "check_date",
                    "description": "返回当前的日期",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            # "str": {
                            #     "type": "string",
                            #     "description": "返回今天的日期",
                            # }
                        }
                    }
                }
            }
        ]
    )
    return response.choices[0].message

这样就可以让大模型去查票了,代码不是完整的代码,需要完整代码可以留言

大模型+爬虫 可以想象的空间还是比较大的