跳转到主内容

6 篇标记为“扩展”的帖子

查看所有标签

在 Podman AI Lab 中启用 OpenVINO 推理

·4 分钟阅读
Jeff Maury
工程经理

Podman AI Lab 简介

Podman AI Lab 是一个开源平台,旨在简化使用容器技术部署、管理和试验 AI 工作负载。它提供了一个用户友好的界面,用于在本地或云端运行、测试和扩展 AI 模型,利用 Podman 容器的强大功能和灵活性。

什么是 OpenVINO?

OpenVINO™(Open Visual Inference and Neural Network Optimization)是英特尔开发的一个开源工具包,用于加速各种硬件(包括 CPU、GPU 和专用加速器)上的 AI 推理。它优化深度学习模型以实现快速、高效的推理,使其成为边缘和云 AI 应用的热门选择。

在 Podman AI Lab 中使用 OpenVINO

Podman AI Lab 现在支持 OpenVINO 作为推理提供程序。这意味着您可以:

  • 在启动推理服务器或 playground 时选择一个与 OpenVINO 兼容的模型。
  • 在支持的英特尔设备上享受硬件加速推理带来的好处。
  • 轻松地在不同的推理提供程序(例如,llama-cpp、OpenVINO)之间切换,以进行基准测试和兼容性测试。
警告

此功能仅在基于英特尔的系统上可用,因为 OpenVINO 是为英特尔硬件优化的。如果您使用的是非英特尔系统,您将无法使用 OpenVINO 作为推理提供程序。

如何使用

  1. 启动 Podman AI Lab 并导航到模型部署或 playground 部分。
  2. 在配置您的模型时,选择一个与 OpenVINO 兼容的模型。
  3. 启动推理服务器或 playground。

启动 OpenVINO 推理服务器

  1. 点击导航栏中的 Podman AI Lab 图标。
  2. 在 Podman AI Lab 导航栏中,点击 模型 > 服务 菜单项。
  3. 点击右上角的 新建模型服务 按钮。
  4. 模型 列表中选择一个与 OpenVINO 兼容的模型(例如 OpenVINO/mistral-7B-instruct-v0.2-int4-ov),然后点击 创建服务 按钮。
  5. 该模型的推理服务器正在启动,稍等片刻后,点击 打开服务详情 按钮。

OpenVINO inference server details

使用终端 shell,执行给定的 curl 命令并查看推理结果输出。

使用 OpenVINO 兼容模型启动 Playground

  1. 点击导航栏中的 Podman AI Lab 图标。
  2. 在 Podman AI Lab 导航栏中,点击 模型 > Playgrounds 菜单项。
  3. 点击右上角的 新建 Playground 按钮。
  4. 模型 列表中选择一个与 OpenVINO 兼容的模型(例如 OpenVINO/mistral-7B-instruct-v0.2-int4-ov),然后点击 创建 Playground 按钮。
  5. 该模型的 playground 正在启动,稍等片刻后,将显示一个聊天界面。

Initial playground on OpenVINO model

在提示符中输入“What is OpenVINO ?”,然后点击 发送 按钮。OpenVINO 模型将回复一个答案。

OpenVINO model response in the playground

与 OpenShift AI + OpenVINO 的一致性

在 Podman AI Lab 中使用 OpenVINO 的一个关键优势是,当将工作负载过渡到 OpenShift AI 时,它带来了一致性。这两个平台现在都支持 OpenVINO,确保:

  • 在 Podman AI Lab 中本地测试和优化的模型,在部署到 OpenShift AI 时将表现出相同的行为。
  • 您可以维持从开发到生产的统一工作流,减少意外情况和集成问题。
  • 性能优化和硬件加速在不同环境中得以保留。

结论

通过启用 OpenVINO 作为推理提供商,Podman AI Lab 使用户能够在本地和云端利用高性能 AI 推理,并在 OpenShift AI 等平台上获得一致的体验。这种集成简化了 AI 开发生命周期,并为部署高效、可扩展的 AI 解决方案开辟了新的可能性。

使用 Podman 和 Podman Desktop 增强您在 VS Code 中的容器开发

·5 分钟阅读
Matt Demyttenaere
产品经理

开发容器化应用程序有时会感觉很复杂,但有了合适的工具,它就可以成为一个顺畅高效的过程。在这篇博文中,我们将探讨如何利用 Visual Studio Code (VS Code) 与 Podman 和 Podman Desktop 的强大功能来简化您的容器开发工作流程。我们将介绍如何设置和使用两个与 Podman 集成的 VS Code 扩展。

VS Code:您的容器开发 IDE

VS Code 是一款流行且功能多样的代码编辑器,可以通过扩展来增强其功能。对于容器开发,有几个优秀的扩展可以与 Podman 无缝集成。

先决条件

在我们开始之前,请确保您已安装以下软件:

  • Podman:请遵循官方网站上的安装说明。
  • Podman Desktop:官方网站下载并安装 Podman Desktop。
  • Visual Studio Code:官方网站下载并安装 VS Code。

VS Code 扩展

为了将 VS Code 与 Podman 集成,我们有两种扩展可供选择:

  1. Microsoft 的容器工具扩展“容器工具”扩展为容器相关任务提供了出色的支持,包括构建镜像、管理容器以及处理 Containerfile 和 Dockerfile。微软最近宣布,他们将把 Docker 扩展发展为容器工具扩展,以支持 Podman 等其他工具!
  2. Pod Manager:此扩展由我们社区的一名成员创建,并且完全开源。它旨在帮助您直接从 VS Code 界面管理 Podman 容器、镜像、卷和网络。

虽然您不太可能同时使用这两个扩展,但比较它们将帮助您了解每个扩展的优缺点,最终更容易选择最适合您需求的扩展。因此,对于这篇博文,我们将逐个安装它们。

选项 1:Microsoft 的容器工具扩展

要安装此扩展:

  1. 打开 VS Code。
  2. 点击活动栏中的扩展图标(或按 Ctrl+Shift+XCmd+Shift+X)。
  3. 搜索“Container Tools”并安装微软发布的扩展。

为 Podman 配置 VS Code

容器工具扩展通常会自动检测 Podman,如果 Docker 没有运行,它会通过查看 DOCKER_HOST 环境变量。在 Podman Desktop 中,导航到“设置”>“Docker 兼容性”>“第三方工具兼容性”,并确保该选项已启用。在我们的文档中了解更多关于 Docker 兼容性的信息。

enabling docker compatibility in the settings

选项 2:Pod Manager

要安装此扩展:

  1. 打开 VS Code。
  2. 点击活动栏中的扩展图标(或按 Ctrl+Shift+XCmd+Shift+X)。
  3. 搜索“Pod Manager”并安装由 dreamcatcher45 发布的扩展。

使用 VS Code 扩展

既然我们已经安装并配置了扩展,让我们看看如何使用它们。

使用 Containerfile 和 Dockerfile

这两个扩展都为 Containerfile 和 Dockerfile 提供语法高亮、代码补全和语法检查功能。在 VS Code 中打开一个 Containerfile,您将立即从这些功能中受益。

您也可以直接从 VS Code 构建镜像:

  1. 在资源管理器视图中右键单击 Containerfile。
  2. 选择“构建镜像”。
  3. VS Code 将提示您输入镜像名称和标签。
  4. 然后,扩展将使用 Podman 构建镜像。
  5. 之后,您将在侧边栏中看到构建好的镜像。

如果您使用命令行来构建镜像,您也会在这里看到它们。

building a Containerfile in vs code using the microsoft extension

管理容器

这些扩展还允许您直接从 VS Code 管理容器。您可以启动、停止、重启和移除容器,以及查看它们的日志和检查它们的配置。

要查看容器日志:

  1. 点击活动栏中的容器图标。
  2. 您将看到您的容器、镜像和网络列表。
  3. 右键单击一个容器以执行操作。

using Container Tools extension to view the logs of the container

同样,使用 Pod Manager 扩展,我们可以直观地检查容器、镜像和卷。

  1. 点击活动栏中的 Pod Manager 图标。
  2. 您将看到您的容器、镜像和网络列表。

using podmanager to view all the running containers, images and volumes

并管理容器的生命周期。

using podmanager to manage the lifecycle of the container

当然,还可以通过可视化界面来解决问题。

using podmanager to enter the container

结论

相比之下,两个扩展提供了几乎相同的功能集,因此选择哪一个 UI 完全取决于您的偏好。就我个人而言,我将坚持使用 Pod Manager,因为它的标志是一个海豹 🦭。请记住,如果您在使用这些工具或 Podman Desktop 时遇到任何问题,请通过发起讨论创建问题来告知我们。

通过结合 VS Code、Podman 和 Podman Desktop 的强大功能,您可以创建一套精简高效的容器开发工作流程。VS Code 扩展与 Podman 提供了出色的集成,允许您直接从代码编辑器管理容器、构建镜像和使用 Containerfiles。我们很高兴看到 Microsoft 正在接纳 Podman 并将其支持集成到他们的生态系统中。Podman Desktop 通过可视化界面来管理您的容器环境,并有助于从开发环境过渡到生产 Kubernetes 环境。拥抱这些工具,提升您的容器开发体验!

Podman Quadlets 与 Podman Desktop

·5 分钟阅读
Axel Stefanini
软件工程师

banner

容器通常部署在 Kubernetes 集群中。然而,对于单节点服务器或开发过程中的小规模用例,Kubernetes 可能有些大材小用。

对于运行包含多个交互容器的自治应用程序,有什么更轻量级的解决方案呢?

在这篇博客中,我们将深入探讨 Quadlet 是什么、它们的优势,以及如何在 Podman Desktop 中使用它们。

Podman Desktop BootC 扩展 1.6 发布

·4 分钟阅读
Charlie Drage
软件工程师

BootC 扩展 1.6 发布!🎉

banner

BootC (Bootable Container) 是 Podman Desktop 的一个扩展,用于构建可启动的容器磁盘镜像。从标准容器镜像到完整的可启动 USB 操作系统!

您可以通过 Podman Desktop 扩展目录 更新或安装该扩展。

此版本引入了令人兴奋的新功能和改进。

  • 详细的示例页面: 每个示例现在都有一个专门的页面,提供详细的使用说明。
  • 交互式构建配置创建器: 直接在图形界面中通过填写表单轻松创建您的构建配置。
  • 实验性 Linux 虚拟机支持: 增加了在生成的镜像上运行 Linux 虚拟机的支持。

发布详情

示例现在有了详情页面

每个示例现在都包含一个专门的详情页面!点击示例部分中的更多详情,查看每个示例的逐步说明。

example details

交互式构建配置创建器

无需手动创建自定义构建配置。使用我们的交互式构建配置创建器,通过用户友好的表单轻松生成您自己的构建配置。

build config interactive

实验性 Linux 虚拟机支持

现在已支持在生成的镜像上运行虚拟机!请在磁盘镜像页面查找新的虚拟机(实验性)选项卡或专门的虚拟机启动按钮。

linux support


详细发布变更日志

功能 💡

  • 功能:由 @cdrage 在 #1017 中添加示例详情页面
  • 功能:由 @cdrage 在 #1026 中添加构建配置器
  • 功能:由 @cdrage 在 #1102 中添加 Linux 虚拟机实验性支持

杂项 🛠️

  • 杂务:由 @deboer-tim 在 #969 中移除 yarn 引用
  • 杂务:由 @deboer-tim 在 #971 中更新到最新的 UI 库
  • 杂务:由 @deboer-tim 在 #970 中添加发布流程
  • 杂务:由 @benoitf 在 #1001 中删除 `packages/backend/yarn.lock`
  • 杂务:由 @benoitf 在 #999 中重命名 CODEOWNERS 中的团队
  • 杂务:由 @benoitf 在 #1003 中刷新依赖项以更新到最新版本
  • 杂务:由 @cdrage 在 #1098 中为示例添加遥测
  • 杂务:由 @cdrage 在 #1078 中更新 `bootc-image-builder` 镜像
  • 杂务:由 @cdrage 在 #1089 中从 AMD64 虚拟机命令中移除 HVF 加速
  • 杂务:由 @cdrage 在 #1014 中为每个示例添加 README
  • 杂务:由 @cdrage 在 #1015 中重命名章节
  • 杂务:由 @cdrage 在 #1116 中恢复到 Vite 5 并更新 Vitest

修复 🔨

  • 修复:由 @dgolovin 在 #1085 中修复 E2E 测试工作流安装 PNPM 失败的问题
  • 修复:由 @dgolovin 在 #1103 中修复 E2E 主工作流的节点设置步骤
  • 修复:由 @cbr7 在 #1052 中修复到 webview 的导航
  • 修复:由 @cbr7 在 #998 中修复 bootc E2E 测试

文档 📚

  • 文档:由 @cdrage 在 #1115 中更新发布文档

Podman AI Lab - 供开发者在本地运行 LLM 来构建 AI 应用程序

·10 分钟阅读
Philippe Martin
首席软件工程师

banner

Red Hat 为 Podman Desktop 提供了一个扩展,Podman AI Lab,它让开发人员可以通过使用大型语言模型(LLMs)发现应用程序示例,并为他们提供一个框架来创建自己的基于 AI 的应用程序并与他们的团队分享。

通过本文,我们将探索创建我们的第一个 AI 应用程序,并将其添加到 Podman AI Lab 的配方目录中的不同步骤。

对于我们的第一个实验,我们将为 podman-desktop.io 网站开发一个微服务。该微服务将从网站接收搜索词,并要求模型查找最匹配的页面,然后将结果返回给网站。

my first app

准备 Podman Desktop 和 Podman AI Lab

如果您还没有安装,请先安装 Podman Desktop 及其扩展 Podman AI Lab

为了获得更好的体验,建议使用 GPU 加速来服务模型。如果您的机器上有这样的 GPU,您需要使用 LibKrun 提供商(在 MacOS 上)创建一个 Podman 机器。有关Podman AI Lab 的 GPU 支持的更多详细信息。

在撰写本文时,Podman AI Lab 的 GPU 支持仍处于实验阶段。您需要在首选项中启用该选项才能使用。

a podman machine running using libkrun

GPU support for inference servers preference is enabled

使用模型测试提示

Podman AI Lab 提供了一个可本地使用的开源模型目录。您可以前往 `Models > Catalog` 页面下载您选择的模型。在本文中,我们将使用 `Mistral-7B-instruct` 模型。

Mistral model is downloaded

一旦模型下载完成,我们就可以测试并与该模型交互,尝试为我们的应用程序找到最佳的提示词。对于聊天模型,Podman AI Lab 提供了一个 Playground,因此我们可以测试不同的提示词并验证模型的响应是否充分。

让我们开始一个新的 playground(从 `Models > Playgrounds` 菜单),并发送我们的第一个提示

Give me a list of pages in the website podman-desktop.io related to "build an image"

模型应该会以人类可读的形式回复一些页面列表(参见下面的截图,我们收到的响应)。

a first prompt with human-readable output

问题在于响应是人类可读的形式,但我们不希望 API 按原样返回此响应。我们希望获得页面的名称和 URL,并将其发送到网站,以便网站可以用其首选格式显示这些页面。

为此,我们可以尝试要求模型以结构化响应回复,使用以下提示

Give me a list of pages in the website podman-desktop.io related to "build an image" as JSON output as an array of objects with 2 fields name and url

这一次,我们收到了一个 JSON 格式的响应,这更适合我们的需求。

a prompt with structured output

我们不希望用户提出如此精确的问题,我们更倾向于将用户的确切问题发送给模型,而无需实时修改。为了实现这一点,聊天模型提供了系统提示功能。系统提示可以在聊天会话开始时定义。

Podman AI Lab 支持此功能,让我们用以下系统提示重新启动一个 Playground 会话

Give me a list of pages in the website podman-desktop.io related to the request as JSON output as an array of objects with 2 fields name and url

然后,发送提示 `build an image`,以模拟一个真实的用户搜索输入。

我们可以在下面的截图中看到,模型仍然返回一个适合我们用例的响应。

a session with a system prompt

请注意,本节并非关于编写最佳提示的课程,我相信您会找到更高效的提示用于此目的。本节的目的是演示您如何使用 Podman AI Lab 迭代以完善您想用于应用程序的提示。

测试配方

现在我们有了适合我们应用程序的提示,是时候启动我们的应用程序本身了。

许多开发者更喜欢从一个可用的应用程序示例开始,而 Podman AI Lab 通过一个配方目录提供了这样的示例,可以在 `AI Apps > Recipe Catalog` 页面看到。

让我们选择 Chatbot 配方(在 Chatbot 卡片上点击 `More details` 链接),并使用 Mistral 模型启动它(通过按 `Start` 按钮并填写表单)。

应用程序启动后,我们可以在 `AI Apps > Running` 页面访问正在运行的应用程序列表,并通过点击 `Open AI App` 链接访问应用程序的 UI。

我们可以再次通过输入我们的提示(不是带有系统提示的那个,因为该配方不支持提供系统提示)进行测试,并看到响应与从 playground 收到的非常相似。

a session on the Chatbot recipe

返回配方的详情页面,我们可以通过点击 在 VSCode 中打开 按钮、存储库链接或 本地克隆 链接来访问配方的源代码。

配方的结构

配方的入口点是其存储库中的 ai-lab.yaml 文件。

让我们检查一下聊天机器人示例的此文件内容(文件语法在此文档中指定)。

version: v1.0
application:
type: language
name: ChatBot_Streamlit
description: Chat with a model service in a web frontend.
containers:
- name: llamacpp-server
contextdir: ../../../model_servers/llamacpp_python
containerfile: ./base/Containerfile
model-service: true
backend:
- llama-cpp
arch:
- arm64
- amd64
ports:
- 8001
image: quay.io/ai-lab/llamacpp_python:latest
- name: streamlit-chat-app
contextdir: app
containerfile: Containerfile
arch:
- arm64
- amd64
ports:
- 8501
image: quay.io/ai-lab/chatbot:latest

该文件定义了两个容器,一个用于推理服务器,另一个用于应用程序本身。

第一个容器用于推理服务器,是通用的,可以被任何使用聊天模型的应用重用。

第二个是我们特别感兴趣的。它定义了应用程序的容器镜像是如何构建的。它指向用于构建镜像的 Containerfile,我们可以在其中找到应用程序的源代码:在 app/chatbot_ui.py 文件中。

查看 Python 源代码文件,我们可以看到应用程序使用了 streamlit 框架来处理 UI 部分,并使用 langchain 框架与模型进行对话。

我们可以调整此源代码,将 UI 部分替换为能将应用变为 REST 服务的框架,并保留 langchain 部分。

源代码中一个有趣的部分是,该配方没有向用户暴露系统提示,而是在内部定义了一个(You are world class technical advisor)。

prompt = ChatPromptTemplate.from_messages([
("system", "You are world class technical advisor."),
MessagesPlaceholder(variable_name="history"),
("user", "{input}")
])

这正是我们希望在应用程序中实现的功能,我们将能够在此处指定我们之前找到的系统提示。

创建我们自己的应用

针对我们应用程序的目的调整源代码超出了本文的范围,让我们看看我们的应用仓库中的结果。

如前一节所述,我们已将 streamlit 部分替换为 flask 框架,以创建具有两个端点的 REST API:一个用于 Podman AI Lab 所需的 / 上的健康检查,另一个用于 /query,这将是微服务用户发送请求的端点。

我们还指明了我们自己的系统提示。

prompt = ChatPromptTemplate.from_messages([
("system", """
reply in JSON format with an array of objects with 2 fields name and url
(and with no more text than the JSON output),
with a list of pages in the website https://www.podman-desktop.io related to my query
"""),
MessagesPlaceholder(variable_name="history"),
("user", "{input}")
])

在本地测试我自己的应用

为了在应用程序开发过程中进行迭代,我们可以在本地主机系统中测试我们的应用程序,同时使用 Podman AI Lab 提供的模型。为此,我们需要从“模型”>“服务”页面启动一个新的模型服务,方法是点击“新建模型服务”,然后选择合适的模型(在本例中为 Mistral-7B-instruct),并指定一个端口号(例如 56625)。

a running inference server with Mistral model

然后,我们可以运行我们的应用程序,通过 MODEL_ENDPOINT 环境变量指定如何访问模型服务。

my app running locally

最后,我们可以向这个在本地运行并监听 5000 端口的应用发送请求,我们可以在下面的截图中检查到响应如预期一样,是一个 JSON 格式的页面列表(名称和 URL)。

a request to the micro-service

创建配方

最后一步是将此应用程序添加到 Podman AI Lab 配方目录中。

Podman AI Lab 为用户提供了一种通过自己的配方扩展现有目录的方法。这可以通过在特定目录中添加文件来完成,如此文档所述。

{
"version": "1.0",
"recipes": [
{
"id": "search-podman-desktop-io",
"description": "Search on Podman-desktop.io website",
"name": "Search Podman-desktop.io",
"repository": "https://github.com/redhat-developer/podman-desktop-demo",
"ref": "main",
"icon": "natural-language-processing",
"categories": ["natural-language-processing"],
"basedir": "ai-lab-demo/recipe",
"readme": "",
"recommended": ["hf.TheBloke.mistral-7b-instruct-v0.2.Q4_K_M"],
"backend": "llama-cpp"
}
]
}

通过创建文件 $HOME/.local/share/containers/podman-desktop/extensions-storage/redhat.ai-lab/user-catalog.json 并包含上述内容,您现在应该能够在 Podman AI Lab 的配方目录中看到一个新的配方 Search Podman-desktop.io,并像运行其他配方一样运行它。当然,您可以与同事分享此文件,与他们分享您的最新实验。

Podman Desktop 扩展简介

·4 分钟阅读
Charlie Drage
软件工程师

programming

扩展是自定义和扩展 Podman Desktop 功能的强大工具。无论您是想添加新的容器管理功能、简化当前工作流程,还是创建特定于您的技术栈的自定义 UI 元素,构建扩展都可以让您根据特定需求定制 Podman Desktop 体验。

在本指南中,我们将介绍如何构建自己的 Podman Desktop 扩展,并提供详细文档链接,涵盖该过程的每个部分。

扩展简介

Podman Desktop 中有丰富的扩展,可以在 扩展 -> 目录 部分找到。

extension catalog

每个扩展都扩展了 Podman Desktop 的功能,例如通过 Minikube 提供 Kubernetes 开发集群,甚至分析您的镜像层

以下是镜像层浏览器扩展及其如何集成到 Podman Desktop 中的示例。

layers_explorer

开始您的项目

创建扩展的第一步是设置项目环境。要了解如何配置项目和添加基本组件,请查阅创建扩展模板指南,该指南将引导您从官方模板初始化项目。

添加 UI 组件

创建扩展时最常见的任务之一是添加用户界面。无论是添加按钮、面板还是图标,UI 组件都有助于使您的扩展更具交互性和可访问性。添加 UI 组件是完全可选的,扩展可以在没有 UI 组件的情况下运行。在添加 UI 组件文档中了解更多信息,您将在其中找到有关创建组件并将其集成到应用程序 UI 的说明。

使用图标

图标是使您的扩展在视觉上更具独特性的好方法。您可以按照添加图标文档学习如何添加和样式化自定义图标。

以下是 bootc 扩展如何向 Podman Desktop 内的镜像列表添加图标的示例。

icons

扩展通常与现有菜单和导航集成,以便用户可以轻松访问新命令和功能。如果您想向上下文菜单添加项目,请查阅菜单配置文档,其中解释了如何将命令添加到菜单以及如何使用 When Clauses 控制它们的显示。

以下是 bootc 扩展如何向镜像列表添加新菜单命令的示例。

menus

添加和配置命令

命令是大多数扩展的支柱,允许用户与应用程序交互并触发特定操作。

如果您需要定义和注册自定义命令,命令指南将向您展示如何创建响应用户操作或输入的命令,并将其与您的扩展工作流关联起来。

您还可以配置这些命令以在不同的上下文中出现。请查阅When 子句上下文文档,了解有关将命令限制为特定场景的更多信息。

命令深受VS Code 命令的影响,并且可以以类似的方式进行配置。请参阅我们的命令指南了解更多信息。

设置入门工作流

创建一个流畅的入门体验对于帮助用户开始使用您的扩展至关重要。这包括 CLI 二进制文件安装或其他初始设置值的步骤。

您可以使用入门工作流指南提供指导、教程或初始设置步骤。

以下是内置 compose 扩展如何为 compose CLI 二进制文件安装添加入门流程的示例。

compose

配置设置

构建好组件和命令后,您可能希望为扩展的高级用法设置配置选项。

配置文档概述了配置文件的结构以及如何将所有内容链接在一起以使用用户特定的值。

发布您的扩展

发布后,用户就可以安装您的扩展,您可以将您的扩展编译成容器镜像,以便用户轻松使用。请遵循发布指南,了解如何分发您的扩展。

结论

创建扩展为根据您的特定需求定制 Podman Desktop 开启了无限可能。

打包和发布您的扩展以供他人使用也很容易。

祝您在探索我们关于如何创建扩展的文档中玩得开心,编码愉快!