3

用 Python 自动创建 Markdown 表格 - 每天5分钟玩转 GPT 编程系列(4)

 10 months ago
source link: https://www.cnblogs.com/daniel-hutao/p/gpt-5-min-4-python.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1. 他们居然问我要 Prompts

早几天我用 GPT-4 写了一个 Golang Worker Pool 程序,测试了一把居然性能爆表,然后“他们”就问我要完整的 prompts,想看下到底是 GPT-4 写出来的 GoPool,还是我自己手撕的。(我哪有手撕的本事,你们还真是看得起我。)

GoPool 是一个 95% 代码用 GPT-4 生成的高性能、功能强大且简单易用的 Golang Worker Pool 开源库,详细介绍可以参考这篇文章:

好吧,那我就搞一个网站,把 GoPool 开发过程中用到的 prompts 以及对应的 commits 都列在一起,开源出去!

首先我需要在网页里加这样一张表格:


998740-20230804152837627-1834780094.png

没错,表格的原始文本得是 Markdown 格式的,然后被转成 HTML(我总不能手撕 HTML 表格吧),放到 pro.devchat.ai

这个表格对应的 Markdown 最终会长这样:

998740-20230804152847935-708088189.png

混乱不?抓狂不?我反正写了一行就放弃了:

| Commit                                                                                                                              | Commit Hash | Author                                       | Prompts with GPT                                                          | 给 GPT 的 Prompts                                                             |
| :---------------------------------------------------------------------------------------------------------------------------------- | :---------- | :------------------------------------------- | :------------------------------------------------------------------------ | :---------------------------------------------------------------------------- |
| [Add README.md and go.mod for GoPool project](https://github.com/devchat-ai/gopool/commit/a6315922a026b4290b0b1cd54e95b25e93538047) | a631592     | [Daniel Hu](https://github.com/daniel-hutao) | [Prompts with GPT](./commits/a6315922a026b4290b0b1cd54e95b25e93538047.md) | [给 GPT 的 Prompts](./commits/a6315922a026b4290b0b1cd54e95b25e93538047_zh.md) |

写完一行,老眼昏花,内心久久不能平静。这种“重体力活”怎么能忍?

你想象一下我要到 GitHub 上的 GoPool 项目 commits 列表里,看着接近30个 commits,一个个去摘抄这些信息:

  1. Commit message 第一行;
  2. Commit hash 前7位;
  3. Author 信息;
  4. 完整的 commit 地址;

然后在本地创建和 commit 地址对应的一个个 Markdown 文件,类似:

  • a6315922a026b4290b0b1cd54e95b25e93538047.md
  • a6315922a026b4290b0b1cd54e95b25e93538047_zh.md

最后还要在这些 Markdown 文件里将这个 commit 对应的 Prompts 填进去,让大家看到这个效果:


998740-20230804152902351-1571301347.png

真他喵不是人干的活。赶紧冲一杯咖啡提提神,搞不完今天下不了班了。

有事 GPT 干,没事干 GPT,有事 GPT 干,没事干 GPT,有事 GPT 干,没事干 GPT……

对呀,脏活累活,一律祭出 GPT!

2. 让 GPT-4 来写代码

直觉上这个任务适合用 Python 脚本来实现。不过我并不熟悉 Python,也就是说如果 GPT-4 给的 Python 代码能用,我就用。反之不能用,我就不得不自己用 Golang 来写了。

下文通过 DevChat 和 GPT-4 交互。DevChat 是一款开源的 VS Code 插件,默认对接 GPT-4,现在还在公测阶段,可以通过这个地址免费注册一个 key,然后不需要“ke xue 上网”就能用上 GPT-4 了。

关于 DevChat 的详细介绍欢迎跳转这篇文章:

2.1 我对 DevChat 说

998740-20230804153016242-1629958094.png

如上图所示,在问这个问题的时候我加了一个“上下文”,也就是一行 Markdown 表格示例。

完整的问题如下:

我需要你写一个 python 脚本,脚本中要实现的功能是拉取GitHub上特定项目的Commit记录,然后写入本地特定文件中。

  1. 比如项目的 org 是 devchat-ai,name 是 gopool,那么你要找的项目是 https://github.com/devchat-ai/gopool
  2. 你要获取这个项目的main分支的所有 commits 历史,按照时间顺序依次写入本地的 devchat-ai/gopool/index.md 的中,但是你要考虑脚本重复执行需要幂等,所以你应该追加内容,而不是覆盖。
  3. 我已经将 index.md 的例子发给你,你不需要管里面的开头描述部分,只需要在文件后半部分的 Markdown 表格上操作。

2.2 DevChat 回答

要实现这个需求,我们需要做以下几步:

  • 使用 GitHub API 来获取特定项目的 commit 历史记录。
  • 解析 API 返回的数据,提取我们需要的信息,如 commit hash,author 等。
  • 将这些信息以 Markdown 表格的形式追加到本地的 index.md 文件中。

这里有一个 Python 脚本的示例,它使用了 requests 库来发送 HTTP 请求,使用 pandas 库来处理和写入 Markdown 表格。如果你的环境中没有这两个库,你可以使用 pip 来安装它们:

pip install requests pandas

然后,你可以使用以下的 Python 脚本来实现你的需求:

import requests
import pandas as pd
from typing import Dict, List

def get_commits(org: str, repo: str) -> List[Dict[str, str]]:
    url = f"https://api.github.com/repos/{org}/{repo}/commits"
    response = requests.get(url)
    response.raise_for_status()
    commits = response.json()
    return [
        {
            "Commit": commit["commit"]["message"],
            "Commit Hash": commit["sha"],
            "Author": commit["commit"]["author"]["name"],
        }
        for commit in commits
    ]

def append_commits_to_file(commits: List[Dict[str, str]], file_path: str) -> None:
    df = pd.DataFrame(commits)
    with open(file_path, "a") as f:
        f.write(df.to_markdown(index=False))

def main():
    org = "devchat-ai"
    repo = "gopool"
    file_path = "devchat-ai/gopool/index.md"
    commits = get_commits(org, repo)
    append_commits_to_file(commits, file_path)

if __name__ == "__main__":
    main()

这个脚本首先从 GitHub API 获取 commit 历史记录,然后将这些记录追加到本地的 index.md 文件中。注意,这个脚本只会获取最近的 30 条 commit 记录,因为 GitHub API 的默认分页大小是 30。如果你需要获取更多的记录,你需要处理 API 的分页。

此外,这个脚本没有处理 API 的错误和异常,你可能需要根据你的需求来增加错误处理和异常处理的代码。

管它三七二十一,对着操作一波再说。运行后我得到了这个结果:

998740-20230804153136121-1120495291.png

一口老血啊…… 克制,不动怒,继续“友好”沟通。

2.3 我又对 DevChat 说

hash 我只需要保留7位,Commit Message 只需要保留第一行。最后的结果需要是这样的:

| [Add GoPool and Worker structures](https://github.com/devchat-ai/gopool/commit/ee0b38ba85830d07046145583c2a568905d9839f) | ee0b38b | [Daniel Hu](https://github.com/daniel-hutao) | [Prompts with GPT](./commits/a6315922a026b4290b0b1cd54e95b25e93538047.md) | [给 GPT 的 Prompts](./commits/a6315922a026b4290b0b1cd54e95b25e93538047_zh.md) |

2.4 DevChat 的第二轮回答

了解了,我们需要对获取到的 commit 数据进行一些处理,以满足你的需求。具体来说,我们需要:

  • 将 commit hash 截取为前 7 位。
  • 只保留 commit message 的第一行。
  • 生成 commit 的链接。
  • 生成 commit 的作者的链接。

以下是修改后的 Python 脚本:

import requests
import pandas as pd
from typing import Dict, List

def get_commits(org: str, repo: str) -> List[Dict[str, str]]:
    url = f"https://api.github.com/repos/{org}/{repo}/commits"
    response = requests.get(url)
    response.raise_for_status()
    commits = response.json()
    return [
        {
            "Commit": f"[{commit['commit']['message'].split('\n')[0]}](https://github.com/{org}/{repo}/commit/{commit['sha']})",
            "Commit Hash": commit["sha"][:7],
            "Author": f"[{commit['commit']['author']['name']}](https://github.com/{commit['author']['login']})",
            "Prompts with GPT": f"[Prompts with GPT](./commits/{commit['sha']}.md)",
            "给 GPT 的 Prompts": f"[给 GPT 的 Prompts](./commits/{commit['sha']}_zh.md)",
        }
        for commit in commits
    ]

def append_commits_to_file(commits: List[Dict[str, str]], file_path: str) -> None:
    df = pd.DataFrame(commits)
    with open(file_path, "a") as f:
        f.write(df.to_markdown(index=False))

def main():
    org = "devchat-ai"
    repo = "gopool"
    file_path = "devchat-ai/gopool/index.md"
    commits = get_commits(org, repo)
    append_commits_to_file(commits, file_path)

if __name__ == "__main__":
    main()

这个脚本现在会生成你需要的 Markdown 表格,并将其追加到 index.md 文件中。

很快 DevChat 就给出了回答,不过这次的代码有语法错误:

998740-20230804153151357-950554219.png

一开始我就说了,我并不熟悉 Python。所以这里看似一个挺简单的错误,反正我改不来。所以,继续问 GPT-4 咯。

2.5 我再次对 DevChat 说

Escape sequence (backslash) not allowed in expression portion of f-string prior to Python 3.12

2.6 DevChat 回答

对不起,我犯了一个错误。在 f-string 表达式部分,我们不能使用反斜杠作为转义字符。在这种情况下,我们可以先将 commit message 分割成行,然后在 f-string 中使用第一行。以下是修改后的代码:

import requests
import pandas as pd
from typing import Dict, List

def get_commits(org: str, repo: str) -> List[Dict[str, str]]:
    url = f"https://api.github.com/repos/{org}/{repo}/commits"
    response = requests.get(url)
    response.raise_for_status()
    commits = response.json()
    commit_data = []
    for commit in commits:
        commit_message_title = commit['commit']['message'].split('\n', 1)[0]
        commit_data.append({
            "Commit": f"[{commit_message_title}](https://github.com/{org}/{repo}/commit/{commit['sha']})",
            "Commit Hash": commit["sha"][:7],
            "Author": f"[{commit['commit']['author']['name']}](https://github.com/{commit['author']['login']})",
            "Prompts with GPT": f"[Prompts with GPT](./commits/{commit['sha']}.md)",
            "给 GPT 的 Prompts": f"[给 GPT 的 Prompts](./commits/{commit['sha']}_zh.md)",
        })
    return commit_data

def append_commits_to_file(commits: List[Dict[str, str]], file_path: str) -> None:
    df = pd.DataFrame(commits)
    with open(file_path, "a") as f:
        f.write(df.to_markdown(index=False))

def main():
    org = "devchat-ai"
    repo = "gopool"
    file_path = "devchat-ai/gopool/index.md"
    commits = get_commits(org, repo)
    append_commits_to_file(commits, file_path)

if __name__ == "__main__":
    main()

这个脚本现在应该可以正常运行,生成你需要的 Markdown 表格,并将其追加到 index.md 文件中。

我再次运行了下这个代码,终于,表格出来了。

2.7 最后效果

后面我还继续聊了几轮,让 GPT-4 把本地创建表格中出现的 Markdown 文件的逻辑也加上了,所以最后我顺利的通过 Python 脚本生成了下图中的这个巨大无比的表格,以及对应的左侧五十多个 Markdown 文件。

998740-20230804153205891-1802787003.png

Python 代码最终版本如下:

import os
import requests
import pandas as pd
from typing import Dict, List

def get_commits(org: str, repo: str) -> List[Dict[str, str]]:
    url = f"https://api.github.com/repos/{org}/{repo}/commits"
    response = requests.get(url)
    response.raise_for_status()
    commits = response.json()
    commit_data = []
    for commit in commits:
        commit_message_title = commit['commit']['message'].split('\n', 1)[0]
        commit_data.append({
            "Commit": f"[{commit_message_title}](https://github.com/{org}/{repo}/commit/{commit['sha']})",
            "Commit Hash": commit["sha"],
            "Author": f"[{commit['commit']['author']['name']}](https://github.com/{commit['author']['login']})",
            "Prompts with GPT": f"[Prompts with GPT](./commits/{commit['sha']}.md)",
            "给 GPT 的 Prompts": f"[给 GPT 的 Prompts](./commits/{commit['sha']}_zh.md)",
        })
    return commit_data

def append_commits_to_file(commits: List[Dict[str, str]], file_path: str) -> None:
    df = pd.DataFrame(commits)
    df['Commit Hash'] = df['Commit Hash'].apply(lambda x: x[:7])
    with open(file_path, "a") as f:
        f.write(df.to_markdown(index=False))

def create_commit_files(commit: Dict[str, str], directory: str = "devchat-ai/gopool/commits") -> None:
    """
    Create markdown files for each commit.
    """
    for suffix in ["", "_zh"]:
        file_path = os.path.join(directory, f"{commit['Commit Hash']}{suffix}.md")
        if not os.path.exists(file_path):
            with open(file_path, "w") as f:
                f.write("")

def main():
    org = "devchat-ai"
    repo = "gopool"
    file_path = "devchat-ai/gopool/index.md"
    commits = get_commits(org, repo)
    append_commits_to_file(commits, file_path)
    for commit in commits:
        create_commit_files(commit)

if __name__ == "__main__":
    main()

3. 他们居然让我要写总结

那就总结一下吧。

今天挑战的是让 GPT-4 用我不熟悉的 Python 语言来完成一个自动化任务。

像这种大表格的编辑以及相应的50+个文件的创建,手动操作是很容易出错的,这类活天然适合交给 Python 脚本。不过放在以前,可能这种活我只能选择用自己熟悉的其他高级语言来完成,可以预见 Python 50 行代码对应的 Golang 估计得小100行了。100行啊,一杯水,一包烟,一个脚本写半天。不过现在可以让 GPT-4 来完成这类工作。

几轮“自然语言沟通”就搞定了,算下来可能花了不到30分钟,大约就是:0.5h VS 2.5h 吧。

又是 N 倍效率的一天,马克杯里的咖啡都还没凉,事情又干完了。呼…… 下班,等吃饭!

998740-20230804153222024-272715732.jpg

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK