Elasticsearch:使用 ESRE 和生成式 AI 了解 TLS 日志错误
作者:DAVID HOPE
本博客介绍了 Elasticsearch 相关性引擎 (ESRE) 及其 Elastic Learned Sparse Encoder 功能的新颖应用,特别是在日志分析中。
最近发布的 Elasticsearch Relevance Engine™ (ESRE™) 包含一系列重要功能,可增强搜索能力,并可使用与询问生成式 AI 问题相同的自然语言来查询 Elasticsearch®。
这让我想知道我们如何将其用于日志。 开始使用 Elastic Learned Sparse Encoder 模型相当容易,这是一种支持语义搜索的重要 ESRE 功能 - 我们将在本博客中介绍如何使用它进行日志记录。 此功能与 Elasticsearch® 当前的功能有很大不同,因为它理解单词的含义并广泛搜索具有相似含义或与我搜索的单词同义的单词。
Elastic Learned Sparse Encoder 也是一种高效的搜索排名解决方案,在域外空间(即,当模型未严格根据用户数据进行训练时),可产生比传统 BM25 和基于向量的 KNN 搜索更好的结果。 后期交互模型通过对原始文本进行编码,以便在查询时提供更多上下文信息,从而提高搜索准确性。
Elastic Learned 稀疏编码器如何工作?
当 Elastic Learned Sparse Encoder 应用于原始文本(例如日志消息)时,它会生成一个数据结构。 该结构的键代表原始文本中找到的术语及其同义词。 在称为术语扩展(text expansion)的过程中,模型根据术语和同义词与原始文本的相关性,从 30K 固定术语的静态词汇表中添加和删除数据中的术语和同义词。 这与向量嵌入类似,创建辅助数据结构(或多个结构)并将其存储在字段中,然后可用于查询中的即时语义匹配。
每个术语还有一个关联的分数,它捕获了其在原始文本中的上下文重要性。 我们将此数据结构称为(评分的)词袋(bag of words)或 BOW。
BOW 示例
请注意如何捕获输入文本的单词、词干、添加同义词以及最终评分。 另请注意,“Scored Bag of Words” 结构只是 [word => Score] 的映射。 稍后你将看到这是如何为我们的系统日志生成的。
在查询时,输入查询字符串在后台经历与我们在摄取时执行的原始日志文本相同的推理过程,以生成 BOW。 然后,将此 BOW 与索引中原始日志文本的 BOW 进行匹配,类似于带有嵌入向量的 k 最近邻搜索。 搜索结果的最终排名分数是一个公式的结果,该公式考虑了查询 BOW 中的匹配单词和原始日志文本的分数。
我们来举个例子说明它的用处,如果我正在搜索 “Are there any TLS warnings?”。 在我的系统日志中,以下日志行 “2023/05/24 17:10:33: Error getting config status, workload certificates may not be configured: HTTP 404” 匹配,尽管该特定日志行中不存在精确匹配。 ESRE 了解 TLS 与证书相关。
这里需要注意的是:此搜索是 “模糊” 搜索,可能不会为你提供所需的结果。 你甚至可以使用更好的模型来实现此目的,例如根据你自己的数据训练的模型。 重要的是要记住,这只是当我们需要解决模糊问题时帮助我们指明正确方向的另一个工具。 能够在搜索过程中一般性地讨论问题,而不必非常具体地讨论我们看到的错误,这可以帮助我们进行根本原因分析。
你可以启动并运行它,然后只需单击几下即可开始使用它来搜索日志。
这能够改变你进行问题检测和修复的方式,因为 ESRE 可能会返回你以前可能从未想过分析但与你要解决的问题相关的日志。 这是减少 MTTx 指标的胜利。 然后,你可以使用从 Elastic 返回的文档和相同的搜索词向 ChatGPT 等生成式 AI 引擎提出问题,我们将在最后探讨该引擎,并且在本博客的其他用例中也进行了探讨。
在本博客的最后,你将得到一个如下所示的高级流程:
设置步骤
在接下来的几个步骤中,我将逐步介绍:
- 在 Elastic Cloud 上获取帐户(必须是版本 8.8 及以上)并安装 Elastic Agent
- 在此环境中设置 ESRE 并将日志连接到 ESRE
- 使用 Kibana® 通过 ESRE 搜索日志
- 使用 ChatGPT 快速创建可与 Elasticsearch 和 ESRE 配合使用的应用程序
第 0 步:在Elastic Cloud上创建帐户
在继续之前有一些注意事项:
1)确保在创建 Elastic Cloud 实例时单击 “Advanced Options”(如下所示)并为本博客添加至少 4GB RAM 的机器学习节点。
2) 当你按照以下说明操作时,请务必遵循 “Add System” 集成步骤。
牢记这些注意事项,按照说明开始使用 Elastic Cloud。
牢记这些注意事项,按照说明开始使用 Elastic Cloud。
第 1 步:安装 Elastic Learned Sparse Encoder 模型
这些步骤将部署 Elastic Learned Sparse Encoder 以与系统日志一起使用。 文档页面位于此处。中文指南可以在这里获得。
Elastic Learned Sparse Encoder 是由 Elastic 训练的检索模型,使你能够执行语义搜索以检索更相关的搜索结果。 此搜索类型为你提供基于上下文含义和用户意图的搜索结果,而不是精确的关键字匹配。
转到 Analytics -> Machine Learning:
点击 Model Management -> Trained Models:
选择 Elastic Learned Sparse EncodeR v1 并单击最右侧的下载按钮。
下载后,我们需要启动它。
就本博客而言,默认设置就可以了。
第 2 步:修改索引模板
接下来,我们需要向传入文档添加几个字段,以便 Elastic Learned Sparse Encoder 用于 tokens 和搜索。 我们可以通过更新我们想要使用模型的 log 类型的索引模板来做到这一点。
在本节中,我们将添加 token 字段和 text_field — 这两个字段都是与 Elastic Learned Sparse Encoder 模型一起使用所必需的。 运行推理时,模型将在 text_field 字段中查找日志消息。 然后,推理步骤会将日志消息文本转换为 token 权重对列表,该列表存储在 tokens 字段中 - 这就是我们需要这些映射的原因。
索引模板允许我们定义索引中文档的格式和映射,在本例中为 syslog 索引。
前往 “Stack Management”。
接下来,转到 Index Management -> Index Templates。 我们将修改 “syslog” 索引,如下所示:
单击索引名称,选择右下角的 “Manage”,然后选择 “Edit”。
跳至步骤 4:“Mappings”。
并添加以下映射:ml.tokens 和 text_field。
单击 Next 并保存。
第 3 步:添加自定义 ingest pipeline
接下来,我们将添加一个自定义摄取管道,以便 Elastic Learned Sparse Encoder 可以将 token 添加到发送到 Elastic 的文档中。 这是语义搜索所必需的 —— 请对此进行深入研究。 很酷的是我们可以在文档中看到 token,这让你直观地了解其工作原理。
管道步骤首先将日志消息复制到 text_field 字段中,因为这是模型查找所需数据的地方。 通过推理步骤,它会将日志消息文本转换为 token 权重对的列表,该列表存储在 ml.tokens 字段中。
请注意,如果你在此索引上的日志摄取非常繁忙,则推理将增加一点处理时间 - 如果你的负载非常重,这可能不是一个好主意,但对于我们这里的小型用例来说,这应该还好。
首先,前往 Ingest pipeline:
创建一个名为 “logs-system.syslog@custom” 的新摄取管道。 这是一个从主 syslog 摄取管道调用的特殊名称,并且存在于所有 “Managed” 管道中,因此你可以添加自定义摄取步骤。
现在让我们向该摄取管道添加两个处理器:
1)第一个处理器将使用日志消息字段设置 text_field,其中包含我们要使用 Set 处理器和 Copy from 操作搜索的日志数据,如下所示。
2)添加的第二个处理器是 “inference” 处理器,它将生成语义搜索所需的 token。 按以下方式进行设置。
字段映射:
{"text": "text_field"
}
Inference 配置:
{"text_expansion": {"results_field": "tokens"}
}
完成后,单击 “Create pipeline”。
第 4 步:滚动索引
要强制索引 rollover 并使用我们创建的新索引模板,请转到 Dev Tools 并执行以下 POST:
POST /logs-system.syslog-default/_rollover/
第 5 步:欢迎使用日志进行语义搜索
现在,转到发现并创建一个仅显示系统日志的新数据视图:
你可能需要稍等一下才能在此处填充一些数据。 一旦有数据,你应该会看到 ML Tokens 字段填充如下:
这就是 Elastic Sparse Learned Encoder 的魔力。你可以在此处看到的 token 增强了它如何能够理解日志行的语义,并使你能够找到与搜索参数具有相似含义的日志。
现在我们可以运行语义搜索。 将下面的语言框从 KQL 更改为 Lucene。
在搜索框中输入以下内容。 这里,文本扩展查询使用自然语言处理模型将查询文本转换为 token 权重对列表,然后将其用于针对我们上面定义的 rank features 字段的查询中。
{"text_expansion":{"ml.tokens":{"model_id":".elser_model_1","model_text":"Are there any TLS warnings?"}}}
恭喜! 你刚刚使用 Elastic 进行了语义搜索。
现在这里还有一件事要做:我们需要对结果进行排序,以便我们看到排名靠前的搜索结果。 添加 _score 字段,如下所示。
还有 “message” 字段。
现在我们可以按从高到低的顺序对其进行排序,这可以告诉我们什么是强匹配(类似于 Google 上搜索结果的排名方式):
现在让我们看看是否可以将其连接到 ChatGPT!
第 6 步:将其连接到 ChatGPT
现在让 ChatGPT 为我们编写一些代码。 我们询问 ChatGPT:
“Can you write some code to query Elasticsearch and then send the documents that are returned to ChatGPT?”
它编写了以下代码:
from elasticsearch import Elasticsearch
from openai import OpenAI, ChatCompletion# Initialize Elasticsearch
es = Elasticsearch([{'host': 'localhost', 'port': 9200}])# Search for documents in Elasticsearch
body = {"query": {"match_all": {}}
}res = es.search(index='your_index_name', body=body)# Initialize OpenAI
openai = OpenAI(api_key='your_openai_api_key')# Send documents to ChatGPT
for hit in res['hits']['hits']:message = {"role": "system","content": f"Document : {hit['_source']}"}# Generate response from ChatGPTresponse = openai.ChatCompletion.create(model="gpt-4.0-turbo",messages=[message])# Print the model's responseprint(response['choices'][0]['message']['content'])
现在这很容易修改,因此我们可以使用新的 Elasticsearch “Semantic query”,如下所示。
更改以下行:
# Search for documents in Elasticsearch
body = {"query": {"match_all": {}}
}
下面就到此为止。 请注意,这将确保我们只获得排名前三的结果,从而获得最相关的结果:
body = {"query": {"text_expansion": {"ml.tokens": {"model_id": ".elser_model_1","model_text": "Are there any TLS warnings?"}}},"size": 3,"sort": [{"_score": {"order": "desc"}}]
}
并更改这一行:
"content": f"Document : {hit['_source']}"
变成这样:
"content": f”Are there any TLS warnings? Log line : {hit['_source']}"
这使我们能够将 Elasticsearch 结果包含在 ChatGPT 查询中,从而大大降低产生幻觉的可能性,并且更有可能为我们提供相关的诊断。 在这里查看最终结果。
ChatGPT responds:
The error message you're seeing seems to suggest that there might be an issue related to Transport Layer Security (TLS) certificates. The HTTP 404 error indicates that the requested resource cannot be found.
- Incorrect or incomplete configuration: The error suggests that workload certificates may not be configured. If your service requires TLS certificates to communicate securely, but these have not been properly set up, this could cause the issue. You should review your configuration to make sure TLS is correctly set up
- Wrong path: The system might not be able to find the certificates because they're not located at the specified path in your configuration. You need to ensure that the path to the certificate files is correct.
- Permission issues: There could be issues with file or directory permissions that are preventing your system from accessing the certificate files. You should ensure that the relevant user or service has the necessary permissions to access these files.
- Server or service is not available: The HTTP 404 error could indicate that the server or service you're trying to reach is not currently available or doesn't exist. You need to check if the server is running and that the endpoint is correct. Now if you didn’t want to do this yourself, I have created an application that does all of this over here, in this GitHub repository. When you run it, you get this nice graphical user interface:
因此,将所有内容连接起来后,我们解决方案的架构最终如下所示:
现在你已经了解了如何设置 Elastic Learned Sparse Encoder 模型,我向读者提出挑战,要求他们弄清楚他们还可以将该模型用于哪些其他用途,以及他们可以提出哪些日志记录用例。 你还可以扩展此示例以在 Elastic 中缓存和存储 ChatGPT 响应,就像此博客一样,使你能够启动知识库。 随着时间的推移,你可以用自己的知识来增强这一点。
SRE 开箱即用的卓越相关性
在本博客中,我们指导你完成设置用于日志分析的 Elastic Learned Sparse Encoder 的过程,并向我们的读者提出了探索该模型的新用途的挑战。 一个简单的示例可能涉及探测任何与 TLS 相关的问题,如本博客中所示。
随着 Elasticsearch 相关性引擎的推出,我们将独特的 Elastic 检索模型带到你的手中。 这种即用型模型可以轻松地与我们的全系列数据摄取方法集成,包括本博客中所示的摄取管道。 开箱即用,任何人都可以在其可搜索语料库中使用它,而且它足够紧凑,可以容纳在笔记本电脑内存的范围内。
Elastic 的学习稀疏编码器为搜索用例(包括日志)提供跨域语义搜索,如本博客所示,无需定制调整或培训即可提供高度相关的搜索结果。
现场测试一致表明,混合排名技术可产生最相关的搜索结果集。 然而,一个关键因素 —— RRF——一直不存在。 我们现在正在集成 RRF 来满足你的应用程序搜索需求,使你能够融合向量和文本搜索功能。
详细了解 Elasticsearch 和生成式 AI 的可能性。
在这篇博文中,我们可能使用了第三方生成式人工智能工具,这些工具由其各自所有者拥有和运营。 Elastic 对第三方工具没有任何控制权,我们对其内容、操作或使用不承担任何责任,也不对你使用此类工具可能产生的任何损失或损害负责。 使用人工智能工具处理个人、敏感或机密信息时请务必谨慎。 你提交的任何数据都可能用于人工智能培训或其他目的。 无法保证你提供的信息将得到安全或保密。 在使用之前,你应该熟悉任何生成式人工智能工具的隐私惯例和使用条款。
Elastic、Elasticsearch 和相关标志是 Elasticsearch N.V. 的商标、徽标或注册商标。 在美国和其他国家。 所有其他公司和产品名称均为其各自所有者的商标、徽标或注册商标。
原文:Logs: Understanding TLS errors with ESRE and generative AI — Elastic Search Labs
相关文章:

Elasticsearch:使用 ESRE 和生成式 AI 了解 TLS 日志错误
作者:DAVID HOPE 本博客介绍了 Elasticsearch 相关性引擎 (ESRE) 及其 Elastic Learned Sparse Encoder 功能的新颖应用,特别是在日志分析中。 最近发布的 Elasticsearch Relevance Engine™ (ESRE™) 包含一系列重要功能,可增强搜索能力…...

Swing程序设计(3)JDialog窗体
文章目录 前言一、JDialog窗体的介绍二、JDialog窗体的使用 1.JDialog的常用构造方法2.实例展示及分析总结 前言 JDialog窗体是窗体中的另一种类型的窗体,指对话框窗体。与JFrame窗体类似,绝大部分对于JFrame窗体使用的方法,对于JDialog窗体也…...

类和对象(1)
文章目录 1.面向过程和面向对象初步认识2.类的引入3.类的定义4.类的访问限定符和封装4.1访问限定符4.2封装 5.类的作用域6.类的实例化6.2结构体内存对齐规则 7.this指针7.2this指针的特性 封装(补充) 1.面向过程和面向对象初步认识 C面向对象但不纯面向…...

学会用命令行创建uni-app项目并用vscode开放项目
(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 创建 uni-app 项目 命令行创建 uni-app 项目 编译和运行 uni-app 项目: 用 VS Code 开发 uni…...

java.lang.ClassCastException: android.os.BinderProxy cannot be cast to ...
项目开发遇到下面这个报错了! 问题原因 直接说原因,就是因为进程间不能直接传递对象,应该传递该Binder对象的映射(代理对象),所以类型转换就出错了。如果在同一个进程中,直接传递对象没有关系&a…...
AIGC(生成式AI)试用 3 -- 专业主题
何为专业? 主要研究某种学业或从事某种事业 我的理解可能是在某个方向、某个行业,专业的更靠谱、说了更算、表达的更晰,结果更有说服力 本次提问:你我的专业 生成式AI知道你我的专业吗?生成式AI如何诠释你…...
rsyslog-日志管理 logrotate-日志轮转
日志的管理的方式,以及怎么自己写一个管理日志的小脚本,其实也不能算脚本 管理日志的进程 rsyslogd:绝大部分日志记录,和系统操作有关,安全,认证sshd,su,计划任务at,cron… httpd/nginx/mysql: …...

类和对象续
目录 包 自定义包 包的访问权限控制 常见的包 Static成员 静态成员变量 静态成员方法 代码块 构造块 静态块 重写 继承 继承是啥? 父类成员访问 子类中访问父类成员变量 两者不同名 两者同名 子类中访问父类对的成员方法 super 子类构造方法 …...

SpringCloud:Feign实现微服务之间相互请求
文章目录 🎉欢迎来到Java学习路线专栏~SpringCloud:Feign实现微服务之间相互请求 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒🍹✨博客主页:IT陈寒的博客🎈该系列文章专栏:Java学习路线📜其他专栏…...

LeetCode 1359. Count All Valid Pickup and Delivery Options【动态规划,组合数学】1722
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...

[杂谈]-从硬件角度理解二进制数
从硬件角度理解二进制数 文章目录 从硬件角度理解二进制数1、概述2、模拟电路3、数字电路4、逻辑电平5、TTL 器件的电压水平6、总结 1、概述 二进制数以 2 为基数系统表示,该系统只有两 (2) 个不同的数值,即 0 和 1。就像最常见的那样,十进制…...

Fast-DDS 服务发现简要概述
阅读本文章需要对DDS基础概念有一些了解,一些内容来自Fast-DDS官方文档,一些是工作中踩过的坑。 1. 服务发现阶段 满足OMG标准的DDS服务发现分为两部分,分别是: PDP(Participant Discovery Protocol 参与者发现协议):参与者确认…...

基于spingboot的websocket订阅、广播、多人聊天室示例
概述 基于spingboot的websocket多人聊天系统。包括订阅,广播、点对点单人聊天,多人聊天室功能。 详细 一、运行效果 简单示例 广播 单人聊天 多人聊天室 二、相关代码 websocket配置 package com.iamgpj.demowebsocket.config;import com.iamgpj.d…...

Linux mac Windows三系统 局域网文件共享方法
主要工具: Samba是一个开源的软件套件,允许Linux系统与Windows系统之间共享文件和打印机。 一、首先是Linux共享的设置 ①安装 sudo apt-get install samba ②创建共享文件夹 sudo mkdir /home/share ③配置用户 sudo smbpasswd -a kequan ④修改…...

Java——比较器
引入的背景 我们知道基本数据类型的数据(除boolean类型外)需要比较大小的话,直接使用比较运算符即可,但是引用数据类型是不能直接使用比较运算符来比较大小的。那么,如何解决这个问题呢? 在Java中经常会涉…...
【数据结构】初识泛型
文章目录 一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。这种限制对代码的束缚就会很大。所以我们引入了泛型。泛型,泛顾名思义就是广泛的意思。就是适用于许多许多类型。从代码上讲,就是对类型实现了参数…...
代码随想录--哈希--有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 示例 1: 输入: s "anagram", t "nagaram" 输出: true 示例 2: 输入: s "rat", t "car" 输出: false 说明: 你可以假设字符串只包含小写字母。…...
MySQL——数据的增删改
2023.9.12 本章开始学习DML (数据操纵语言) 语言。相关学习笔记如下: #DML语言 /* 数据操作语言: 插入:insert 修改:update 删除:delete */#一、插入语句 #方式一:经典的插入 /* 语法: insert …...

云服务器与http服务器
如何与http服务器建立连接(客户端)? http请求设计格式: 例子: 发送http请求 http数据响应格式: 接收http服务器返回的数据需要进一步进行字符串处理操作,提取有用的数据。...

golang教程 beego框架笔记一
安装beego 安装bee工具 beego文档 # windos 推荐使用 go install github.com/beego/bee/v2master go get -u github.com/beego/bee/v2masterwindows使用安装bee工具时碰到的问题; 环境配置都没有问题,但是执行官网的命令:go get -u github…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...