标签: AI

  • 【视频教程】开发AI求职助手,一起走上全职远程之路(一)

    【视频教程】开发AI求职助手,一起走上全职远程之路(一)

    新系列简介

    开个新坑。其实类似的想法我去年就有了,但是一直没有做,除了懒之外,很大的问题就是我不会爬虫。而且在我的认识里,爬虫是一个很依赖后续维护的工作,不符合我写完能用很久的预期。不过我最近在思否看到 亮数据,似乎可以很好的弥补我的不足。于是我决定先把坑挖起来。

    本文是系列的第一集,会先介绍我的动机(找到全职远程工作);我设想的做法;介绍亮数据;分析我的代码(踩坑经验);最终初步抓取到 Vuejobs 的远程数据。

    创造新工具帮我们找到远程工作

    如何找到全职远程工作

    全职远程工作有很多好处,比如可以去泰国曼谷耍泼水节,只要安排好时间,工作娱乐两不误。很多朋友问我,怎么找到一份全职远程的工作,我有几个建议分享给大家:

    1. 不断提升自己,扩展技术栈。因为全职远程跟大公司做螺丝钉不同,更倾向于独当一面,所以你的技术栈越全面,能做的工作越多,找到全职远程工作的可能性也越大。
    2. 利用现在的工作机会,给自己打造可靠的个人品牌,形成良好的合作团队,利用好自己的工作副产品,给独立工作或者远程工作做好准备。
    3. 培养自己的自控力。远程工作比较重视结果,你越能控制自己,稳定输出,找到远程的机会也就越多。

    除去以上三点,今天要重点分享的,是如何找到尽可能多的远程工作机会;或者,要找到你需要弥补、增强的能力。这个过程,我们要学会利用好各种工具服务和提升自己。如果没有现成的工具,我们就自己开发需要的工具。

    关于亮数据(Bright data)

    我前几天在思否上看到一个小广告,叫 亮数据。看介绍,我发现它能很好的帮助我补强网络爬虫、内容抓取的能力。尤其是看其功能设计,能解决我前面说的“重维护”问题,我觉得值得一试。

    至于做什么,我觉得以前设想的“ 应用创意:AI 求职助手”很合适。只不过,我早先设想时,把简历上传、AI 分析放在第一步;现在我觉得,可以把工作机会获取、AI 分析与提示,放在第一步。即:

    1. 有一个爬虫,帮我四处收集招聘信息,尤其是全职远程
    2. AI 帮我分析 JD,并根据我的基本简历,生成求职信+针对性简历,投递
    3. AI 帮我准备面试,直至入职

    编写爬虫脚本

    想好就动手。今天的目标是做完第一步,也就是数据抓取,后面再继续做 AI 分析JD 和处理简历。我起初想用他们家的在线 IDE,尝试之后发现不太符合要求,调试起来也比较费力,遂放弃,改用亮数据浏览器(Scraping browser)。

    亮数据浏览器是他们部署在全球的服务,我们可以用 puppeteer-core 连接,然后发起请求,抓取目标网页。他们会帮我们解决一般的访问限制,甚至宣称可以通过验证码(我没试)。我觉得这样设计最大的好处是,我们可以在本地简单的开发爬虫脚本,然后直接上线使用,可以与既有的开发习惯轻松融合。

    这一步的脚本很简单,我就不详细介绍了,大家可以直接在 我的 GitHub 仓库 里查看;我的视频里也有详细讲解。这里只列举一下我踩过的坑:

    1. 连接亮数据浏览器需要使用 puppeteer-core,不能用 puppeteer,否则会超时,不知道为什么。
    2. 使用前必须付费,或者,请大家用我的 分享链接 完成注册,这样你就有 $10 的试用额度
    3. 因为 puppeteer-core 要使用 WebSocket 连接,之后每步操作也都要走 WS,所以网络就非常重要。我建议大家用云服务器来跑,我用的是博客服务器,美国 DO。
    4. 每次请求 打开一个网页,抓取一些信息。如果需要打开多个网页,就多次连接亮数据浏览器、打开页面

    配置亮数据

    调试好脚本之后,我们需要把它连接到亮数据浏览器。请大家使用我的 分享链接 完成注册,这样你就有 $10 的额度可以使用。

    登录之后,在 代理&爬虫基础设施 里找到“亮数据浏览器”,点击“开始使用”按钮,创建可用实例。

    如果参考我的脚本,可以先复制 .env.example.env,然后把用户名密码放在 BRIGHT_DATA_AUTH,把主机放在 BRIGHT_DATA_SBR_WS_ENDPOINT 即可完成配置。如果你自己编写脚本,也请注意让配置生效。

    至此,再找一台合适的服务器,就能完成抓取了。可能 Vue jobs 平日的访问量也不大,所以没有什么防护策略,至少我的简单脚本用起来没问题。如果未来遇到难抓的网站,我再尝试进阶用法。

    视频教程

    小结

    时间关系,今天先介绍第一部分,也是我最不熟悉的爬虫部分。后面会集成 AI 分析和记入数据库,那个我就比较熟了。

    对远程工作、爬虫开发、全栈开发等有兴趣、有问题的同学,欢迎留言讨论。也请大家多多支持我的文章和视频,给我动力尽快更新下一期。


    请大家使用我的分享链接注册 亮数据,这样你我都能获得 $10 的使用额度,我也会尽快更新下一篇。

  • 尝试用 DALL-E 3 制作漫画《姆伊姆伊》

    尝试用 DALL-E 3 制作漫画《姆伊姆伊》

    DALL-E 3 发布有一阵子了,今天跟一个朋友聊到 AI 制作漫画,我突然想起来,还没测试过 DALL-E 3 的漫画制作能力,所以简单试了试。我认为它的表现不错,做绘本类的产品应该问题不大。下面是我的作品。

    Once upon a time, there is a dog, his name is Muimui

    (这是我早年帮孩子写的英文演讲的作文。)

    Once upon a time, there is a dog, his name is Muimui. Muimui is a corgi.

    Muimui is a good dog, everything is fine except that he like barking very much.

    When I cleaning the room, he barks.

    When my mom and dad talk to me loudly, he barks.

    One day, I was eating hot dog bread, I like hot dog bread.

    Suddenly, my mom said to me: “Do you finish your homework?”, when I turn my head to her, I fall the hot dog bread down to the ground!

    (这张图我尝试了很多次,都没法把说话气泡指向妈妈。)

    I was shocked, and my hot dog bread fell to the floor.

    Muimui run fast to the hot dog bread immediately, grabbed the bread and happily ate it.

    This time, he didn’t bark at all!

    简评 DALL-E

    DALL-E 作为 OpenAI 的产品,它最大的优势就是可以很好的理解我们的 Prompt,不需要我们事先学习模型训练时的标记,大大降低了普通用户使用 text2img 功能的难度。Prompt 会试图把我们的 Prompt 扩写得更全面,比如第一幅图,实际生效的 Prompt 是:

    Watercolor painting of Muimui the corgi looking out of a large window in a comfortable home, with curtains gently swaying.

    如果我们要调整图片,可以继续跟 DALL-E 对话,它会自动帮我们整合 Prompt,然后输出新的图片。我们可以要求它基于某个图片进行修改,以便产出我们想要的效果。

    如果你仔细观察,会发现上面几张图片里,有几张里面的角色存在明显的特征,比如坐在沙发上的那个小男孩,戴眼镜穿衬衣,卡其色的裤子都很接近,我不知道它是怎么做到的,不过如果能维持这个稳定性,可能真的可以用来画漫画。

    我并没有尝试对角色稳定性做出约束,比如什么样的发型、什么样的衣服等,不知道会不会对输出的结果产生影响。

    不过 DALL-E 也有劣势:我们不能自己训练小模型(Lora),所以大家的产出可能会千篇一律。另外 DALL-E 有很多“安全性”预设 Prompt,我们不能随意要求它画出一些 NSFW 的作品。

    总结

    不知道读者觉得这个作品如何?欢迎留言讨论。

  • AI 产品开发小科普

    AI 产品开发小科普

    今天有个朋友问我,有没有本地运行过 AI 模型,他想做一个 text2sql 工具,自动分析数据库,然后就能自然语言查询,并进一步做智能分析,乃至逻辑推演。我分享了一些知识、理解给他。我发现,虽然我一直觉得自己懂得少,没啥可分享的;但是总有朋友比我懂得更少,需要学习和纠正。所以写一篇小科普,希望帮到大家。

    text2sql 产品的问题

    类似的产品比较多见,比如早期的明星作品 ChatExcel.com,现在 TiDB、Supabase 也都提供了 AI 生成 sql 的功能。不过我觉得都不好用,原因如下:

    1. 控制不住幻想。
    2. 没法很好的理解数据库结构,无法根据我的那些可能并不准确的字段名推断表之间的关系,并合理的输出 SQL。
    3. 没有根据环境微调,输出的代码可能没法直接跑。比如 TiDB 也会输出 PG SQL。反之亦然。

    幻想”是目前 LLM 最常见的问题。我们可以把 LLMs 理解成小学生,他们迫切地想满足用户(老师、家长)的要求(或者说他们被造出来就是这个目的)。所以,假如用户提出的需求他们无法满足,他们也不愿意给出零回答或者负面回答(“我不知道”、“我不会”、“不太可能”,等等),而是编造一个答案。在某些情况下,尤其是自然语言交互时,幻想答案可能问题不大;但是在编程领域,幻想答案就完全不可接受了。

    尤其是,如果这些工具无法预先理解数据库结构、也无法判断执行环境,幻想就会频频发生在各种不同的地方,让人防不胜防。

    朋友的想法

    他想在本地跑 Code Llama 模型,实现 text2sql。他打算做一些微调,以便突破我前面说的问题。

    之所以想在本地跑,是希望借助苹果 CPU 内存数量大的架构优势,突破 GPT 的上下文容量限制。

    他不想从 prompt 入手,主要觉得太 low,不够技术。

    我的建议

    我的观点则相反:一定要从 prompt 入手。Prompt 不是玄学,事实证明,合理优化 prompt,可以得到更好的结果。

    其次,不管哪家模型,都已经做好了完整的基础设施建设,基本上不会在生成端遇到问题。开发者只需要关心自己的业务逻辑开发。

    从 text2sql 的角度来看,fine-tuning 当然可以得到最好的结果,但是 fine-tuning 之后,数据库结构就跟模型绑定了。否则的话,一定要想办法把数据库结构解释给 LLM,也就是说,一定要把数据结构放进 prompt。这是基本原理,也意味着我们不需要绕开 prompt engineer。

    总结起来,我的看法是,如果要做这样的产品,应该:

    1. 想办法解析表结构、数据库结构
    2. 把解析结果,准确描述给 LLM(prompt)
    3. 解析用户的要求,尽量还原成数据库结构
    4. 然后一起交给 LLM 来执行

    这里就存在一些难点:

    1. 理解数据结构
    2. 理解用户的需求,和数据结构建立关联
    3. 输出正确的语句,不要出现幻觉
    4. 输出稳定,能够被你的后续处理代码正确处理

    如果模型比较好,可以节省(3)的时间。但是我猜测如果参数少,比如 7b、13b,那么(1)(2)都会很麻烦。所以,公共模型好,还是自己微调的模型好,最终效果不好判断。

    总结

    目前 LLM 尚且无法独立完成工作,应该说是我们开发者的幸运。不过,基于 LLM 开发应用跟以往不同,不太好套用以往的经验,比如上来就自建+调优。

    我建议大家要对 LLM 的基本原理有一些了解,知道 LLM、fine-tuning、embedding+searching 等之类的功能是怎么实现的,能解决什么问题,会有哪些缺陷。这样就能选择最快捷方便有效的方案。

    希望我那个朋友一切顺利。如果各位读者对 LLM 或者应用开发有什么问题,欢迎留言讨论。

  • 应用创意:AI 求职助手

    应用创意:AI 求职助手

    好久没发应用创意。我之前想做一个 AI 简历工具,琢磨来琢磨去,我觉得只关注简历是不对的,太狭隘。简历本身价值很有限,作用也不太大,用户关注简历的时间很短,做简历很难做成一个长期项目,用户大概率会用完就走,也不太容易会付费。

    所以必须升级成 AI 求职助手,才有做的必要。这里把我的想法放出来跟大家交流一下。

    首先,我们来想一想,在求职中,目前通行的各环节作用是什么?我的观点是:

    1. 简历,证明我适合这个岗位。
    2. 面试,证明我的简历所言非虚。
    3. 上家公司的薪资,证明我值得这份钱。

    具体的分析可以参见 从招聘方的角度理解求职,本文不再详叙。

    有些同学不会写简历,我认为一方面因为不理解简历的作用,另一方面,现阶段各种写简历的工具过分关注于简历本身,而缺少对于写好简历的教育。

    另外,写好简历只是第一步,后面还有面试和入职,现在也缺少相应的工具来帮助用户。其实“刷题”这个需求已经被满足得很好了,但是“模拟面试”的工具,感觉还不太够。

    再及,因为我自己是远程工作,所以我比较关注这个领域。我发现很多自由职业者、独立开发者,其实也有做简历的需要。未来可能会有很多开发者不仅仅面向一份全职全时工作,而是同时在多个领域多个方向做开发,那么同时维护多份简历也很常见。

    所以我想创建这样一款工具:

    1. 不要求用户一次性完成一份简历,而是鼓励用户不断添加自己的工作履历和项目经验。
    2. 根据一些既定规则,判断一段工作履历和项目经验的描述是否合格、有何改进空间,提升每段经历的表达质量。
    3. 当我决定投递简历的时候,AI 求职助手会根据招聘目标、JD,帮我自动生成一份高质量的简历。
    4. 如果我的经历经验跟目标岗位要求不符,它会提醒我,还会告诉我应该补足哪些的知识。
    5. 它还可以针对目标岗位,给出模拟面试题,我做完面试题之后,它会给我打分。
    6. 面试之后,我们可以反馈面试结果,让 AI 求职助手帮我们判断面试表现,复盘整体表现,提升下次面试的表现。
    7. 它还可以主动出击,去全网搜集适合我的 JD,主动帮我们生成、投递简历,帮我们准备面试,帮我们复盘,等等。

    短期内这样的面试助手只会针对 Web 前端、全栈这样我最熟悉的岗位,未来可以的话,再慢慢扩展到更多的岗位(需要其它岗位上经验丰富的同学来充当内容编辑)。

    我希望这样的产品是订阅制的,按月计费。考虑到可能需要使用 GPT-4,我觉得定价太低也不行,估计得在 100~200 这个区间吧。不知道各位读者有什么意见、建议,欢迎在评论里告诉我。

    希望大家都能找到满意的工作。

  • 我的 AI 学习一周/月总结:四月三场 Hackathon

    我的 AI 学习一周/月总结:四月三场 Hackathon

    这篇文章在我草稿箱里躺了一个月,因为种种原因,内容不够充足,就一直没发。周末想了想,还是补一些内容把它发出来。经过连续几个月的高强度信息获取、吸收,我觉得现在已经进展到必须躬行实践的阶段。未来类似这种信息汇编、浅尝辄止的博客会减少,还是回到案例分析、实践分享的老路上吧。

    最近几周,我一直在努力 release 产品,先死磕计费系统、然后跟 Chrome Extension 在各个网站里搏斗,基本上眼睛一睁一闭,一天就过去了;与此同时,之前报名参加 Hackathon 开始进入正赛阶段,最近三周一周一场,时间非常紧张,周更文章根本来不及……

    不过笔记该写还得写,近期也学到一些东西,记一记。

    我不看好 AutoGPT

    近期最火的产品应该是 AutoGPT。顾名思义,AutoGPT 就是在 ChatGPT 的基础上,让 AI 自己决策、自己尝试、自己评估。这样,我们只需要告诉 AI 我们的需求,然后等待,就能拿到自己需要的东西。

    理想状态,尤其是电影里,这样当然是可行的,然后天网就来了……但是我认为,现阶段这种尝试就是纯烧钱,效果跟猴子打字机差不多。我甚至怀疑这个产品是 OpenAI 自己放出来做压力测试的。

    ChatGPT 的确从人类生产的文本知识里获得到了很多经验,以至于可以回答比如“我想做一个XXX,我应该怎么做”这样的问题。我们普通人多半也是这么开始工作的:先找出一些方案,然后尝试这些方案;遇到问题就再想方案,再解决;重复若干次,直至达成主要目的。似乎用 ChatGPt 也能做到这一点。

    但是我们的决策大量依赖经验、和人类与生俱来的直觉(生物进化 37 亿年得到)。很多时候,经验丰富的老手和新人之间的区别,就是判断哪些方向可以尝试、哪些方向应该优先尝试。所以我们可以把 ChatGPT 当成一名新晋毕业生,刚刚学了一堆知识,但是实操经验几乎为零,然后你告诉他:按照你的想法随便搞,预算不限。结果可能好么?

    我看好在 ChatGPT 等 LLM 加持下,胶水层、DSL、专家系统能够达到新高度,但我不看好 AutoGPT 这样的无头苍蝇。

    OpenAI 发布 Embedding 指南

    openai-cookbook/Question_answering_using_embeddings.ipynb at main · openai/openai-cookbook · GitHub

    昨天 OpenAI 发布了 Embedding 指南,其中一个要点:为什么(Embedding)搜索要好于微调(fine-tuning)?

    文中有个比喻:模型权重就像长期记忆,微调模型就像是为了 闭卷 考试而学习,到了考试的时候,记忆还是会混乱,还是会做错题。搜索就像是开卷考试,通过携带信息(现场翻书),答案会更准确,通常得分也更高。

    显然,使用 Embedding 搜索时,发送的内容会更多,能用到的上下文就会更受限,而且价格会更高。所以最终怎么选择,需要我们自己权衡。

    这篇文章还提到了 Embedding 不适用的场合,以及如何 debug+调优,非常值得一看,推荐给大家。

    四月份参加三场 AIGC Hackathon

    四月连续参加三场 Hackathon,连续三周都在各种赶工,累得够呛,也是本系列文章搁置的原因。我在 复盘文章 里比较详细的记录了参赛过程和作品设计开发,感兴趣的同学可以去看看。简单来说,我们努力开发了一款 web app,叫做 拜拜,可以让用户在任何场合都能求神拜佛,并得到一些心灵的慰藉。

    目前我们已经让神佛可以用语音的方式跟信众交流,结合回声效果,实测效果不错,欢迎大家试用、反馈。

    下一步我们会添加用户体系,并先在大陆地区以外上线。大陆地区以内当然也不会放弃,不过要确保我们合法合规,肯定会慢很多。所以,一步一步来吧,顺利的话,我们希望今年能够提交到各种市场、平台上线;不顺利的话,把主要流程做出来跑通,找个公司卖掉也好。

    一些碎碎念

    我这两天再看 Supabase 的文档,发现它们在 Supabase AI 搜索的下面增加了这样一个补充说明:

    Supabase AI is experimental and may produce incorrect answers.

    Always verify the output before executing.

    看起来,利用 ChatGPT 提升文档可用性并非一帆风顺,乱编答案的问题可能会长期困扰我们。期待大家进一步的最佳实践。

    目前更大上下文规模的模型也不断放出,比如前两天公布的 Claude,支持 100K 上下文,大家可以试一试。

    AI 倦怠期

    ChatGPT 去年引爆行业,今年过完春节破圈,接下来整个 234 月,大家都沉迷于各种 AI 新技术无法自拔。终于,过完五一之后,舆论环境终于开始降温,我相信各位读者老爷跟我的感觉应该差不多吧。

    其实也很正常,密集的投入开发之后,目前 AI 技术能干什么、不能干什么、什么能干好、花多少钱能干好之类的边界,虽然不能说非常清晰吧,但是大概在哪里,大家应该都知道了。割韭菜的那些我们不聊,只说付出辛勤劳动就能有所收获的部分,其实也不太多,或者成本不低。

    所以最近新东西不太多,更多的则是降本增效,比如用小模型换取接近的效果,比如用开源产品替代闭源产品等等。我相信,这是技术发展的必然,也是新一波创新前的宁静,后面会更好。


    总结

    地球生物的身体是自然界进化了 37 亿年得到的,我们可以非常高效地使用资源,比如一个馒头,就够我们活蹦乱跳几个小时。但是当需求上升到一定阶段后,效率就要让位给绝对值,比如硬拉世界纪录,也只有区区 500+kg,但是大型机械随便就是几十吨。

    AI 其实复刻了这条道路。它在思想深度广度上,都不如人类;但是凭借现在的算力冗余,大力出奇迹,从另一个角度超越了人类。将来怎么走,不好说,希望我们能像使用机械一样,使用 AI。

    就目前的状况来看,AI 基础设施现在已经非常好了,应用层存在大量机会。我维持之前的判断不变,建议大家有机会多多接触,早日加入。

  • 使用 Vercel Edge Function 访问 OpenAI API 的注意事项

    使用 Vercel Edge Function 访问 OpenAI API 的注意事项

    从某天开始,OpenAI API 无法从国内直接访问。而且,也不是每个人都有自己的云服务器,能够搭建独立服务。那么,还有别的办法能比较容易的访问到 OpenAI 么?当然是有的,比如 Vercel Edge Function,或者 CloudFlare Edge Function。

    这里我准备结合前阵子的开发经验,分享一下使用 Vercel Edge Function 访问 OpenAI API 的注意事项,让新来的开发者能少走弯路。

    推荐阅读

    开始之前,我建议大家先花点时间了解一下 Edge Function,以及如何使用 Vercel Edge Function 开发 OpenAI 应用。因为我后面要分享的主要是踩过的坑,所以先系统性了解会好很多:

    Building a GPT-3 app with Next.js and Vercel Edge Functions

    官方教程,还有 Demo 网站GitHub 项目,非常友好。虽然是英文写的,不过并不难懂,实在不行就用 Edge 浏览器自带的翻译功能吧,建议大家好好学习英文。

    自有域名+CNAME 实现国内访问

    Vercel 给免费版用户也提供子域名+ SSL 证书,很多时候都够用,但可惜,vercel.app 大域名被墙了,连带所有子域名都无法访问。好在 Vercel CDN 在国内也还能用,所以我们只需要一个自己的域名即可。

    申请域名的选择有很多,国内几大云服务商都能注册,国外的域名供应商也可以放心使用。我比较常用的是 namecheap.com。便宜的比如 .xyz 域名首年只要几块钱,随便注册一个就能用。

    注册完域名之后,在 Vercel 后台找到自己的应用,在“Setting > Domains“里添加域名,然后 Vercel 会告诉你怎么配置 DNS。复制解析目标,在域名供应商 DNS 配置页面完成 CNAME 配置,稍等片刻,解析生效后,即可得到一个国内也能正常访问的域名。

    使用 Edge Function

    Vercel Edge Function 与我们日常开发的 node.js 服务器略有区别。它并非完整的 node.js,而是 Edge 基于 V8 专门打造的袖珍运行时,尽可能轻量化,裁剪掉很多系统 API。功能少,但是速度很快,几乎零启动时间。(我之前将它跟 Supabase 记混了,以为它也是基于 deno 的。)

    使用 Edge Function 的好处,简单来说:省运维;详细来说,大概有这么几点:

    1. 性能更好。比随便买个小水管强得多。
    2. 自带弹性伸缩。不管访问量怎么成长,都有 Vercel 集群帮我们自动伸缩。(当然可能需要付钱)
    3. 启动速度比 serverless 快很多,基本没有等待时间。
    4. 免费额度足够初期 MVP 验证。

    坏处当然也有。首先,Edge Function 里跑的是 TS,这就意味着很多兼容 JS 的开源仓库都不能用。其次,Edge Function 很多原生 API 都不支持,所以没有特意兼容的仓库也不能用。举个例子,要完成网络请求,大家最熟悉的 Axios 就不能用,只能用系统原生的 fetch

    解决超时问题

    由于算法原因,OpenAI API 返回数据的总时间可能比较长,而 Edge Function 的等待时间又限制得很严。所以如果等待 OpenAI 返回全部数据再渲染,可能因为等太久,在 Edge Function 这里会超时。

    解决方案就是使用流(stream)式传播。在这种情况下,OpenAI 会逐步返回结果(差不多一个单词一个单词这样蹦),只要在客户端进行组合,就能看到类似实时输入的效果。

    完整的范例代码上面的官方文章有,我就不复制粘贴了,大家注意就好。

    Edge Function 的流不是最初的流

    这里有个坑,虽然我们在 Edge Function 里获取了 OpenAI API 的流,然后转发出来,但实际上我们接收到的流并不是最初的流。最初的流里,每次发送的数据都是完整的 JSON 文件,可以直接解析;但是 Edge Function 里转发给我们的却是前后合并后随机切分的结果。

    于是我们必须重新整理响应体。大概方案如下:

    1. 在每次返回的响应体里找到两个 json 的连接处
    2. 截断,拿到前面的 json,解析,得到自己想要的数据
    3. 继续查找完整的 json,如果没有,则和下一次响应体连接起来处理

    核心代码如下:

    class fetchGpt {
      fetch() {
        // 前面的代码参考官方例子
        // 我从循环读取开始
        while (!done) {
          const { value, done: doneReading } = await reader.read();
          done = doneReading;
          if (!value) {
            break;
          }
    
          // readableStream 读出来的是 Uint8Array,不能直接合并
          if (chunkValue.length > offset) {
            lastValue = concatUint8Array(lastValue, value);
          } else {
            lastValue = value;
            offset = 0;
          }
          chunkValue = decoder.decode(lastValue);
          [finishReason, offset] = this.parseChunk(chunkValue, offset);
        }
      }
      parseChunk(chunk: string, offset = 0): [string, number] {
        let finishReason = '';
        let nextOffset = offset;
        while (nextOffset !== -1) {
          nextOffset = chunk.indexOf(splitter, nextOffset + 1);
          const text = nextOffset !== -1
            ? chunk.substring(offset, nextOffset)
            : chunk.substring(offset);
          try {
            const json = JSON.parse(text);
            const [ choice ] = json.choices;
            const { delta, finish_reason } = choice;
            const chunkContent = delta?.content || '';
            // 这里我把数据交给事件 和 pinia 处理
            this.emit(MessengerEvent.MESSAGE, chunkContent, json.id, json.created);
            this.store.appendTextToLastItem(chunkContent, {
              id: json.id,
              created: json.created,
              system: this.options.system || '',
            });
            finishReason = finish_reason;
            offset = nextOffset !== -1 ? nextOffset : chunk.length;
          } catch (e) {
            //- ignore
          }
        }
        return [finishReason, offset];
      }

    常见 API 使用错误

    大家都知道,OpenAI 按照请求响应的 token 数算钱。所以我就想精打细算,通过在请求参数里减少 max_tokens,尽量少返回些内容。

    事实证明这个做法不成立。首先,OpenAI 对请求的兼容性不高,max_tokens 如果是 NaN 或者带有小数,都会报错。其次,ChatGPT 很啰嗦,内容量少了,它不过瘾,就会反复要求继续(finish_reason: 'length'),尤其在极端条件下,如果我们自动 continue,可能会误入死循环。

    所以我建议,max_tokens 最少 128,尽量 256 以上。


    前几天,有朋友在我的博客下面留言,说 Whisper 他试过,没啥特别的。我的观点不是这样。所谓纸上得来终觉浅,绝知此事要躬行。很多东西,确实不复杂,照着官方教程弄,三下五除二,在本地跑起来,并不难。但是想弄得干净利索,在生产环境里跑顺,遇到什么问题都能快速解决,也不是随随便便就能搞定的。

    希望有类似需求,寻求类似解决方案的同学能少走弯路;也欢迎大家多多分享,有意见建议,欢迎留言讨论。

  • 我的 AI 学习一周总结:ChatGPT API 发布

    我的 AI 学习一周总结:ChatGPT API 发布

    即然接下来的时间准备投身 AI 行业应用层开发,那就隔三岔五分享一下近期学到的知识、在做的事情吧。(配图是今天用第一次用 SD 生成的图片,prompt:“a beautiful girl“。)

    ChatGPT API 发布

    今天(2023-03-02,美国时间 03-01) OpenAI 正式发布了 ChatGPT API,即 基于 gpt-3.5-turbo 模型的。它的价格更便宜,$0.002/1k tokens,比之前 text-davince-003 便宜 10 倍。它能提供更好的对话质量,还提供了新的结构化数据接口,相信会给应用开发者带来更多的空间。

    chatgpt 等 npm 包也相应更新,如果没有办法搞定绑卡操作,可以继续用这些社区接口白嫖。

    尝试 Vercel Edge Function

    之前开发 GPT-3 插件的时候,有同学介绍了 Building a GPT-3 app with Next.js and Vercel Edge Functions 一文,于是我尝试把 API 挪到 Vercel Edge Function 上,然后失败。

    今天写本文的时候,又看了眼 TwitterBio 的例子,发现自己并没有做错。排查来排查去,还是自己犯蠢,部署环节出了问题。如今已经可以使用了。回头重构下插件,添加一些功能进去。

    学习社区 ChatGPT API 仓库

    ChatGPT 的开发商 OpenAI 提供两大块服务,API 和 ChatGPT 网页版。API 需要绑卡,有一定门槛;网页版可以免费用,不过存在偶尔连不上、响应慢等情况,据说买 plus 之后会有好转。

    于是社区就开发了网页版转 API 的工具,可以用来搭建自己的 ChatGPT API。但是需要使用反向代理服务器作为中转,开发者也不提供反向代理服务器的源码,存在一些风险,所以我看完就不打算使用了。

    本地搭建 Stable Diffusion 环境

    搭建过程其实很简单,难点主要在下载 pip 包和模型上,受限于墙内的网络环境,原本简单的下载变得异常艰辛。还好在换用国内 pip 源之后,我终于在本地搭建成功 Stable Diffusion Web UI 环境。大体过程如下:

    1. 安装必须的软件环境,比如 cmake、python3.10 等
    2. clone AUTOMATIC1111/stable-diffusion-webui: Stable Diffusion web UI (github.com)
    3. 修改 pip 源
    4. 反复执行 ./webui 直至安装成功
    5. 换模型可以在 Civitai 下载

    Whisper 模型

    Whisper 模型是 OpenAI 释出的开源模型,可以用来做语音识别,据说效果非常好。它不仅可以识别语音内容,还可以根据声纹,区分不同的发言人。所以用途也很广,比如视频会议之后,可以用它生成会议的文字记录。如果再结合 ChatGPT,就可以进行内容总结、会议摘要等工作,想象空间很大。

    因为开源,所以可以自己搭建服务器,据说不需要很强的计算能力,庶民可用。OpenAI 这次也放出了 Whisper API,方便用户使用。

    ChatGPT 新知

    中文语料少的副作用

    使用英文要求 ChatGPT 创作哈姆雷特的故事,它会拒绝,因为它知道哈姆雷特,新故事如果背景差异过大,它就会拒绝。但如果用中文,因为语料不足,哈姆雷特对它来说也只是个人命,它就会很配合。

    名人资料

    GPT-3 会大量混淆中国名人,比如郭德纲、岳云鹏;相对来说,ChatGPT 就好很多。


    现在 AI 工具与 AI 基础设施层出不穷,日新月异应接不暇,学起来既有动力也有压力。下一步希望能把所有工具的环境都搭建起来,先积累感性认识再说。

  • 我所了解的 ChatGPT:二次开发;有何限制;对未来的影响

    我所了解的 ChatGPT:二次开发;有何限制;对未来的影响

    前言

    ChatGPT 其实去年底就已经在开发界大放异彩,但是圈子之外对它了解不多。春节过后,公关公司开工上班,马上开始紧锣密鼓的宣传,然后就开始破圈,如今已经是整个公共领域,尤其是创投方面最热门的话题。

    我最近也接到需求,要开发一个基于 OpenAI API 的小应用,于是开始深入了解。如今应用初步完成,对 OpenAI 的产品有了更具体的了解。再结合之前向做 AI 的朋友请教,并总结自己观察思考,于是想写一篇文章分享给大家。希望未来的 AI 世界我们都不要缺席。

    OpenAI 的服务

    ChatGPT 是 OpenAI 的一项服务。它的内核是 GPT-3.5。OpenAI 还提供很多其它服务,比如图像生成、文本分析、比 ChatGPT 质量略差的 GPT-3 等。使用这些服务需要一些操作或技巧,比如翻墙——这次是 OpenAI 先动的手。以下是我摸索出的一些经验,希望可以帮后来者省去一些时间。

    注册

    目前注册 OpenAI 比较麻烦,因为他不向中国用户提供服务,所以必须有国外手机号,并且全程使用全局代理才可以完成。国外手机号可以借用接号平台来绕过,大家可以按需选用;如果有国外的亲朋好友帮忙,就会很容易。

    绑卡

    如果你只想在网页端使用 ChatGPT,可以暂时不绑卡。如果要使用 API 或者其它服务,就得绑卡。绑卡很麻烦,国内信用卡都不支持。虚拟信用卡比如 Payoneer,只对企业开放,需要资质审查,也不太好搞。

    至于我,最后还是拜托国外的亲戚帮忙搞定。目前有三个月的免费期,暂时够我把设想的应用场景跑一遍了。

    GPT-3 与 GPT-3.5

    大热的 ChatGPT 就是 GPT-3.5,现在只提供网页服务,如果要当成 API 调用,需要一些转换步骤,比较麻烦。从开发角度来说,直接使用 OpenAI API 会简单很多,但是只能使用 GPT-3 模型,对话 质量会差一些。不过看起来 ChatGPT API 已经在登记预约中,猜测很快也会开放,所以先把代码写好,等待开放应该也可以。

    目前来看,我认为官方不希望大家偷摸使用 Web 接口,近期可以继续尝试,长远来看最好做好切换到 API 的准备。

    我的进展

    我目前实现了本地通过 OpenAI SDK 调用服务 API。不过官方 SDK 有些问题,比如因为使用 Axios,无法部署在 Vercel Edge Function,必须放在自己的服务器上。所以接下来我计划做两件事情:

    1. 尝试不用 SDK,把逻辑直接放在 Vercel Edge Function 里
      • Vercel Edge Function 无论是否开启 stream: true 都会报告 504,猜测是 OpenAI 封禁了 Vercel。理论上当然可以继续尝试绕过,不过长远来看,与服务商做斗争并不明智,先放着吧。
    2. 搭建 ChatGPT Web API 环境,以便直接使用更好的服务
      • 需要使用第三方反向代理服务器,存在一些风险。而且他们并不愿意提供部署代理服务器的方案,理由是给非官方代理方案更大的生存空间。我觉得那就不如耐心等待 ChatGPT API 开放。

    ChatGPT 的限制

    (以下内容感谢 @Gary 指导。)

    4097 tokens

    GPT-3.5 的最大长度是 4097 token,根据我做 AI 的朋友讲解,汉字=2token,英文=0.5 token。也就是 GPT-3.5 的上下文最多保持 2k 汉字或 8k 英文字符 的内容。所有文本合并到一起发给 AI,AI 给出答案;我们再把新文本续上,发过去,AI 给出新的答案。直到最初的内容被挤出去,产生新的上下文。

    这是什么意思呢?比如我们日常交流,都是自带上下文的,跟父母、跟同事、跟恋人说话不一样,也是因为上下文不同。我会跟游戏里的同好聊魔兽世界,但是如果跟父母说同样的话题,他们就会不知所云。这就是上下文的差异。

    换言之,我们跟 ChatGPT 对话,用中文,教给它一件事情,累计 2k 字之后,他就会忘记这个要求。要避免这种情况,我们就得每隔一段时间重新教它一次;或者,以编程的方式重构 prompt,添加先决条件,以便维持特定功能。

    听起来有理有据,但其实错误百出

    我称其为“尬聊之神”。ChatGPT 并不是真的智能,或者说,目前的 AI 实现都在从不同方向模拟人类的智能,也许我们最终会成功,但是现在似乎还有些距离。具体到 ChatGPT 上就是,你说什么,他都会给出回应,但是回应有没有价值,不好说。

    尤其在一些绝对的事实方面,因为训练语料的问题,ChatGPT 的表现会比较差。因为对它来说,假的、错的语料,只要语法正确,也是好语料。这方面 Bing 里号称 GPT-4(我对此版本号表示怀疑)的模型表现就会好很多,因为它会结合网页权重,使用更权威的材料。

    在编程领域也是如此。因为开源软件的关系,ChatGPT 拥有非常丰富的程序开发知识,可以帮我们解决很多问题,写出很多代码。但是这些代码写得如何、能不能跑起来,还很难讲。所以,能不能把编程的工作丢给它?目前不能,它甚至不具备基于语言特性进行逻辑推导(语法检查)的能力。——但是不代表我们不能用它提升效率、学习技术。

    还没有真正的智能,也无法持续学习

    前面说过,ChatGPT 可以在保留一定上下文的基础上,与当前用户进行有状态的交流。所以我们也可以教 ChatGPT 做一些事情,比如发出指令:“以后提到日期,都用 YYYY-MM-DD 的格式”。接下来,我们就能把 ChatGPT 当成自动格式转换器来使用。或者,我们可以让它换用不同的语气、不同的语法,改变输出的内容,契合某种风格。比如出名的胡总编模拟器、鲁迅模拟器等。

    但这些并不是自我意识与学习,本质上只是 ChatGPT 根据完整上下文合成的文本,而已。有很大的限制:首先我们必须保留足够的上下文,其次我们也没有办法直接把这个状态转移到其它用户。

    哪些未来更可期?

    ChatGPT 的出现,让大家都很兴奋,我也一样。我们都确定未来可期,但是通常来说,总会有一些未来更可期,另一些未来不那么可期。结合上面提到的问题,我认为有一些领域可能不太好做:

    老年人陪护(x)

    我有个朋友上一份工作主攻老年人市场,所以他立刻就问,能不能用 ChatGPT 做一款老年陪护软件。

    我认为不行。这里涉及到两个问题:

    1. 上下文限制。AI 会损失大量的历史记录,需要用户花费大量的时间反复训练。对有经验的用户来说,可以通过各种手法优化,对老年人来说,可能会反复经历挫折。
    2. 不够准确。因为训练语料的问题,ChatGPT 无法保证内容的准确性,如果老年人寻医问诊,可能得到错误的答案。众所周知,AI 不能背锅,这一点也很难解决。

    但也有一些领域会有很大的机会:

    语言类,翻译、文书等

    这方面算是 ChatGPT 的主场了,无论翻译,还是文书书写,目前来看 ChatGPT 都能完成的非常好。4097 tokens 的限制,可能需要我们在产品层面给予一定的辅助设计,但是在可以想象的空间内,都能产生不错的产品。包括但不限于:

    1. 小说生成器
    2. 解说文字生成器
    3. 内容/关键词提取器
    4. 商务邮件辅助工具
    5. 学外语辅助工具
    6. ……

    太多太多,不一一列举了。总之,这块儿几乎一定会产生很多应用,甚至我们现在就能见到不少。

    用户界面

    我认为 ChatGPT 最大的价值就是全新的用户界面。以前我们的用户界面,无论命令行、图形化,都只针对具体的需求,需要用户自己有清晰的认知、有明确的方向、并认真学习。如果用户没有学习过,就很难使用现有的产品。想象一下,如果用户可以用自然语言发出命令,那几乎所有产品界面都可以重建得更好用。

    举个例子,我们家 Siri 最常用的功能就是定时,比如煮泡面:嘿,siri,定时 4 分钟。但是其它功能很难做到,因为其它的功能描述起来太复杂,而且表达方式也比较多,Siri 目前处理不了。

    ChatGPT 则可以从用户的文字描述中提炼出有价值的信息;经过简单的训练之后,还可以发出指定的命令。所以我设想,将来很多东西都可以用它重建,比如(GPT 没有好的翻译,所以我就用姆伊姆伊来替代):

    • “姆伊姆伊,帮我叫水”——我家桶装水喝完之后,要打电话给水站让他们送水——ChatGPT 自动拨号,跟客服简单沟通,叫水。
    • “姆伊姆伊,帮我订个外卖,吃粉吧“——这个需求会复杂很多,除了外卖之外,我们需要 AI 分辨出“吃米粉”这样的需求,并且从历史当中,判断我们常吃的粉是哪一家,然后帮我们完成订外卖的需要。

    AI 公司的未来

    未来 OpenAI 这样的大型公司,能提供通用模型的公司会越来越少,因为通用模型数据量和计算量太大,小公司根本烧不起。但是做 AI 的小公司可能会冒出来,类似用 WordPress 做建站,小公司可以帮客户在大模型的基础上做 finetuning,帮助客户将 AI 集成到产品里。

    我会怎么做?

    首先,我一定要尝试用 ChatGPT 做产品。我觉得它是很重要的产品,是未来的重要组成部分。去年它开始在业内刷屏的时候,我没想到它能获得这么大的公众关注度,这对我们来说既是好消息也是坏消息。好消息是将来可以借助它的品牌做宣传,坏消息是势必有更多的竞争者入局。

    接下来是产品方向。我想做简历相关,让 ChatGPT 帮我们把简历做得更匹配 JD、更有竞争力。考虑到它在文本分析和生成方面的强势,我觉得这个方向有很大的机会。

    我也计划加入一家以 AI 应用层为主要产品的公司,不要错失良机。希望能找到合适的老板或团队,即尊重技术,又擅长市场,大家能够合作共赢。

    前端怎么做?

    我认为现在是前端的好机会,因为目前 ChatGPT 基于浏览器提供服务,所以浏览器扩展就有很大的想象空间。建议所有前端小伙伴都好好学习一下 ChatGPT 的相关知识,能够实际开发一两个相关产品。比如,有人会让 ChatGPT 推荐一些配色,如下图:

    ChatGPT 只能给出色值,不方便直接看到。我们就可以写一个浏览器插件,将页面上的颜色转换成色块显示出来,并且支持一键保存到自己的调色盘。利用好这段真空期,有很大的发展空间。

    总结

    以上,就是我从去年得知 ChatGPT,到最近一周基于 ChatGPT 开发浏览器扩展,再结合我看到的、聊到的、想到的内容,集中分享。

    希望对看到文章的各位有启发、有帮助。如果你对 ChatGPT,对近期的 AI 热潮有想法、有问题,欢迎留言讨论。更欢迎针对我文章的评议、讨论。

    未来,AI 一定会有一席之地,我们也一起来争取属于我们的新领地吧。

  • 应用创意:我也是大腿

    应用创意:我也是大腿

    直播界风起云涌,如今很多大主播的号召力已经不亚于三四线小明星,比如陈一发。相信很多人都知道,相信很多人也看过这个视频:主播真会玩鬼畜篇08:暴击女王陈一发。像我这样的中老年人其实对 B 站和鬼畜都不怎么感冒,不过对这种视频的传播效力很感兴趣。

    今天百度发布了分词产品,虽然我很讨厌百度,但不得不说这个分词产品和它的语音合成产品都给我们这些不会语音合成的开发者创造了新的可能,算是百度积累的一件功德,略微降低了我对它的恶感。

    接下来介绍的这个 idea 我其实琢磨一阵子了,它是一个工具,可以用来合成任意鬼畜视频。工作流程如下:

    1. 抓取直播视频,提取音频文件。现在大主播都有回看功能,应该不难。
    2. 把音频文件切割后,利用百度语音转换成文字。切割主要根据停顿,方便识别句子。
    3. 把时间点和文字入库备用。
    4. 选择一首歌,或者自己写个段子
    5. 使用 ES 之类的工具,检索出匹配度最高的句子;也可以使用百度分词工具,分词,查找最匹配的段落
      1. 合成结果类似:
        白日依山尽 ( 2018-01-01 1.mp4,10:10:10-10:10:25)
        黄河(2018-01-02 2.mp4, 10:10:12-10:10:15) 入海流(2018-01-02 3.avi,10:15:22-10:15:35)
        欲穷千里目(无匹配)
        更上一层楼(4.flv,0:0:15-0:0:35|5.mp4, 1:1:1-1:1:20)
      2. 纯文本文件,方便保存和版本管理
    6. 人工预览一遍,对个别词进行调整
    7. 自动裁剪拼接配乐输出视频
    8. 完成

    这样一来,即使主播本人未播过的歌曲,也可以根据素材合成出来,比如 陈一发儿:~老公~要抱抱~要亲亲~嗯~人家要嘛~

    目前这里面所有步骤都可以使用工具和比较简单的开发语言完成,如果你想积攒编程经验,又无从下手,且喜欢看各种女主播,这个 idea 就不妨拿去一试。