使用Chat-GPT打造自己的iMessage聊天机器人

使用Chat-GPT搭建聊天机器人

微信搜索关注《Python学研大本营》,加入读者群,分享更多精彩

ChatGPT 可以在数千个行业和工作职能中解锁各种新的可能性。这是未来几年 AI 力量的令人难以置信的展示。

将 ChatGPT 的强大功能与 iMessage 相结合

在本教程中,我构建了一个全自动 iMessage 机器人,它检查最近的消息、回复,并等待新消息出现,然后再回复。我的想法是在工作或 AFK 时回复朋友的“笑话”。(我认为为了懒惰而牺牲人际关系对我来说可能不是最好的)

  • 更新包功能

  • 初始化文件并收集输入

  • 从 iMessage 数据构建 ChatGPT 提示

  • 向 ChatGPT 发送提示

  • 使用 ChatGPT 响应回复发件人

  • 自动化

开始之前

对于这个机器人,我们将利用一些开源 Github 项目来访问 chatGPT API 并简化对 iMessages 数据的查询。

  • 安装 ChatGPT Python 包装器 https://github.com/mmabrouk/chatgpt-wrapper

  • 安装 imessage-tools Python Helper(可选:iMessage 数据存储在 SQLITE 数据库中)https://github.com/my-other-github-account/imessage_tools

  • 为 Terminal.App 启用全盘访问

安装 ChatGPT Python 包装器

  1. 用 pip 直接从 github 安装这个软件的最新版本:

pip install git+https://github.com/mmabrouk/chatgpt-wrapper
  1. 在 playwright 中安装浏览器(如果您还没有)。该程序将默认使用 firefox。

如果没有,请安装 playwright。运行这两个命令以确保您同时拥有这两个命令。

npm init playwright@latest
playwright install firefox
  1. 以模式启动程序install。这将打开一个浏览器窗口。在浏览器窗口中登录 ChatGPT,然后停止该程序。

chatgpt install
  1. 重新启动不带参数的程序install即可开始使用。

chatgpt

注意事项

macOS有两个地方site-packags可以安装python。确保 ChatGPT 的安装位置在您的 PATH 变量中。我需要的补充是(f 还没有):

/Users/<user>/Liibrary/Python/3.11/bin

一段时间后会话可能会变得无效,当会话无效时,Python API 返回空并且可能会造成混淆。检查 webUI 以查看您是否已达到每小时配额。您可以花 20 美元购买 GPTPlus 以绕过

安装 imessage-tools Python Helper(可选:用于轻松收集消息数据和处理回复)

从 MacOS Ventura 开始,Apple 开始将已发送消息存储在不同的列中,并且需要对数据进行解码。较旧的操作系统版本可能仍有可用的文本。阅读有关查询 iMessageDB 的更多信息.https://arctype.com/blog/search-imessage/

幸运的是,已经有人解决了这个问题并发布了 python 代码。要获取此代码,请从Github安装或复制代码

要安装 imessage-tools,请运行以下命令:

pip3 install git+https://github.com/my-other-github-account/imessage_tools.git

为 Terminal.app 启用全盘访问

iMessages 存储在本地 SQLite 中chat.db确保您已为 Terminal.App 启用了完整的磁盘访问权限,否则查询将无法运行。在 MacOS Ventura 上执行此操作(与之前类似)

Open System Settings > Privacy and Security > Full Disk Access > Terminal.App

为 Terminal.App MacOS Ventura 启用全磁盘访问

1.更新包功能

默认情况下,imessage-tools返回纯文本。从安装位置打开 python 文件并进行以下更改

安装位置:/Users/<user>/Library/Python/3.9/python/site-packages/imessage-tools.py

为 JSON 添加导入

import json

修改print_messages函数输出JSON

之前…

def print_messages(messages):
    for message in messages:
        print(f"RowID: {message['rowid']}")
        print(f"Body: {message['body']}")
        print(f"Phone Number: {message['phone_number']}")
        print(f"Is From Me: {message['is_from_me']}")
        print(f"Cache Roomname: {message['cache_roomname']}")
        print(f"Group Chat Name: {message['group_chat_name']}")
        print(f"Date: {message['date']}")
        print("\n")

之后…

def print_messages(messages):
    print(json.dumps(messages))

保存并关闭imessage_tools.py

2. 初始化文件并获取用户输入

将所需的包导入到新的 python 文件中。

添加一个函数来收集chat.db文件路径,phone_number机器人应该与之交谈的人,以及这个人的name。提示:我使用 Github CoPilot 来帮助编写我们今天使用的大部分代码!

from chatgpt_wrapper import ChatGPT
from imessage_tools import read_messages, print_messages, send_message
import time
bot = ChatGPT()

def user_inputs():
    #ask the user for what phone number they want to send/read messages from
    phone_number = input("What phone number would you like to send/read messages from? (format: +12223334444): ")
    #ask the user for the path of their iMessage database
    chat_db = input("What is the path to your iMessage database? (/Users/userName/Messages/chatDB): ")
    #ask the user for the name of the person they are texting
    person = input("What is the name of the person you are texting? (format: FIRSTNAME): ")

    #default values for testing, uncomment the below 3 lines and comment out the above 3 lines to use the default values``
    chat_db = "/Users/kellygold/Library/Messages/chat.db"
    phone_number = "+12223334444"
    person = "Albert"
    
    return [phone_number, chat_db, person]

3. 收集最近的消息

调用read_messagesimessage-tools并附加一个字段以sender表示谁发送了带有人名而不是布尔值的消息。

def get_recent_messages(phone_number, chat_db, person):
    # Phone number or label for "you"
    self_number = "Me"
    # Number of messages to return
    n = 15
    # Read the messages
    messages = read_messages(chat_db, n=n, self_number=self_number, human_readable_date=True)
    # Filter messages where phone_number is phone_number
    messages = [message for message in messages if message['phone_number'] == phone_number]

    #if is_from_me is true, then set messages.sender to "ME: " and if is_from_me is false, then set messages.sender to "THEM: "
    for message in messages:
        if message['is_from_me'] == True:
            message['sender'] = " ME: "
        else:
            message['sender'] = person + ": "
    return messages

4. 从 iMessage 数据构建 ChatGPT 提示

⚠️等待⚠️

提示步骤对于 ChatGPT 的响应是最关键的。我强烈建议您考虑一下您向 ChatGPT 提供的消息数量,无论您是将其分解为 1 个请求还是多个请求,以及您给它的规则是什么。对于单个提示,我使用了……的变体。我发现将提示和消息分成两个请求有助于保持一致性。我也在尝试提供原始 JSON,因为 ChatGPT 可以很好地解释它。

在这个例子中,我给 ChatGPT 一个带有提示的单行命令。后跟包含消息历史记录的单个字符串。我传递给 ChatGPT 的字符串看起来像ME: nah, not really you? Want to go skiing? THEM: Hey got any plans this weekend? ME:.

为我写下以下短信消息对话的回复。回复必须少于 280 个字符,因此要非常简洁。不要在你的回复中使用引号。不要使用问候语。对话发生在我(KELLY)和一个朋友(“+ person +”)之间。不要使用 KELLY 或“+person+”这样的词。来自 KELLY 的消息以“KELLY:”开头,来自“+person+”的消息以““+person+””开头:最旧的消息在最后。最新消息排在最前面。回复的语气应该是友好的、支持的和鼓励的。风格应该是休闲和非正式的。如果需要,您可以提出 1 或 2 个跟进问题。该消息应该从最近的消息继续并且是非正式的。最新消息包含相关主题。选择相关主题。写下对以下对话的回复......

这是将提示与您的消息结合起来的代码

def build_prompt(messages, person):
    prompt = ""
    promptPrefix = "Write a reply for me to the following text message message conversation. The reply must be less than 280 characters so be very concise. Do not use quotations in your resposne. Do not use a greeting. The conversation is between me (KELLY) and a friend (" + person + "). Do not use words KELLY or "+person+". Messages from KELLY begin 'KELLY: ' and messages from "+person+" begin with '"+person+"': .The oldest messages are last. The most recent messages are first. The tone in the reply should be friendly, supportive, and encouraging. The style should be casual and informal. You may ask 1 or 2 follow up quetsions if needed. The message should continue from the most recent messages and be imformal. The most recent messages contain relevant topics. Choose relevant topics. Write a reply to the following conversation....."
    promptSuffix = ""
    for message in messages:
        promptSuffix += message['sender'] + message['body']
    prompt = promptPrefix + promptSuffix
    #print(prompt)
    return prompt

5.发送提示到ChatGPT

询问机器人的功能

def ask_chatGPT(prompt):
    response = bot.ask(prompt)
    print(response)
    return response

6. 使用 ChatGPT 响应回复发件人

发信息

def  sender ( phone_number, response ): 
    send_message(response, phone_number, False )

7.自动化 要让脚本无限期运行,请将除用户输入之外的所有函数包装到一个 while 循环中,并添加一些逻辑来检查时间间隔并检查最后一个发送者是否是我。我们不要在人们回复之前向他们发送垃圾邮件

from chatgpt_wrapper import ChatGPT
from imessage_tools import read_messages, print_messages, send_message
import time
bot = ChatGPT()

def user_inputs():
    #ask the user for what phone number they want to send/read messages from
    phone_number = input("What phone number would you like to send/read messages from? (format: +12223334444): ")
    #ask the user for the path of their iMessage database
    chat_db = input("What is the path to your iMessage database? (/Users/userName/Messages/chatDB): ")
    #ask the user for the name of the person they are texting
    person = input("What is the name of the person you are texting? (format: FIRSTNAME): ")

    #default values for testing, uncomment the below 3 lines and comment out the above 3 lines to use the default values``
    
    chat_db = "/Users/userName/Library/Messages/chat.db"
    phone_number = "+13034768549"
    person = "Albert"
    
    return [phone_number, chat_db, person]
dynamicData = user_inputs()
def check_last_sender(messages):
    last_sender = messages[0]['sender']
    print ("The last sender was: " + last_sender)
    return last_sender

while True:
    def get_recent_messages(phone_number, chat_db, person):
        # Phone number or label for "you"
        self_number = "Me"
        # Number of messages to return
        n = 15
        # Read the messages
        messages = read_messages(chat_db, n=n, self_number=self_number, human_readable_date=True)
        # Filter messages where phone_number is phone_number
        messages = [message for message in messages if message['phone_number'] == phone_number]

        #if is_from_me is true, then set messages.sender to "ME: " and if is_from_me is false, then set messages.sender to "THEM: "
        for message in messages:
            if message['is_from_me'] == True:
                message['sender'] = " ME: "
            else:
                message['sender'] = person + ": "
        return messages

    def build_prompt(messages, person):
        prompt = ""
        promptPrefix = "Write a reply for me to the following text message message conversation. The reply must be less than 280 characters so be very concise. Do not use quotations in your resposne. Do not use a greeting. The conversation is between me (KELLY) and a friend (" + person + "). Do not use words KELLY or "+person+". Messages from KELLY begin 'KELLY: ' and messages from "+person+" begin with '"+person+"': .The oldest messages are last. The most recent messages are first. The tone in the reply should be friendly, supportive, and encouraging. The style should be casual and informal. You may ask 1 or 2 follow up quetsions if needed. The message should continue from the most recent messages and be imformal. The most recent messages contain relevant topics. Choose relevant topics. Write a reply to the following conversation....."
        promptSuffix = ""
        for message in messages:
            promptSuffix += message['sender'] + message['body']
        prompt = promptPrefix + promptSuffix
        #print(prompt)
        return prompt

    def ask_chatGPT(prompt):
        response = bot.ask(prompt)
        print(response)
        return response

    def sender(phone_number, response):
        send_message(response, phone_number, False)


    recent_messages_for_number = get_recent_messages(dynamicData[0], dynamicData[1], dynamicData[2])
    if check_last_sender(recent_messages_for_number) == " ME: ":
        print("I am the last sender, so I will not respond to myself.")
        time.sleep(25)
        continue
    else:
        chatGPT_Prompt = build_prompt(recent_messages_for_number, dynamicData[2])
        chatGPT_response = ask_chatGPT(chatGPT_Prompt)
        sender(dynamicData[0], chatGPT_response)
        time.sleep(25)

在行动+总结

使用如图所示的脚本……我得到了不同的结果。玩提示是关键。我正在开发第二个版本,它将使用 JSON 结构来提示 ChatGPT 并显着提高一致性。

当您发出多个请求时,此处使用的 ChatGPT Python API 会维护一个会话bot.ask()。我发现最好告诉它你想要什么,问它是否理解,然后单独提供文本。我还发现 ChatGPT 可以按原样读取 JSON 消息,并且不需要像上面那样构建提示

这是我最近与朋友的谈话中的一个例子

鉴于:

我们发送:

推荐书单

《Python从入门到精通(第2版)》

《Python从入门到精通(第2版)》从初学者角度出发,通过通俗易懂的语言、丰富多彩的实例,详细介绍了使用Python进行程序开发应该掌握的各方面技术。全书共分23章,包括初识Python、Python语言基础、运算符与表达式、流程控制语句、列表和元组、字典和集合、字符串、Python中使用正则表达式、函数、面向对象程序设计、模块、异常处理及程序调试、文件及目录操作、操作数据库、GUI界面编程、Pygame游戏编程、网络爬虫开发、使用进程和线程、网络编程、Web编程、Flask框架、e起去旅行网站、AI图像识别工具等内容。所有知识都结合具体实例进行介绍,涉及的程序代码都给出了详细的注释,读者可轻松领会Python程序开发的精髓,快速提升开发技能。除此之外,该书还附配了243集高清教学微视频及PPT电子教案。
《Python从入门到精通(第2版)》【摘要 书评 试读】- 京东图书京东JD.COM图书频道为您提供《Python从入门到精通(第2版)》在线选购,本书作者:明日科技,出版社:清华大学出版社。买图书,到京东。网购图书,享受最低优惠折扣!icon-default.png?t=N7T8https://item.jd.com/13284890.html

精彩回顾


《事半功倍,使用ChatGPT编写Python函数》

超快速,使用ChatGPT编写回归和分类算法

《如虎添翼,将ChatGPT和Python结合起来!》

《ChatGPT优化Python代码的小技巧》

《使用ChatGPT提升Python编程效率》 

微信搜索关注《Python学研大本营》,加入读者群

访问【IT今日热榜】,发现每日技术热点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值