初步尝试AI应用开发平台——Dify的本地部署和应用开发

随着大语言模型LLM和相关应用的流行,在本地部署并构建知识库,结合企业的行业经验或个人的知识积累进行定制化开发,是LLM的一个重点发展方向,在此方向上也涌现出了众多软件框架和工具集,Dify就是其中广受关注的一款,今天我们就来近距离了解下它。

Dify介绍

简单说,Dify 是一款开源的大语言模型(LLM)应用开发平台,融合了后端即服务(Backend as Service)和LLM运维服务(LLMOps)的理念,旨在简化和加速生成式 AI 应用的创建和部署。
Dify 的名称来源于 “Define + Modify”。“Define” 代表着对 AI 应用进行定义,包括明确其功能、目标、应用场景等方面;“Modify” 则表示持续改进,体现了 Dify 平台支持开发者根据实际需求和反馈,不断优化和调整 AI 应用的特点。这两个词结合起来,传达出了 Dify 平台的核心理念,即帮助开发者定义并不断完善自己的 AI 应用。

Dify安装

我们先把Dify在本地安装运行起来。
安装Dify的最简单方式是借助Docker。官方已经做好了编排文件,只要将Dify源码下载下来,然后运行Docker编排命令就可以了。关于基础的linux系统环境和软件工具,如Git,Docker等,可以自行上网查询其安装方式,也可以参考我之前的文章:
Docker+Ollama+RAGFlow本地部署DeepSeek R1并构建本地知识库
这里就不再赘述。
在linux命令行中,先进入自己创建好的本地工作目录,执行如下命令下载Dify源码:

$ git clone https://gitee.com/dify_ai/dify.git

然后进到dify/docker目录,执行如下命令:

$ docker compose up -d

命令运行过程中显示了如下三段信息:
第一段

WARN[0000] The "DB_USERNAME" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_DATABASE" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_USERNAME" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_DATABASE" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_DATABASE" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_USERNAME" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_USERNAME" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_DATABASE" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "CERTBOT_EMAIL" variable is not set. Defaulting to a blank string.
WARN[0000] The "CERTBOT_DOMAIN" variable is not set. Defaulting to a blank string.

这显然是一段告警,表示初始的数据库字段未设置。注意到docker目录下有个readme.md文件,打开它,情况就一目了然。Dify已将所有的环境变量设置都集中到了配置文件.env中,并提供了一个样板文件.env.example,里面已经有了必要的初始化参数配置,我们只需复制样板文件就行,复制后也可以根据实际情况略加修订。

第二段

[+] Running 79/79✔ plugin_daemon Pulled                                                                                          123.2s✔ web Pulled                                                                                                    216.7s✔ weaviate Pulled                                                                                                98.6s✔ sandbox Pulled                                                                                                208.7s✔ db Pulled                                                                                                     146.3s✔ redis Pulled                                                                                                  209.9s✔ nginx Pulled                                                                                                  180.0s✔ api Pulled                                                                                                    198.8s✔ ssrf_proxy Pulled                                                                                              42.6s✔ worker Pulled                                                                                                 198.8s

这是在拉取Dify依赖的软件包,显示了其中的几大关键组件及其所消耗的时间。

第三段

[+] Running 12/12✔ Network docker_default             Created                                                                      0.1s✔ Network docker_ssrf_proxy_network  Created                                                                      0.0s✔ Container docker-ssrf_proxy-1      Started                                                                     10.6s✔ Container docker-web-1             Started                                                                     10.4s✔ Container docker-weaviate-1        Started                                                                     10.6s✔ Container docker-db-1              Healthy                                                                     16.0s✔ Container docker-sandbox-1         Started                                                                     10.4s✔ Container docker-redis-1           Started                                                                     10.4s✔ Container docker-plugin_daemon-1   Started                                                                      7.7s✔ Container docker-worker-1          Started                                                                      7.6s✔ Container docker-api-1             Started                                                                      7.7s✔ Container docker-nginx-1           Started                                                                      8.4s

这是把几大组件直接启动起来了,也就是说,这一个命令就完成了Dify的部署和运行,是不是太简单?!
总结一下,安装和运行Dify只需要执行下面的几条命令:

$ git clone https://gitee.com/dify_ai/dify.git
$ cd dify/docker
$ cp .env.example .env
$ docker compose up -d

完成以上步骤之后,打开浏览器,输入本地服务器地址(如http://192.168.1.229,默认端口号是80),就会出现Dify平台的登录界面。首次运行时需要设置管理员账号,输入账号名、邮箱地址和密码,提交完成后再以该账号登录(跟前面参考文章中的Open-WebUI的配置机制一样),出现的首页就长这个样:
在这里插入图片描述

Dify的配置

首页显示“工作室”的内容,从首页界面就能发现:Dify主要是用来创建和管理LLM应用的。应用分为五大类型,分别是:聊天助手(chat)、智能体(agent-chat)、文本生成(completion)、对话流(advanced-chat)、工作流(workflow)。可以按五大类型分类,分别罗列已经创建的应用。当然,我的实际环境中一个都还没有,在创建应用之前,需要先配置一下LLM模型!
点击页面顶端右侧的账号图标,出现一个下拉菜单,点击“设置”按钮,出现如下设置界面:
在这里插入图片描述
默认显示的是成员配置,点击左侧“模型供应商”菜单,出现模型供应商安装界面:
在这里插入图片描述
第一次进入时,会提示“尚未安装模型供应商”、“系统模型尚未完全配置”等信息。下面的待安装模型供应商列表显示了国内外各大知名供应商,包括OpenAI、Gemini、深度求索、通义千问、硅基流动等等。安装模型供应商的作用,实际上是安装访问各个供应商的模型API接口的插件(这里的模型供应商就是插件)。在安装插件之后,还要进一步配置我们在各供应商服务平台上注册的账号和API Key,这一步的目的就是建立起访问LLM模型的通道。
对于本地部署LLM模型的情况,根据运行LLM模型的方式提供相应的本地API接口即可。典型地,对于以Ollama方式运行的LLM模型,我们首先就要安装Ollama模型供应商(插件)。在待安装模型供应商列表中找到Ollama,点击“安装”按钮,
在这里插入图片描述
在出现的确认界面上继续点击“安装”按钮,等待安装过程完成。
在这里插入图片描述
安装需要一定的时间,在安装的过程中,可以点击浏览器的刷新按钮,或者也可以先浏览下其他的页面,直到页面顶端右侧(“插件”菜单的左边)的下载图标消失,就表示安装完成。
在这里插入图片描述
再次回到模型供应商的设置界面,可以看到Ollama已经出现在模型列表中(如果还是没有,可以再重新安装一遍,有时会出现安装失败的情况)。
在这里插入图片描述
点击Ollama组合框右下角的“添加模型”按钮,添加我们将要调用的LLM模型。因为Ollama可以同时部署多种不同类型和规模的LLM模型(关于用Ollama部署LLM模型的方法步骤,也可以参考我上面链接的文章),所以这里需要告诉Dify我们会使用哪些模型。在“添加模型”的界面上,按实际情况填写模型参数,如果有不清楚的地方,可以在命令行执行“ollama show model-name”命令(注意将其中的model-name改成实际的模型名称),然后将对应字段填入。下面是我的实例参数值:
在这里插入图片描述
填好参数以后,点击“保存”按钮,这个模型就会被设置生效并保存,然后出现在模型列表中。
在这里插入图片描述
添加了至少一个LLM模型之后,就可以继续设置系统模型了。点击“系统模型设置”按钮,弹出如下的标签页:
在这里插入图片描述
由于我目前只添加了一个deepseek-r1:1.5b模型,它只能用于推理,所以目前也只能设置“系统推理模型”,点击该配置项的下拉框,刚添加的deepseek-r1:1.5b就出现在下拉列表中了,选中它,然后点击“保存”按钮。完成之后,刷新页面,再次进入模型供应商设置页面就不会再有“尚未安装模型供应商”、“系统模型尚未完全配置”等提示了,已经添加的模型会显示在模型列表中,可以点击“配置”按钮对这些已经添加的LLM模型调整参数。
在这里插入图片描述
除了模型配置外,也可以在配置界面上设置Dify平台的默认语言和系统时区参数:在这里插入图片描述
也可以添加其他成员账号,供团队成员访问:
在这里插入图片描述
至此,最基础的Dify配置就完成了。至于“数据来源”和“API扩展"两项,暂且可以不管它,等后续需要更丰富的功能时再来研究。

创建应用

下面我就来尝试创建第一个应用。

回到首页,点击左上角的“创建空白应用”菜单,弹出创建应用界面:
在这里插入图片描述首先选择五大类型中的某一种,右边会展示该类型应用的基本样式。

也可以在首页点击左上角的“从应用模板创建”菜单,就会弹出各种应用模板的列表:
在这里插入图片描述
模板按“用途”进行了分类,每个模板的下面以文字标明了其所属的类型。

我就选择创建一个“聊天助手”类型的空白应用,填入应用名称和简要描述,然后点击“创建”按钮,出现了如下的应用“定义”界面:
在这里插入图片描述
这里我们就很容易理解“定义”这个词在Dify平台中的含义了。开发LLM应用确实就是个定义过程,定义的对象包括模型(前面已经演示,模型也是定义出来)、提示词、变量、知识库、元数据过滤规则等。定义界面上可以方便地进行即时的调试和预览。

来尝试一把。先选定LLM模型,并设定模型参数。我们目前只添加了一个deepseek-r1模型,所以就选定它了。对于模型参数,如果不清楚它有什么作用,可以点击参数旁边的小问号查看参数解释,如果还不清楚就上网搜索或者直接问AI助手。
在这里插入图片描述
然后填入提示词,其他字段暂且留空。完成这两步之后,就可以在“和机器人聊天”的输入框中输入问题,点击箭头符号确认输入,我们指定的deepseek模型就开始推理思考了(速度取决于咱们的硬件资源),最后给出了很详细的回答。
在这里插入图片描述
以上推理过程都是在本地完成的。如果对这个“定义”和回答还满意,我们就可以发布这个应用了。可以当它是AI应用,也可以当它是个机器人,它就是基于LLM大模型,在我们的明确定义之下,形成的一个有特定功能,面向特定方面提供服务的应用程序。点击“发布”按钮,然后点击“发布更新”,发布过程就完成了。再点击“运行”菜单,弹出一个新的应用界面:
在这里插入图片描述
点击“嵌入网站”菜单(“发布”按钮下的子菜单),弹出一段HTML代码,直接复制,可以将它粘贴到咱们自己的网站中,咱们的网站就有了AI聊天助手功能。
还可以通过API的方式来访问这个应用,点击“访问API”菜单(“发布”按钮下的子菜单),就会弹出一个页面,显示详细的使用指南,教你如何在程序中编码来调用API,以及如何处理输入和输出信息等,指导信息很具体很详细。

保存应用

创建了第一个AI应用之后,在Dify首页的应用列表中就可以看到它了。
在这里插入图片描述
进一步思考一个问题:我们定义(开发)的这些AI应用,它们的本体到底是什么呢? 我们怎么保存它,怎么传输给别人并和别人交流,怎么记录我们对应用的改进历史?像我们平常开发的其他软件一样,这个程序的“代码”在哪里呢?对于这个问题,我们需要理解一个新概念——DSL。Dify是一个AI应用定义平台,它对AI应用的具体定义,存储在一个DSL文件中。把鼠标放到上图的“测试应用”图标上,图标右下角出现一个省略符号,点击它,出现一个操作菜单,其中有一个“导出DSL”的子菜单,点击它,浏览器就会自动下载(由Dify生成)一个名为“测试应用.yml”的文件。
在这里插入图片描述
所以DSL文件的格式其实是yml,用文本编辑器打开它,看看它的内容:

app:description: 第一个dify机器人icon: 🤖icon_background: '#FFEAD5'mode: chatname: 测试应用use_icon_as_answer_icon: false
dependencies:
- current_identifier: nulltype: marketplacevalue:marketplace_plugin_unique_identifier: langgenius/ollama:0.0.6@7d66a960a68cafdcdf5589fdf5d01a995533f956853c69c54eddcf797006fa37
kind: app
model_config:agent_mode:enabled: falsemax_iteration: 5strategy: function_calltools: []annotation_reply:enabled: falsechat_prompt_config: {}completion_prompt_config: {}dataset_configs:datasets:datasets: []reranking_enable: falseretrieval_model: multipletop_k: 4dataset_query_variable: ''external_data_tools: []file_upload:allowed_file_extensions:- .JPG- .JPEG- .PNG- .GIF- .WEBP- .SVG- .MP4- .MOV- .MPEG- .WEBMallowed_file_types: []allowed_file_upload_methods:- remote_url- local_fileenabled: falseimage:detail: highenabled: falsenumber_limits: 3transfer_methods:- remote_url- local_filenumber_limits: 3model:completion_params:stop: []mode: chatname: deepseek-r1:1.5bprovider: langgenius/ollama/ollamamore_like_this:enabled: falseopening_statement: ''pre_prompt: '#角色:你是一位经验丰富的出国留学顾问#功能:1)你通晓出国留学相关的各种知识,包括全世界各个国家的排名前10的大学和全世界排名前100名的大学的情况,包括它们的历史、突出专业、师资队伍、学术地位、招生政策、教学制度、留学费用、申请流程等等;2)你熟悉国内有留学需求群体的特点,了解改革开放依赖国内留学政策及其变迁,了解实际留学人员的学习过程情况和毕业后工作发展情况,熟悉当前留学市场客户的心理特征和期望,熟悉留学市场的当前状况和未来趋势;3)你能结合留学需求人员和留学市场的国际国内行情,为客户提供最合适的留学方案,并耐心回答客户问题,完成留学申请过程的辅导以及后续跟踪服务。#限制:1)要求实事求是,基于确定的事实、历史记录和数据来回答客户问题;对于趋势分析、未来预测等要求基于有科学依据且广受认可的分析方法来进行,对其结果要明确标定,方便客户识别你的回答内容是客观事实还是分析判断;2)要求友好理性,对客户的任何问题,要友善地回答,以帮助客户充分理解具体情况并能进一步作出最优决策为宗旨,对客户问题及相关背景进行理性分析,然后组织语言,简明清晰地回答问题;不允许出现任何没有根据或者不友好的回答;3)要求合理合法,回答内容必须合乎相关国家的法律法规以及社会风俗习惯。'prompt_type: simpleretriever_resource:enabled: truesensitive_word_avoidance:configs: []enabled: falsetype: ''speech_to_text:enabled: falsesuggested_questions: []suggested_questions_after_answer:enabled: falsetext_to_speech:enabled: falselanguage: ''voice: ''user_input_form: []
version: 0.3.0

这就是我们前面所有定义的内容。一个AI应用,是以Dify平台服务为基础的一系列属性值的组合,Dify根据这些属性来修饰和调用LLM模型,并为用户呈现LLM推理的结果,对外表现为独立的AI应用。基于用户的各种定义,同一个Dify平台,可以同时为用户呈现多种不同的AI应用服务。

有了上面的DSL文件,我们就可以在不同的地方传递、共享、重现我们定义的AI应用,也可以用Git等配置管理软件进行历史版本记录和团队合作开发。在Dify首页上创建AI应用时,有个“导入DSL文件”的子菜单,其中的DSL文件就来源于此。
在这里插入图片描述

确实是好方便啊!

总结

至此,我们就简单但完整地体验了一下Dify的安装部署和使用。这个过程让我想起了之前使用字节跳动的“扣子”平台的经历,可以回顾我之前写的系列文章。相比较而言,Dify已经是一个成熟产品,一个软件平台,一个可在本地部署的AI应用定制开发平台,更准确地说,Dify是一款开发AI应用的工具软件。它也支持工作流的定义,支持知识库的应用,功能已经很强大。“扣子”平台还在开发和完善之中,它的功能跟Dify有很多重叠,但它的目标可能更远大,背景实力更强。“扣子”是一个在线平台,是字节跳动公司的一种生意模式,它将开发者聚集到这个网络平台上,支持在线开发AI应用的功能,同时与其他在线资源,比如各大LLM模型服务器、AI应用市场、抖音发布平台、豆包APP等结合起来,成为字节跳动公司抢占AI软件市场的一把利器!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/82494.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高阶数据结构——哈希表的实现

目录 1.概念引入 2.哈希的概念: 2.1 什么叫映射? 2.2 直接定址法 2.3 哈希冲突(哈希碰撞) 2.4 负载因子 2.5 哈希函数 2.5.1 除法散列法(除留余数法) 2.5.2 乘法散列法(了解&#xff09…

7.安卓逆向2-frida hook技术-介绍

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 内容参考于:图灵Python学院 工具下载: 链接:https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwdzy89 提取码&#xff1…

DB-GPT扩展自定义Agent配置说明

简介 文章主要介绍了如何扩展一个自定义Agent,这里是用官方提供的总结摘要的Agent做了个示例,先给大家看下显示效果 代码目录 博主将代码放在core目录了,后续经过对源码的解读感觉放在dbgpt_serve.agent.agents.expand目录下可能更合适&…

Android 架构演进之路:从 MVC 到 MVI,拥抱单向数据流的革命

在移动应用开发的世界里,架构模式的演进从未停歇。从早期的 MVC 到后来的 MVP、MVVM,每一次变革都在尝试解决前一代架构的痛点。而今天,我们将探讨一种全新的架构模式 ——MVI(Model-View-Intent),它借鉴了…

【YOLOv8-pose部署至RK3588】模型训练→转换RKNN→开发板部署

已在GitHub开源与本博客同步的YOLOv8_RK3588_object_pose 项目,地址:https://github.com/A7bert777/YOLOv8_RK3588_object_pose 详细使用教程,可参考README.md或参考本博客第六章 模型部署 文章目录 一、项目回顾二、文件梳理三、YOLOv8-pose…

集成30+办公功能的实用工具

软件介绍 本文介绍的软件是千峰办公助手。 软件功能概述与开发目的 千峰办公助手集成了自动任务、系统工具、文件工具、PDF工具、OCR图文识别、文字处理、电子表格七个模块,拥有30余项实用功能。作者开发该软件的目的是解决常见办公痛点,把机械操作交…

IDEA启动报错:Cannot invoke “org.flowable.common.engine.impl.persistence.ent

1.问题 项目启动报错信息 java.lang.NullPointerException: Cannot invoke "org.flowable.common.engine.impl.persistence.ent 2.问题解析 出现这个问题是在项目中集成了Flowable或Activiti工作流,开启自动创建工作流创建的表,因为不同环境的数据…

网络安全--PHP第三天

今天学习文件上传的相关知识 上传的前端页面如下 upload.html <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"&g…

【愚公系列】《生产线数字化设计与仿真》004-颜色分类站仿真(基础概念)

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…

基于 uni-app + <movable-view>拖拽实现的标签排序-适用于微信小程序、H5等多端

在实际业务中&#xff0c;我们经常遇到「标签排序」或「菜单调整」的场景。微信小程序原生的 movable-view 为我们提供了一个简单、高效的拖拽能力&#xff0c;结合 Vue3 uni-app 的组合&#xff0c;我们可以实现一个体验良好的标签管理界面。 核心组件&#xff1a;<movab…

一些较好的学习方法

1、网上有一些非常经典的电路&#xff0c;而且有很多视频博主做了详细的讲解。 2、有一部分拆解的UP主&#xff0c;拆解后会还原该器件的原理图&#xff0c;并一步步做讲解。 3、有两本书&#xff0c;数电、模电&#xff0c;这两本书中的内容很多都值得学习。 5、某宝上卖的…

《1.1_4计算机网络的分类|精讲篇|附X-mind思维导图》

网络相关知识 按使用范围分类 公用网 由电信部门或其他提供通信服务的经营部门组建、管理和控制&#xff0c;向全社会提供服务的网络。 专用网 由某个单位或部门组建、仅供本单位或部门内部使用的网络。 按传输介质分类 有线网络 如&#xff1a;双绞线、同轴电缆、光纤…

Git 和 GitHub 学习指南本地 Git 配置、基础命令、GitHub 上传流程、企业开发中 Git 的使用流程、以及如何将代码部署到生产服务器

Windows 上 Git 安装与配置 下载安装&#xff1a;访问 Git 官方网站下载适用于 Windows 的安装程序。运行安装包时会出现许可协议、安装目录、组件选择等界面&#xff08;如下图&#xff09;。在“Select Components”页面建议勾选 Git Bash Here 等选项&#xff0c;以便在资源…

航空航天领域对滚珠丝杆的精度要求有多高?

航空航天领域对滚珠丝杆的精度要求非常高&#xff0c;尤其是飞行器、火箭和卫星等载具的导航和定位系统都需要高精度的滚珠丝杆&#xff0c;以确保高精度的位置控制和稳定的导航性能。那么&#xff0c;航空航天领域对滚珠丝杆的精度要求有多高&#xff1f; 1、定位精度&#xf…

技术篇-2.5.Matlab应用场景及开发工具安装

Matlab 在数学建模和数值分析等领域具有无可替代的地位。它几乎涵盖所有常见数学算法的内置函数库&#xff0c;使得从数据预处理、方程求解到优化算法的实现&#xff0c;无需编写大量底层代码即可快速完成&#xff1b;同时&#xff0c;Matlab 强大的可视化能力&#xff0c;可以…

Vtk概览1

vtk环境搭建 见&#xff08;VTK开发环境配置(Visual Studio C)-详细图文教程-CSDN博客&#xff09; 在学习vtk图形图像进阶的第二章时&#xff0c;通过vs2022建的控制台程序&#xff0c;编写运行示例2.1 发现 不显示图像。 #include <iostream> #include<vtkRenderW…

【数据集】基于ubESTARFM法的100m 地温LST数据集(澳大利亚)

目录 数据概述一、输入数据与处理二、融合算法1. ESTARFM(Enhanced STARFM)2. ubESTARFM(Unbiased ESTARFM)代码实现数据下载参考根据论文《Generating daily 100 m resolution land surface temperature estimates continentally using an unbiased spatiotemporal fusion…

Lucide:一款精美的开源矢量图标库,前端图标新选择

名人说:博观而约取,厚积而薄发。——苏轼《稼说送张琥》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、前言:为何选择 Lucide?二、Lucide 是什么?1. 基本介绍2. Lucide vs Feather三、如何在项目中使用 Lucide?1. 安装图标包(以 React 为例)2…

BeanUtil和BeanUtils有什么区别

BeanUtil 和 BeanUtils 是两个常见的工具类&#xff0c;通常用于 Java 开发中处理对象之间的属性复制或转换。它们的功能可能看起来相似&#xff0c;但实际上它们来自不同的库&#xff0c;并且在实现细节和使用方式上存在一些差异。 以下是它们的主要区别&#xff1a; 1. 来源…

【CF】Day66——Edu 168.D + CF 853 (Div. 2).C (树 + 二分 + 贪心 | 组合数学)

D. Maximize the Root 题目&#xff1a; 思路&#xff1a; 树上二分&#xff0c;中下题 我们可以发现如果 x 可以&#xff0c;那么 x - 1 肯定也可以&#xff0c;所以可以直接二分答案 具体的&#xff0c;我们每次二分能增加的值 mid &#xff0c;如果 a[i] < mid&#xf…