随着 AIGC 热潮的兴起,越来越多的 AI 工具应用开始出现,包括 OpenAI ChatGPT、Github Copilot 等,这些工具正在改变着传统的工作生产方式。
在 2023 年 3 月的一次发布会中,OpenAI 甚至展示了直接通过识别原型草图,智能生成网站代码的案例。
一时间,“程序员要失业了”类似言论甚嚣尘上。
但技术革命改变的只是工具,只有持续地学习新工具,才能不被时代所抛弃。
打不过就要加入,程序员要想保住自己的“饭碗”就需要开始使用 AI 工具提升自己工作效率,甚至直接参与到 AI 工具的开发中,完成个人能力升级。
AI工具使用痛点和解决方案
当下 AI 工具能力一类来自 AI 头部公司提供的通用能力,如 ChatGPT、 Copilot等,一类来自社区的开源生态,如 LangChain、AutoGPT 等。
前者功能稳定,但主要面向通用场景,缺少针对实际工作场景的定制化能力,如不支持基于公司内部文档解答问题等,甚至还有泄露公司内部信息的隐患。
后者扩展性强,可私有部署控制,但如果要完美契合当前团队工作流,其定制成本又特别高昂,难以在人力不足的中小型团队落地。
因此,有机地将头部 AI 公司的通用能力和社区开源生态进行结合,取长补短、灵活定制,才是长期的最佳策略。
下面笔者以 CLI 智能提示助手的定制化为例,讲解如何低成本地实现这种结合。
CLI 智能提示助手实践
CLI 智能提示助手是一个命令行终端工具,支持用户用自然语言描述想做的事情,比如统计查找重复文件等,然后回复建议的 CLI 命令。这类工具开源社区已有多个实现,为方便展示,我们选取其中的 Python 技术栈版本 ricklamers/shell-ai,使用效果如下:
其开源源码核心部分 shell_ai/main.py 比较简单(只有两百多行)。检查后便不难发现他的底层是通过如下提示词模板定制 OpenAI 通用模型 API 角色设定的:
1. SystemMessage.content='You are an expert at using shell commands.` ``I need you to provide a response in the format `{"command": "your_shell_command_here"}`.`` `The system the shell command will be executed on is Darwin 22.1.0.` `Only provide a single executable line of shell code as the value for the "command" key.``Never output any text outside the JSON structure. The command will be directly executed in a shell.``For example, if I ask to display the message \'Hello, World!\', you should respond with ```json\n{"command": "echo \'Hello, World!\'"}```.``Between [], these are the last 1500 tokens from the previous command\'s output, you can use them as context: [None], if it\'s None, don\'t take it into consideration.'` `2. HumanMessage.content="Here's what I'm trying to do: run 统计查找重复文件" # 这里注入用户输入
这个提示词中通过 SystemMessage 限定了 AI 机器人的身份背景和输入输出格式,同时给出了系统背景信息,如上文给出的是 MacOS 背景设定。
OpenAI API 在收到上述提示词后,将会基于大模型的历史训练语料中查找能匹配目标需求的 MacOS 系统命令,并返回给用户进行选择。
而程序员日常工作使用的命令常常是公司内定制的工具,不可能存在于 OpenAI 的历史训练语料中。
这就是前文第二节提到的落地痛点,因此需要将 OpenAI API 能力和开源工具能力有机结合,以扩展支持定制化的场景诉求。
但如何让 AI 学会公司内部工具的使用方法呢?
举个例子,公司内部有个专用命令,会自动汇总个人的开发工作信息,并自动生成每周报告。我们假设其使用文档如下:
显然,my_wr_gen 这个命令只存在于公司内部系统,OpenAI 和 shell-ai 都完全不知晓它的功能和使用方式。因此,当我们调用 shell-ai 问它如何生成周报时,它完全不会回答任何 my_wr_gen 相关信息,如下图所示:
针对这一问题,我们可以在公司内私域部署 Dify 服务,以低成本地实现一个基于私域知识信息的大语言模型 API。
Dify 底层的私有部署、文本分割和嵌入等技术能保障公司私域信息的安全。具体部署流程参考官网 docker 部署和源码部署章节,本文暂不累述。通过Dify 平台,我们可以配置出一个智能对话机器人 API,并将其绑定上文的 my_wr_gen 使用文档。具体步骤如下:
1、上传知识库
首先完成知识库上传:
①打开Dify 顶部【知识库】功能;
②点击【添加文件】将上面提到的使用文档文件上传上去。
Dify 平台默认支持多种文件格式,笔者建议优先使用 Markdown 文件类型。
2、创建和初始化对话机器人
点击顶部【工作室】功能页面创建一个对话类型机器人,然后分三步完成机器人的初始化设置:
①打开左侧【编排】设置页面;
②在【上下文】中添加刚才创建的知识库,实现知识绑定;
③在【提示词】中补充 CLI 助手角色设置如下图所示,笔者在提示词中约束了机器人的身份设定,并要求其根据上下文和用户输入查询给出 CLI 命令建议。
其中这里的变量“query”会用于承载后面 API 请求中的用户输入信息。
3、发布 API
配置完成后点击发布即可获得一个外网可以访问的大语言模型 API。
点击左侧【访问 API】 即可看到所有可用 API 类型,我们只需要使用其中的【发送对话消息】 API,如下图所示:
4、扩展 shell-ai 核心代码支持 Dify API
那么接下来,只需要使用这个 API 替换原来 shell-ai 中对 OpenAI API 的调用,即可让 shell-ai 了解 my_wr_gen 这个私有命令的用法。
由于 Dify 本身 API 接口定义和 OpenAI 完全不同,我们需要在 shell-ai 的源码中进行输入输出格式的适配。
具体可以分为以下步骤:
①增加 Dify API 类型。 检查 shell-ai/main.py 源码,可以发现这一工具每次调用都会自动加载 ~/.config/shell-ai/config.json 文件中的环境配置(MacOS 下为此地址,其他系统可能有所变化)。其中有一个环境配置字段为 OPENAI_API_TYPE 用于判断使用什么类型的 OpenAI 接口,默认支持 openai 和 azure 两种设置。那我们就在这里扩展支持 Dify 的 API 类型。在原来代码的基础上,我们先增加以下代码:
1. OPENAI_API_TYPE = os.environ.get("OPENAI_API_TYPE", "openai")` `3. OPENAI_API_VERSION = os.environ.get("OPENAI_API_VERSION", "2023-05-15")` `4. if OPENAI_API_TYPE not in OpenAIOptions.__members__ and OPENAI_API_TYPE != "dify": # 新增 dify 类型校验` `5. print(` `6. f"Your OPENAI_API_TYPE is not valid. Please choose one of {OpenAIOptions.__members__}"` `7. )` `8. sys.exit(1)` `9.` `10. # ... 省略部分无关代码` `11.` `12. if OPENAI_API_TYPE == "openai":` `13. chat = ChatOpenAI(` `14. model_name=OPENAI_MODEL,` `15. n=SHAI_SUGGESTION_COUNT,` `16. openai_api_base=OPENAI_API_BASE,` `17. openai_organization=OPENAI_ORGANIZATION,` `18. openai_proxy=OPENAI_PROXY,` `19. )` `20. if OPENAI_API_TYPE == "azure":` `21. chat = AzureChatOpenAI(` `22. n=SHAI_SUGGESTION_COUNT,` `23. openai_api_base=AZURE_API_BASE,` `24. openai_api_version=OPENAI_API_VERSION,` `25. deployment_name=AZURE_DEPLOYMENT_NAME,` `26. openai_api_key=os.environ.get("OPENAI_API_KEY"),` `27. openai_api_type="azure",` `28. temperature=0,` `29. )` `30. if OPENAI_API_TYPE == "dify":` `31. chat = DifyChat() # 新增 dify 类型 chat 实例
②封装DifyChat 类。 上面代码中,ChatOpenAI 和 AzureChatOpenAI 的定义都是来自著名 AI 开发框架 LangChain。其接口输入输出定义上是无法和 Dify API 对齐的。但得益于 LangChain 的抽象封装,shell-ai对 chat 实例的调用都收敛在 generate 方法。因此我们可以以最低成本,在 DifyChat 类中完成简单的输入对齐,即将 generate 传入入参的格式进行对齐,并传给 Dify 平台。然后在返回后完成输出响应的对齐。首先是对于 DifyChat 实现的简单封装:
2. class DifyChat:` `3. def generate(self, messages):` `4. print(messages)` `5. query = messages[0][0].content + messages[0][1].content` `6. print(query)` `7. headers = {` `8. 'Authorization': 'Bearer YOUR_DIFY_API_KEY',` `9. 'Content-Type': 'application/json',` `10. }` `11.` `12. data = {` `13. 'inputs': {},` `14. 'query': query,` `15. 'response_mode': 'blocking',` `16. 'conversation_id': '',` `17. 'user': 'abc-123'` `18. }` `19.` `20. response = requests.post('https://api.dify.ai/v1/chat-messages', headers=headers, json=data)` `21. print("Got Response from dify::" + response.text)` `22. return response
③处理请求参数和返回结果。 上述代码中需要注意替换请求头中 Authorization 字段的 API_KEY 为自己的值。API 域名为 Dify 默认,如有私有部署的需要替换为自己域名。处理完成后,DifyChat 实例就能获取用户输入的命令诉求,并将其和 shell-ai 本身的提示词模板拼合后,转发给刚才配置的 Dify 对话机器人。当机器人返回答复后,我们还需要差异化处理返回结果如下:
23. # Extract commands from the JSON response` `32. commands = []` `33. if (OPENAI_API_TYPE == "dify"): # 针对 dify 差异化处理` `34. try:` `35. data = json.loads(response.text) # 解析 dify 返回的 json` `36. command_json = json.loads(data["answer"]) # Dify 的答复在 answer 字段中` `37. command = command_json["command"] # 对齐原有逻辑,答复内容应为一个 json,其中 command 字段为命令` `38. print(command) # 打印 dify 返回的 command` `39. if command: # 对齐原有逻辑` `40. commands.append(command)` `41. except json.JSONDecodeError:` `42. # Fallback: treat the message as a command` `43. commands.append(msg.message.content)` `44. else: # 原始逻辑` `45. for msg in response.generations[0]:` `46. try:` `47. json_content = code_parser(msg.message.content)` `48. command_json = json.loads(json_content)` `49. command = command_json.get("command", "")` `50. if command: # Ensure the command is not empty` `51. commands.append(command)` `52. except json.JSONDecodeError:` `53. # Fallback: treat the message as a command` `54. commands.append(msg.message.content)` `55.` `56. # Deduplicate commands` `57. commands = list(set(commands))
④全局变量配置修改。 完成上述源码逻辑修改后,我们还需要在 ~/.config/shell-ai/config.json 中修改 OPENAI_API_TYPE 类型为 Dify:
24. {``58. "OPENAI_API_TYPE":"dify"``59. }
⑤最终,我们尝试使用本地运行方式试运行 shell_ai/main.py 文件,如下图所示。 可以发现我们修改后的代码成功完成了提示词模板的拼合,将拼合结果传给了 Dify API 并获得符合期望的返回结果。shell-ai 最终成功学习到了我们的私域知识,并给出了 my_wr_gen ~/Dev/ 这个建议。
结语
在上面的实践中,我们成功让一个只能解决通用问题的社区 AI 工具学习到了私域知识。在定制通用工具的过程中,我们不止可以产出更趁手的 AI 工具,同时还能加深对 AI 领域知识的了解。
此外,在上文提到的 Dify 知识库创建中,平台会先使用文本分割技术将我们传入的技术文档分割成一个个碎片,在每次请求 OpenAI 时,会使用嵌入技术动态选择最关联的碎片,因此 OpenAI API 无法一次性获取完整地私域文档知识,进而在一定程度上保障了企业信息安全。同时无论是 Dify 还是 Shell-ai,它们的底层开发都不约而同地使用了 LangChain 这一大语言模型开发框架。
读者福利:如果大家对大模型感兴趣,这套大模型学习资料一定对你有用
对于0基础小白入门:
如果你是零基础小白,想快速入门大模型是可以考虑的。
一方面是学习时间相对较短,学习内容更全面更集中。
二方面是可以根据这些资料规划好学习计划和方向。
包括:大模型学习线路汇总、学习阶段,大模型实战案例,大模型学习视频,人工智能、机器学习、大模型书籍PDF。带你从零基础系统性的学好大模型!
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费
】🆓
👉AI大模型学习路线汇总👈
大模型学习路线图,整体分为7个大的阶段:(全套教程文末领取哈)
第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;
第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;
第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;
第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;
第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;
第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;
第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。
👉大模型实战案例👈
光学理论是没用的,要学会跟着一起做,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
👉大模型视频和PDF合集👈
观看零基础学习书籍和视频,看书籍和视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;
• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;
• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;
• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。
👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费
】🆓