Linux究竟是如何启动的:从固件到登录界面
在任何运行了 systemd 的机器上打开终端,然后运行以下命令: systemd-analyze 在我正在使用的这台笔记本电脑上,运行该命令后得到的结果是: 启动过程耗时:5.855秒(固件加载时间)+ 8.469秒(引导加载程序加载时间)+ 3.106秒(内核加载时间)+ 12.181秒(用户空间处理时间),总计29.613秒。在进入用户空间后,系统又用了12.175秒才完成启动过程。 将这四个数字相加,得到的结果应该是29.611秒,而不是最后一行显示的29.613秒。这个差异是真实存在的,并非计算错误:`systemd-analyze`在显示结果时会对每个阶段的耗时进行四舍五入处理,因
在任何运行了 systemd 的机器上打开终端,然后运行以下命令:
systemd-analyze
在我正在使用的这台笔记本电脑上,运行该命令后得到的结果是:
启动过程耗时:5.855秒(固件加载时间)+ 8.469秒(引导加载程序加载时间)+ 3.106秒(内核加载时间)+ 12.181秒(用户空间处理时间),总计29.613秒。在进入用户空间后,系统又用了12.175秒才完成启动过程。
将这四个数字相加,得到的结果应该是29.611秒,而不是最后一行显示的29.613秒。这个差异是真实存在的,并非计算错误:`systemd-analyze`在显示结果时会对每个阶段的耗时进行四舍五入处理,因此其中几毫秒的差异会在最终结果中被忽略掉。虽然这个差距很小,但它能帮助你避免浪费时间去寻找其实并不存在的问题。
这四个数字代表了Linux系统启动过程中的四个主要阶段:内核加载耗时3秒,引导加载程序加载耗时8.5秒,固件加载耗时近6秒,在这些步骤完成之前,系统的另外14秒钟实际上是在进行一些初始化工作。而大多数人往往只关注其中的一个或两个阶段。
本文详细介绍了Linux系统的完整启动过程,从固件将控制权交给引导加载程序,到最终出现登录界面这一整个流程。这里提到的所有操作你都可以亲自尝试进行,而且几乎不需要使用root权限。
目录
您所需要的准备
任何运行systemd的Linux系统都符合要求,这包括Ubuntu、Debian、Fedora、Arch以及2026年人们通常会安装的其他操作系统。另外还需要一个终端窗口,就这样。
我用来进行测试的系统是Ubuntu 22.04.5 LTS,它运行的是5.15.0-190-generic版本的内核,通过UEFI模式从一块NVMe硬盘启动,该硬盘使用ext4文件系统作为根文件系统,而systemd的进程ID为1。您的系统配置可能会有所不同,有时差异会很大,我会指出这些差异可能出现在哪些方面。
有一个命令需要以root权限执行,而在许多系统中,还有一个文件的访问权限是受限的。当我们讨论到这些内容时,我会特别指出来。
Linux启动过程实际上包含四个阶段
“启动”这个词让人以为整个过程只有一个步骤。但实际上它分为四个阶段,而且这些阶段之间几乎没有任何交互。
首先运行的是固件,它位于主板上的一块芯片上,其任务是找到可启动的部分并启动它。
之后固件会将控制权交给引导加载程序,然后自己停止工作。引导加载程序的任务是找到内核文件,将其连同初始文件系统一起加载到内存中,然后立即开始执行内核代码,之后它也会停止运行。
内核会初始化硬件设备,挂载根文件系统,并启动一个用户空间进程。之后内核就不再直接参与系统的运行了,但它会一直为这个进程提供支持服务。
那个第一个被启动的进程,其进程ID为1,它负责启动系统中的其他所有进程。
每一个阶段的控制权交接都是单向的。固件并不会在Linux系统运行过程中处于待命状态以提供帮助;引导加载程序在完成任务后也会从内存中消失。记住这一点,因为这可以解释为什么在systemd-analyze报告中出现的四个数值是由不同的因素计算得出的,因此它们的含义也各不相同。
固件,以及Linux系统无法直接访问的部分
在报告的5.855秒这个时间值中,只有固件的运行时间不是由Linux系统自己测量的。您可以通过以下命令查看这一数值的具体来源:
cat /sys/firmware/acpi/fpdt/boot/bootloader_launch_ns
输出结果为:5855973785秒。
这就是5.855973785秒,也就是systemd-analyze报告中显示的5.855秒这个数值——实际上这个数字是被截取后呈现给用户的。固件会在将控制权交接之前,将这一数值写入一个名为“Firmware Performance Data Table”的ACPI表格中,而内核则会从该目录中读取这些数据。另外还有一些其他组件也会参与完成这个统计过程:
cat /sys/firmware/acpi/fpdt/boot/exitbootservice_end_ns
在我测试的这台系统上,最终测量得到的时间为14325507185秒,也就是14.325秒。这个数值实际上包含了固件和引导加载程序运行所花费的总时间,与将这两个阶段的时间相加得到的结果是一致的。
这里就是容易让人犯错的地方。实际上,关键并不在于系统是否支持UEFI,而在于你的固件是否真的会发布FPDT信息。很多支持UEFI的系统其实并不会发布这类信息,尤其是虚拟机;在那些系统中,使用systemd-analyze工具检查时,会发现既没有“固件阶段”,也没有“加载程序阶段”的记录,系统的启动过程直接从内核开始计算。因此,你应该查看的是相关表格,而不是是否支持UEFI:
ls /sys/firmware/acpi/fpdt/boot/ 2>&/dev/null || echo "没有FPDT信息,所以无法获取固件相关的启动时间数据"
如果这个命令没有任何输出,那就说明你的固件并没有发布这类信息,而从Linux系统内部也无法恢复这些数据。
近六秒的启动时间确实相当长,而从Linux系统内部来说,我们几乎无能为力。这部分时间主要被用于内存初始化、设备检测,以及硬件厂商在系统交付之前预先执行的某些操作。对于那些拥有快速存储设备的笔记本电脑来说,这个阶段往往就是整个启动过程中耗时最长的环节,这一点会让那些把优化工作重点放在服务程序上的用户感到十分惊讶。
引导加载程序,以及你选择的那五秒钟
这个数值会直接影响你对整个启动过程的理解。在上面的例子中,加载程序阶段耗时8.469秒,这一时间几乎是内核启动时间的三倍。但实际上,其中几乎没有任何时间真正用于实际的操作。
grep ^GRUB_TIMEOUT /etc/default/grub
在这台机器上,相关的配置如下:
GRUB_TIMEOUT="5"
在这8.469秒的时间里,有5秒钟其实是GRUB在倒计时,等待用户按下按键,但实际上这个按键永远不会被按下。这是由安装程序一次性设置的配置选项,之后就再也不会被修改了。如果你曾经疑惑为什么自己的机器虽然硬件配置很好,但启动速度却很慢,那么这就是你需要首先检查的地方,而且这也是本文中提到的最简单的解决方法。
当GRUB在等待的时候,它已经知道接下来要执行哪些操作了。你可以查看它传递给内核的指令:
cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-5.15.0-190-generic root=UUID=b4d0343e-9df4-40a7-be97-dcd51bdbf553 ro splash intel_iommu=on vt_handoff=7
这一行代码实际上就包含了引导加载程序与内核之间所有的交互信息。BOOT_IMAGE指明了要加载的内核版本;root=UUID=...指定了要挂载的文件系统,通过UUID来识别文件系统,这样即使硬盘编号发生变化,这个配置也不会受到影响;ro表示初始时要以只读模式挂载文件系统;splash表示使用图形化启动界面而不是文本界面;intel_iommu=on表示启用IOMMU功能;vt_handoff=7则确保了虚拟终端能够无缝地切换到图形化界面。
GRUB会将两个文件加载到内存中:内核程序和初始文件系统镜像。之后,它就会立即执行内核程序,自己也就不再存在了。
内核阶段:三秒钟让机器进入正常工作状态
现在,Linux系统已经启动运行了。内核会自行解压文件,配置内存管理机制,激活CPU,初始化各种驱动程序,然后寻找合适的根文件系统。请观看这一过程的发生,这些时间戳是从内核开始运行的那一刻起开始计量的:
journalctl -k -b -o short-monotonic | head
[ 0.000000] devils-dell kernel: 微代码已更新至0x100版本
[ 0.000000] devils-dell kernel: Linux版本为5.15.0-190-generic
[ 0.000000] devils-dell kernel: 命令行参数:BOOT_IMAGE=/boot/vmlinuz-5.15.0-190-generic
[ 0.000000] devils-dell kernel: 支持的CPU型号:
“0”这个时间点表示内核开始执行,而不是你按下电源按钮的时刻。在这一点之前的所有内容——包括那14秒钟内的固件和引导加载程序——都完全不在这个计时范围内。这就是关于内核启动时间戳需要了解的第一件事,也是为什么使用dmesg查看输出时,某些设备的运行速度会显得比实际快很多的原因。
你可能尝试过使用dmesg来查看这些信息,但会遇到如下错误:
dmesg: 读取内核缓冲区失败:操作不被允许
这是有意设置这样的限制的,你可以通过以下命令来验证这一点:
sysctl kernel.dmesgrestrict
Ubuntu系统将kernel.dmesgrestrict的值设置为1,这样就会限制只有root用户才能读取内核缓冲区中的信息,因为这些信息可能被攻击者利用。因此,建议使用journalctl -k来查看相关日志,因为这个命令是通过系统日志来读取信息的,而且任何普通用户都可以使用它。
/proc/cmdline文件中还包含另一个值得注意的细节。从该文件可以看出,内核被设置为以只读模式挂载根文件系统,但你现在使用的系统显然能够对磁盘进行写入操作。让我们来看看当前的设置情况:
findmnt -n -o SOURCE,FSTYPE,OPTIONS /
/dev/nvme0n1p2 ext4 rw,relatime,errors=remount-ro
现在根文件系统被设置为可读写模式,这说明肯定有某种设置发生了变化。通常情况下,根文件系统会先以只读模式挂载,这样就可以安全地对其进行检查了;因为如果在进程正在对文件系统进行写入操作时进行检查,很可能会导致问题变得更加严重。
当检查完成后,用户空间会再次将同一文件系统设置为可读写模式。而errors=remount-ro这个选项其实起到了相反的作用:如果内核在后续使用过程中遇到了文件系统错误,它会自动恢复到只读模式,而不会继续尝试对不再可信的文件系统进行写入操作。
现在让我们找出内核开始不再单独执行操作的那一确切时刻:
journalctl -b -o short-monotonic | grep -m1 'systemd[1]'
[ 3.152109] devils-dell systemd[1]: 模块“autofs4”已被加载
在开始运行3.15秒后,PID为1的进程记录了第一条日志信息。这个时间点与systemd-analyze工具所显示的3.106秒的时间相符,也就是说从这一刻起,内核就不再单独执行任何操作了。此后,内核只会响应系统调用,而关于接下来应该执行什么操作的决策都是由用户空间来做出的。
什么是initramfs,以及它所解决的“先有鸡还是先有蛋”的问题
在Linux启动过程中,有一个隐藏在3秒钟内的步骤,这个步骤正是最让人们感到困惑的部分。
内核需要挂载你的根文件系统。为此,它需要你的存储控制器的驱动程序以及文件系统的驱动程序,可能还需要一些用于组建RAID阵列、打开加密磁盘或激活LVM的代码。这些驱动程序都以模块的形式存在,而这些模块则位于根文件系统中——不过目前内核还无法挂载这个根文件系统。
为了解决这个问题,人们使用了这样一个方案:创建一个小型文件系统,由引导加载程序与内核一起加载到内存中,这个文件系统本身是完备的。让我们来看一下具体的内容:
ls -l /boot/initrd.img-$(uname -r)
lsinitramfs /boot/initrd.img-$(uname -r) | wc -l
lsinitramfs /boot/initrd.img-$(uname -r) | grep -c '\.ko'
上述路径和工具是Debian与Ubuntu的标准配置。在Fedora系统中,这个文件系统的路径是/boot/initramfs-$(uname -r).img,使用的工具是lsinitrd;而在Arch系统中,通常使用的是/boot/initramfs-linux.img,对应的工具是lsinitcpio。
在这台机器上,这个文件系统的大小为79,945,887字节,大约相当于76MB,其中包含了2,318个文件,其中1,386个是内核模块。这是一个真正可以正常运行的、虽然功能极为简化的Linux系统,它的存在唯一的目的就是帮助内核找到并挂载真正的根文件系统。
一旦完成了这个任务,这个小型文件系统就会继续执行后续的操作。它不会退出系统,而是会替换掉真正的根文件系统,让自己“退居幕后”,然后执行真正的/sbin/init命令,而整个过程中并不会创建新的进程树。进程ID为1的进程会在执行过程中改变自身的身份,但仍然保持原来的进程ID。
如果你使用的是Arch或经过精简配置的Fedora系统,那么你的initramfs文件系统的大小可能会只有这个大小的十分之一。因为Ubuntu会构建一个包含各种通用驱动程序的initramfs文件系统,这样同一个文件系统就可以在任何机器上正常启动。这种做法实际上是牺牲了文件系统的体积来换取更好的兼容性,而lsinitramfs>命令可以帮助你了解自己系统中实际包含了哪些内容。
进程ID为1的进程,以及另外12秒钟都用来做了什么
内核在3.1秒时完成了初始化工作,而登录界面则在用户空间开始运行的12.175秒时才出现。那么在这中间发生了什么呢?
systemctl get-default
systemctl list-unit-files --no-legend | wc -l
systemctl list-units --type=service --state=running --no-legend | wc -l
graphical.target
472
44
systemd的运作机制是:用户需要指定一个目标,系统会自动确定各个任务执行的顺序。在这里,目标就是graphic.target,而这个目标又依赖于multi-user.target,而multi-user.target的实现则需要一个可以正常工作的网络环境、文件系统、日志记录机制等等。
在这台机器上,共有472个单元文件被安装了起来,其中实际上有44个服务正在运行中。systemd会根据这些信息构建出一个依赖关系图,并尽可能地并行启动所有能够同时运行的服务,只有当存在真正的依赖关系时,系统才会暂停相应的进程等待后续操作完成。
正是这种并行性使得启动过程的分析比看上去要复杂得多。有数十个进程同时在运行,而最终的结果并不是这些进程耗时之和。
为什么 systemd-analyze blame 会让你对启动时间产生误解
接下来人们往往会尝试使用的那个命令其实是错误的,而这个陷阱其实值得人们故意去踩一下:
systemd-analyze blame | head -5
3分钟48.947秒:fstrim.service
44.548秒:plocate-updatedb.service
13.953秒:apt-daily.service
4.875秒:docker.service
4.106秒:NetworkManager-wait-online.service
将上述结果与整个启动过程的总耗时进行对比就会发现:用户空间进程的运行耗时仅为12.181秒,而列表中的第一个条目却显示启动过程花费了三分钟四十九秒。这两个数字都是正确的,但这种矛盾恰恰就是问题的关键所在。
blame 命令会列出systemd启动的每一个服务所耗费的时间,但它并没有说明这些服务是否真的参与了你的登录流程。让我们来看看列表中的前三项:
systemctl show fstrim.service -p TriggeredBy -p WantedBy
systemctl list-timers fstrim.timer
TriggeredBy=fstrim_timer
WantedBy=
NEXT LEFT LAST PASSED
周一 2026-09-14 00:59:36 IST 4天后
周一 2026-09-07 00:33:35 IST 2天前
WantedBy 的值为空,这意味着这个服务在启动过程中并没有被其他服务触发;它是通过定时器来自动执行的。它上一次运行是在两天前,下一次运行将在4天后进行。
plocate-updatedb.service 和 apt-daily.service 的情况也是一样的,它们也是由各自的定时器来触发的。
在blame列表中的前三项服务,虽然总共耗时接近5分钟,但实际上它们对你的登录过程并没有产生任何影响。
真正与启动流程相关的服务是docker.service,它在列表中排在第四位,耗时为4.875秒。
我更希望你们能从中理解一个普遍性的道理,而不是仅仅记住这些具体的例子。如果某个测量工具所反映的信息超出了你真正关心的范围,那么它所提供的数据就会产生误导——这种误导的程度恰恰取决于那些无关信息所占的比例。blame命令本身并没有问题,只是人们使用它的目的与它实际能解答的问题不一致而已。
理解关键路径
实际上,要回答这个问题应该使用以下命令:
systemd-analyze critical-chain
graphical.target @12.175s
└─multi-user.target @12.175s
└─docker.service @7.297s +4.875s
└─network-online.target @7.295s
└─NetworkManager-wait-online.service @3.188s +4.106s
└─NetworkManager.service @3.151s +35ms
└─network-pre.target @3.150s
└─netfilter-persistent.service @1.377s +1.772s
└─local-fs.target @1.374s@符号表示某个服务/进程开始处于活跃状态;+符号则表示该服务/进程持续运行的时间。现在,那些“12秒”的数据就容易理解了:其中将近9秒钟被docker.service占用了(其运行时间为4.875秒),而NetworkManager-wait-online.service则占用了4.106秒。Docker要求在启动任何服务之前,网络系统必须能够正常工作,因此这些时间数据是按顺序排列的。NetworkManager-wait-online是大多数桌面系统中首先需要关注的一个组件。它的作用正如其名称所示:会一直等待直到网络真正连接成功为止;而对于笔记本电脑来说,当它连接到Wi-Fi时,这个过程可能会持续几秒钟,期间系统什么都不会做。这个组件的存在是为了确保那些需要网络才能运行的服务能够在网络连接建立之后再开始启动。你是否需要这样的保障机制,其实是一个需要根据具体使用情况来决定的问题。
关于这些输出结果,有两点需要注意:首先,这些结果显示的只是一条处理流程,并非所有导致系统延迟的原因;因此,那些虽然会引发延迟但并不属于关键路径上的操作根本不会被显示出来。其次,@符号所标记的时间顺序并不能代表事件发生的真实因果关系。以我的输出为例,其中有一个Docker网络挂载操作的耗时为11秒,而另一个操作的完成时间为650毫秒——这一对比看起来似乎有些不可思议,但事实上这些数据只是用来展示各操作之间的依赖关系,并非表示事件发生的实际顺序。在查看这些数据时,请注意+符号后面的数值代表成本,而结构部分则反映了各种操作的排序规则;千万不要将这些嵌套的数据理解为按时间顺序排列的。
为什么你的Linux系统启动时间会不同
以上所有数据都是针对同一台机器进行多次测试后得出的结果,而这些具体的数字本身其实并不那么重要,真正重要的是这些数据背后的分析方法。在将你自己的测试结果与我的进行比较之前,请先了解哪些环节会导致时间差异,以及为什么会出现这种差异。
在这里,固件启动所花费的时间变化幅度最大,而且这与Linux系统几乎没有任何关系。例如,一台拥有大量RAM用于初始化操作、同时还连接了十几个USB设备的桌面电脑,其启动时间可能会达到15秒,而我的笔记本电脑则只需要6秒。如果你的固件提供了快速启动选项,那么这个选项的作用确实就像它的名字一样:它会跳过一些初始化步骤,但这样一来,你可能就无法及时发现新插入的硬件设备。
加载程序的运行时间主要取决于你设置的超时时间,因此这其实也是你可以自己决定的。内核的启动时间则与你的机器上安装了哪些硬件设备、以及需要解压和搜索的initramfs文件的大小有关。正因为如此,像Ubuntu这样的通用型initramfs,在这里的测试结果会比专门为你的机器定制的initramfs要长一些。如果你的根文件系统被设置了加密功能,那么其中一部分看似属于内核启动时间的数据,实际上其实是你在输入密码所花费的时间。
用户空间的运行时间才是真正反映你的机器与我的机器之间差异的地方,因为这部分时间取决于你实际安装了哪些软件。对于我来说,使用Docker会使得启动时间增加近5秒;但如果你不使用它,那么这个时间并不会增加。
在得出任何结论之前,请先多次运行测试。在同一台机器上进行多次测试时,启动时间往往是会有所变化的,因此单次测试的结果并不能为你提供足够准确的信息。
登录屏幕以及系统交接过程
最后一步就是你会看到的那个登录界面了:
systemctl status display-manager --no-pager | head -1
loginctl show-session $(loginctl | awk 'NR==2{print $1}') -p Type -p Class
● lightdm.service - Light Display Manager
Type=x11
Class=user
在这台机器上,显示管理程序是LightDM,它是在graphical.target配置项的作用下被启动的。它会在一个虚拟终端中创建一个会话窗口,然后绘制登录界面并等待用户输入密码。在登录过程中,systemd会为登录用户创建相应的会话环境。当你输入密码后,显示管理器会通过PAM进行身份验证,随后systemd会分配相应的会话资源,你的桌面环境也会作为用户进程启动。
这里就体现了内核命令行中设置的vt_handoff=7这一参数的作用:它能让虚拟终端直接传递给图形界面层,而不会出现屏幕变黑或重新绘图的情况,这就是系统启动流畅与否的关键所在。
从这一阶段开始,内核就会继续执行它一贯的任务,也就是处理各种系统调用。如果你想了解后续发生的具体过程,我曾经详细探讨过这个话题。
结论
现在你可以用具体的数据来分析自己的系统启动过程,而不再只是靠猜测。以这款笔记本电脑为例:29.6秒的启动时间中,有近6秒钟是受硬件固件控制的,无法进行优化;8.5秒钟用于加载引导程序,这部分内容大部分是可以删除的;3秒钟属于内核运行阶段;剩下的12秒钟则主要用于用户空间中的操作,其中有两项服务需要等待网络连接才能完成执行。
更重要的是,你现在有了区分“真实数据”和“近似值”的方法。systemd-analyze blame这个命令虽然看起来很专业,但实际上它回答的是一个没人真正会问的问题;而systemd-analyze plot > boot.svg生成的图表则能让你更直观地了解各个阶段的耗时情况。
还有一些额外的建议:在Debian和Ubuntu系统中,可以使用sudo update-grub来重新生成引导配置文件;在Fedora系统中,则可以使用sudo grub2-mkconfig -o /boot/grub2/grub.cfg命令。重新启动系统后,你会发现启动时间缩短了大约5秒钟。此外,你还可以检查NetworkManager-wait-online.service这个服务是否真的占用了4秒钟的启动时间——对于大多数桌面环境来说,这个服务的耗时通常并不明显。
结语
我之所以会研究这些内容,是因为我正在开发一款采用Android风格权限模型的Linux发行版。在这种系统中,程序只能获得其配置文件中明确请求的权限,而不会拥有用户拥有的所有权限。因此,系统的启动顺序实际上就成为一个与安全性相关的问题:在登录之前启动的每个进程,都比之后运行的任何进程拥有更多的权限。直到我能够清楚地了解每一个进程的作用及其存在的必要性,我才真正有能力判断哪些进程确实需要这些额外的权限。
你可以在thechris.in上阅读我写的更多文章。
相关文章
在Linux系统中,系统调用究竟是如何工作的
这是一个简单的C程序。它调用了三次`clock_gettime()`函数,然后向标准输出输出了5个字节。 #include #include #include int main(void) { struct timespec ts; for (int i = 0; i 这两者看起来都属于系统调用。它们都是向内核请求程序本身无法获取的信息:当前时间,以及文件描述符的访问权限。 gcc -O0 -o mystery mystery.c strace ./mystery 2>&1 | grep -c clock_gettime 答案是`0`。 write() 函数被立即执行了,而那三次`clock_
阅读全文
演示:运用eBPF技术让您的人工智能系统及API焕发新的活力 🪄
Dan Finneran探讨了在生产环境中使用未被妥善管理的AI生成代码所带来的风险,并展示了如何利用eBPF技术在Kubernetes中拦截并控制与AI相关的API请求。他解释了如何通过内核级别的套接字钩子来实现对提示信息的过滤、模型切换、令牌限制以及系统调用功能的管控,从而在无需修改应用程序的源代码或重新启动容器的情况下保障AI系统的安全性。 作者:Dan Finneran
阅读全文
人工智能接待员的工作原理:人工智能电话客服系统背后的技术架构
从表面上看,人工智能接待员似乎很简单:来电者说话,系统做出响应,然后对话持续进行,直到来电者得到答案或与相关人员取得联系。 但实际上,在这一对话的背后,存在着一系列电话基础设施、语音识别技术、语言模型、应用逻辑、应用程序接口、数据库以及呼叫路由机制。 有趣的地方并不在于人工智能模型本身,而在于这些组件是如何协同工作,将音频流转化为有用的商业行动的。 那些希望拥有这类功能的企业有两种选择: 它们可以购买现成的产品。目前市场上已经有专门的人工智能接待系统,比如Nextiva公司的 XBert ,以及Goodcall、Dialzara等公司提供的相关工具。 或者,它们也可以自行开发这样的系统,而这篇
阅读全文
如何构建能够识别自身知识盲区的AI系统:一份实用指南
大型语言模型从根本上改变了我们构建企业内部应用的方式。它们使开发人员能够创建出能够分析复杂企业数据、回答内部查询以及自动化重复性工作流程的智能软件。 然而,将基于大型语言模型的应用从本地原型阶段部署到生产环境时,往往会暴露出一个关键的可靠性问题: 过度自信 。 标准的语言模型被优化为生成在统计学上最有可能出现的下一个输出结果,而不是用来评估它们自身的准确性。当遇到模糊的输入指令、不完整的检索信息或超出模型适用范围的边缘情况时,这些模型会毫无顾忌地生成看似合理的虚假答案,甚至编造事实,而不会向用户提示任何不确定性。 在那些对业务运行至关重要的企业环境中,一个盲目猜测的人工智能应用无疑会带来严重的
阅读全文