All posts by zr9558

应届生入职避雷指南:为什么要经营职场人设?

为什么要经营职场人设

职场人设,就是我们在工作环境中所展现的形象和个性。这不仅仅是你的一些工作技能和专业能力的展示,还包括你的人格魅力、行为举止、沟通方式等多方面的因素。经营好职场人设,对于任何一位职场新人(尤其是应届生)来说,都有着重要的意义。

1. 帮助树立个人品牌

在职场上,人们通常会根据你的表现进行分类和打标签。如果你能够经营好自己的职场形象,尤其是早期(比如应届生),你能给同事和上司留下深刻且正面的印象,这有助于你在团队中脱颖而出。良好的职场人设不仅有助于你更好地融入团队,还能提高你的职业发展机会。

2. 增强职业稳定性和发展空间

无论是初入职场的应届生,还是有一定工作经验的社招人员,良好的职场形象都能让你在工作中更加游刃有余。上司和同事会更愿意与你合作,愿意给你更多的资源和机会。这种影响力和关系的积累,是职业发展的基石。

该公开什么,不该公开什么,哪些信息需要谨慎

经营职场人设并不是让你把个人生活完全隐藏,而是需要知道哪些信息可以公开,哪些需要谨慎。

1. 教育经历:适当公开

教育背景是职场中的基础信息,尤其对于应届生来说,教育经历是一项非常重要的亮点。可以适当分享自己的毕业院校、专业以及所学知识,这有助于他人了解你的基础能力,甚至还能够找到一些校友。如果不想公开,还可以用“普通学校”这样的字眼进行合理的应对。社招人员可以根据需要分享最具代表性的教育经历,但不必过度强调。对于工作人士而言,把带着学校LOGO的衣服穿来公司,是完全没有必要的,如果是名牌学校的话可能还会引发其他同事一些不好的言论。

2. 工作经历:根据情况分享

对于应届生来说,工作经历一般较少,通常会强调过去的实习经历和校园活动等。当然了,应届生可以适当分享这些经历,这有助于展示你的工作能力和学习态度。但对于社招人员来说,工作经历的分享需要考虑到公司文化、同事关系及公司政策。例如,如果有些过于私密或者涉及到竞争的工作经历,最好选择不公开或轻描淡写地一笔带过。而且薪资和收入等信息是完全不需要对外公开的,毕竟在很多公司这都是不被允许讨论的话题。

3. 个人软肋和生活细节:谨慎公开

职场中,大家理论上会更加关注你的工作能力和团队合作能力,而不是你的私人生活。身高、体重、家庭状况、父母养老金、兄弟姐妹关系、是否买车、是否买房等私人信息,通常不适合公开在公司层面。公开这些信息有可能会被同事误解,甚至被用作刻意针对的素材,影响职场形象。过于详细的财务状况、债务问题等经济方面的信息,也不应在职场中公开。这些私人财务问题不仅涉及隐私,还可能被不正当解读为你有经济压力,影响你在职场中的形象。另外,身高、体重、皮肤等身体特征,虽然在日常生活中或许是一个轻松话题,但在职场环境中显得不够专业,容易让你被归类为关注外貌而非能力的人。在面试或日常工作中,过多谈论这些问题可能会给人留下不够成熟的印象,影响别人对你能力的评估。

但请注意,确实有一些团队的领导或者同事会想法设法地打听各种各样的消息,包括家庭状况、婚姻状况、父母家庭住址、家里父母是否存在养老金、父母是否预留了给你买房买车的钱、是否是独生子女、兄弟姐妹有多少个等和工作毫无关系的问题。说好听点是领导为了了解员工,说不好听一点是领导在寻找员工的软肋。所以,即使有领导或者同事专门问你的私人事情,也可以通过构造虚假人设的方式进行应对,不要把自己的私事随便对外说。

4. 性格与情绪管理:避免过度泄露

有时候,在与同事的交流中,我们可能会想分享一些情绪上的感受,但这也要注意尺度。职场中,过于暴露个人情感,尤其是负面情绪(如抱怨、焦虑、愤怒等),容易让他人产生不必要的担忧,影响职场形象。保持冷静、理性,展示你的自我管理能力,会让你在同事和领导眼中更具可靠性。过度强调自己的情绪管理问题、工作中的困难或压力,可能会让同事和上司担心你的稳定性和抗压能力。尤其是在团队合作中,暴露过多的个人弱点或情绪波动,可能会影响你在团队中的被信任程度和团队的合作氛围。

如何在工作层面适当进行社交

应届生职场上能够适当的展示个人生活的一面,能够让你更有亲和力,但过度曝光私人生活则可能让你显得不够专业。建议在沟通中保持以下几个原则:

  1. 专注于工作:谈论工作内容、职业规划时,展现出你对工作的热情和认真。
  2. 适度分享生活:可以适当提及一些个人爱好、生活中的小确幸,但避免涉及过多私人情感、生活状态、身体状况和家庭情况。
  3. 建立良好人际关系:职场中的人际关系不仅是建立在工作能力的基础上,适当的人际互动和关心也是非常重要的,但切记要把握好度。
  4. 不要与同事有经济往来:尤其是借钱等事情,最好想办法婉言拒绝,不要与同事有太高额度的金钱往来。

总结

应届生在刚进入职场时,往往会面临很多挑战,但通过合理经营职场人设,可以让你在同事和领导眼中建立良好的第一印象,以便顺利融入职场。适当展示自己的优势,保持一定的隐私界限,专注于自己的职业发展,将会使你在职场中获得更多的机会和认可。总的来说,职场上公开信息的原则是:适当展示专业性、工作能力和生活中的正面形象,而将私人生活、情感困境以及可能影响职场表现的负面信息保持私密,才能更好地保护自己的职场形象和职业发展。

多头管理的混乱:新人无处可逃的任务漩涡

1.权责不清,工作变成了跑腿

在某些企业里,权责不清的现象屡见不鲜,尤其是在新员工加入的时刻。理应是专业的人做专业的事情,但新员工竟然变成了老员工们的公共财产,谁都有权力找新人做事。软件开发的老员工找新人写代码,硬件的同事找新人整理硬件知识,文档整理的同事找新人整理文档,文宣的同事甚至在没有提前沟通的前提下找新人去进行节目表演。这种混乱的工作分配和多头管理工作,不仅让新员工感到迷茫和困惑,更让他们在没有明确职责的情况下,陷入了无休止的跑腿工作中。

从新员工的培训制度来看,他们本应通过清晰的岗位职责和工作安排,迅速融入团队并提升专业技能,但现实是,他们被要求承担各种不相干的任务,往往无法集中精力做好本职工作。这种现象不仅剥夺了他们的成长机会,更让整个团队的效率低下,甚至形成了“谁都可以让新人干活”的恶性循环。

2.多头管理,谁来负责?

一个新人上面有无数个领导,这听起来像是一个笑话,却是许多企业内实际发生的事情。在权责不清的情况下,新员工往往被各个部门和同事临时拉去做事,工作范围和责任没有清晰界定。对于新人来说,他们每天的工作内容并不固定,经常被不同的“领导”要求去完成各种任务,从代码编写到文档整理,甚至包括一些完全与岗位无关的任务。这些给新人安排工作的人有可能真正是新人的直接领导和汇报对象,也有可能是+2甚至+3的上级,极端情况下还有可能是更低级别的老员工。在这种情况下,一名新人往往不是只需对一个上级负责,而是同时要听从多个领导的指令,每个人都有权力给他们布置任务,哪怕这些任务完全没有关系。结果,工作变得支离破碎,每天的工作内容不断变化,完全没有明确的方向。软件开发的老员工让新人去写代码,硬件的同事要求整理PCB图纸,文案团队更是希望他们参与到无关的宣传活动中。一个新人,背后似乎有无数个上级等待着把任务塞给他,而这些任务往往彼此之间没有任何关联。

这种多头管理不仅让新员工迷失方向,也使得团队合作变得混乱和低效。没有明确的负责人,没人对新员工的工作进展和质量负责,大家都在忙着指挥新人干活,给他们指派各种各样的任务,而真正重要的工作却往往被忽视。当每个部门和同事都把工作甩给新人时,真正能帮助新人成长和进步的指导和支持却显得极为稀缺。

更可怕的是,这种多头管理并没有明确的责任归属。谁给了任务,谁就消失了,不负责任务的执行和结果,最终所有的错误和问题都会由新人背锅。而新人在这种管理下,甚至无法找到明确的指导和支持,面对的是一个个不相关的任务和层出不穷的要求。所有的责任和压力都无形中推到了他们的肩上,却没有任何一个领导能为他们提供明确的方向和有效的反馈。最终,新人不仅失去了成长的机会,还在任务塞满中迷失了自己的角色。

这种管理方式,最终的后果往往是团队的效率低下,员工的积极性受到打压。新员工变成了万能工具人,他们不仅无法专注于自己的本职工作,还要在各种任务中不断挣扎。团队领导忽视了明确职责和责任分工的重要性,结果是让一个新人同时面对多个领导、无数个任务,却没有任何明确的责任和支持。在这种混乱的管理模式下,不仅新人,整个团队的工作效率和协作能力都会大打折扣。

3.无责分工,只会让工作陷入无序

在一个正常运作的团队中,每个人的职责应该清晰明确,工作分配也应当科学合理。然而,在权责不清的环境下,员工的角色和任务变得模糊不清,造成了工作上的极大混乱。例如,开发人员把软件开发的任务外包给新人,硬件团队把PCB设计和整理的工作推给新人,文案团队让新人参与不相关的宣传和表演活动,导致新人无所适从,最终每一项工作都做得不尽如人意。权责不清的后果是严重的,既影响了工作效率,也剥夺了新员工应有的成长机会。面对这些无休止的跑腿任务,新人根本没有机会专注于自己的专业发展,更别提提升个人技能了。而团队的长远发展也会因为这种管理漏洞,陷入低效和混乱的困境。只有明确职责和分工,才能真正让每个人在自己的岗位上充分发挥作用。

以软件开发岗位为例,新人和相应的岗位就应该一一对应起来,避免不专业的人干专业的事情。

岗位岗位职责技能要求
Android 开发工程师负责Android平台应用的设计、开发和维护。 – 与团队合作确保产品功能实现与UI设计的契合。 – 编写高质量代码,进行单元测试和系统测试。 – 优化应用性能,确保流畅体验。 – 跟踪Android系统更新,优化产品功能和体验。精通Java、Kotlin,Android SDK。 熟悉常用框架(如Retrofit、Glide、Room)。 熟悉设计模式(如MVC、MVVM)。 优化应用性能经验。
iOS 开发工程师负责iOS平台应用的设计、开发、优化和维护。 – 撰写技术文档,协助解决技术难题。 – 优化功能、性能和用户体验,确保流畅性。 – 跟进iOS版本更新,合理应用新特性。精通Swift、Objective-C,iOS开发经验。 熟悉开发工具(如Xcode)和常用框架(如Cocoa Touch、CoreData)。 性能优化经验。
Web 开发工程师负责Web端应用开发和维护。 – 与UI设计师、后端工程师协作,保证功能和设计适配。 参与需求分析,确保系统架构和需求匹配。 编写高质量代码,进行单元测试与集成测试。 持续优化性能,提升用户体验。精通HTML、CSS、JavaScript,熟悉框架(React、Vue、Angular)。 前后端分离开发经验,Node.js等优先。 熟悉Web标准与浏览器兼容性。
前端开发工程师负责网站和应用的前端页面开发及用户交互实现。 – 与设计师合作,确保UI界面和交互的完美还原。 – 使用框架(React、Vue)实现富交互页面和动态效果。 优化前端性能,提高页面加载速度。 – 编写代码时保持良好文档和注释。精通HTML5、CSS3、JavaScript及相关框架(如React、Vue)。 熟悉响应式设计、浏览器兼容性处理。 前端构建工具(如Webpack、Gulp)经验。
后端开发工程师负责后端系统的设计、开发与维护。 与前端合作,设计并开发API接口。 优化数据库设计,确保数据存储和查询高效。 编写高质量代码,确保系统安全性。 参与系统架构设计,保证系统可扩展性与可靠性。精通后端开发语言(如Java、Python、Go、Node.js)。 熟悉常用数据库(MySQL、PostgreSQL、MongoDB)。 熟悉分布式架构、微服务技术。
算法开发工程师负责产品中算法模块的设计、开发和优化。 研究并实现机器学习、深度学习等算法。 优化算法模型,提升其效率和准确性。 与团队协作,确保算法和产品的结合效果。 撰写技术文档,记录优化细节。精通Python、TensorFlow、PyTorch等机器学习框架。 扎实的数学和统计学基础,能独立实现复杂算法。 了解计算机视觉、自然语言处理等方向。
数据分析师负责数据收集、清洗和分析,为决策提供数据支持。 使用统计工具和数据挖掘算法,发现潜在业务机会和问题。 设计并执行数据分析报告,跟踪指标变化。 为产品和营销团队提供洞察。 持续优化数据分析方法。精通Excel、SQL,能独立编写查询。 熟悉Python/R等数据分析语言,具备数据处理能力。 熟悉数据可视化工具(如Tableau、Power BI)。
测试工程师负责软件测试的计划、执行和管理,确保产品质量。 撰写并执行测试用例,进行功能测试、性能测试、压力测试等。 与开发人员密切合作,确保问题及时反馈并修复。 记录测试结果,编写缺陷报告和测试文档。熟悉常见的测试工具(如Jira/Selenium)。 了解自动化测试与手动测试流程。 熟悉常见的测试方法与测试用例编写。

这些岗位职责清晰划分了每个角色在软件开发中的职责范围,能帮助团队成员明确自己的职责与工作目标,避免出现任务重叠和责任不清的情况。每一个人最好只做其中一项最多两项,避免一个人干N件事情。

4.员工的时间和精力,岂能随意浪费?

新员工作为团队的一员,他们本应该集中精力在自己的岗位上,通过学习和积累,逐步承担更多的责任。然而,在一个权责不清的工作环境中,时间和精力被无意义的任务消耗掉。开发人员被要求去整理PCB图纸,软件人员被拉去参加节目的排练,而本该属于他们自己职责范围内的工作却被一再推迟。这种现象不仅浪费了新员工的时间和精力,更让他们丧失了成长的机会。工作不再是有条不紊的任务分配,而是成了无序的接力赛。长此以往,员工的积极性会被削弱,团队的合作也会变得越来越低效。真正的责任应该在团队内部分清楚,明确每个人的工作内容,让每个人都成为一个专业的人而不是万能的人,才能让整个团队高效运转。

5.谁该负责?责任模糊,问题无人解决

权责不清最大的隐患之一就是,问题无法得到及时解决。每当新员工遇到困难时,他们往往不知道该找谁解决问题,因为每个布置任务的人都认为那不是自己的责任。所有软件开发的任务往往被推给开发组,但硬件团队也会找新人去处理一些技术问题;文档整理工作从属于行政后勤,但文宣团队却时不时让新人参与到创意和表演中。这种责任的模糊性,导致了工作无法顺利推进,问题的解决也缺乏专人负责。

当每个人都在推卸责任时,整个团队的工作效率必然下降,而新员工在这种环境下,很难获得实际的帮助和支持。最终,这种模糊的责任分配会让团队陷入停滞,员工在困惑和无所适从中消耗了大量的时间和精力,却很难看到任何成长的机会。责任的清晰和分工的明确,才是提高团队效率和凝聚力的关键所在。

6.建立明确的责任体系,才能让团队稳步前行

要解决这种因权责不清导致的混乱局面,必须从根本上梳理每个岗位的职责和任务分配。每个员工都应清楚自己的工作范围和职责,而不是随意成为其他人工作的备胎。明确的职责和清晰的管理体系,不仅能让新员工快速融入团队,还能帮助他们集中精力提升专业能力。只有通过明确的职责划分,员工才能真正发挥出各自的优势,团队的整体效率也会大大提升。领导者应当主动为每个员工设定清晰的目标,并确保每个员工都能承担相应的责任和任务,避免出现混乱和跑腿的局面。唯有如此,团队才能稳步前行和在竞争激烈的市场中脱颖而出。

扣绩效成了解决方案?领导到底是管理,还是威胁?

在某些企业中,绩效考核似乎已经变成了一种威胁工具。每次领导安排工作,开口或者结束总会提到一句话:“如果XX时间之前做不完就扣绩效。” 看似是对员工的提醒,实则是对员工精神的压迫。每个人都有不同的工作节奏和情况,不考虑员工的实际压力和工作环境,仅仅依赖扣绩效来激励,难道不觉得荒唐吗?绩效应该是员工努力和成长的结果,而不是让员工像提心吊胆的犯人一样,在每个工作任务前感受到无形的恐惧。真正的领导,应该通过激励和沟通来提升团队的能力,而不是用绩效威胁让大家战战兢兢地完成任务。每次领导任务布置之后,员工并非专注于如何高效地完成工作,而是想着“怎样做才能不被扣绩效”。领导用绩效威胁来压制员工的创造力,最终只会让团队处于一种低效、低质量的循环中。

每当员工开始工作任务之前,某些公司的领导最常说的不是“把它做好之后有奖励”,而是“任务做不完就扣绩效”。在这种管理模式下,员工的绩效仿佛成了赌博,一切都取决于任务是否能在限定的时间内完成,而不是员工的实际表现。领导是否意识到,过度依赖绩效威胁这种粗暴的管理手段,最终只会让员工丧失对工作的热情和对领导的信任?如果领导真正关心绩效,就该关注员工的努力和成长,而不仅仅是通过扣分来维持表面上的绩效。

所谓的绩效管理,应该是对员工努力和成果的合理评估,而不是一种随意的惩罚工具。通过扣绩效来压榨员工的动力,看似能带来短期的任务完成,但却无视了员工的实际情况和心理状态。长此以往,员工不仅缺乏主动性和创造力,反而会对工作产生厌倦情绪。难道领导觉得绩效威胁是提高效率的捷径吗?不,这只是对管理的懒惰和对员工不负责任的表现。

绩效管理还应该关注员工的成长,而不是通过惩罚来维持短期的表面成绩。通过绩效激励、引导、支持员工的成长,才是一个团队有效的管理方式。一个有效的绩效管理体系,能够帮助员工明确目标、提高自我认知、激发工作热情,同时提升整个团队的整体表现。然而,将绩效管理简单化为扣绩效来威胁员工,实际上是对其功能的严重误解。通过设定清晰的目标、合理的评估标准和及时的反馈,绩效管理能够帮助员工找到成长的方向,提升他们的工作满意度,并推动公司实现更长远的目标。

绩效管理不仅仅是公司对员工的评估工具,更是企业文化的重要体现。如果一个公司只关注短期的完成任务而忽视了员工个人发展的需求,结果往往是员工在压力下完成任务,缺乏主动性和创造力,企业也会因为失去人才的活力而陷入瓶颈期。真正的绩效管理,不是惩罚,而是通过明确的目标和适当的激励机制,使员工持续提升,进而推动公司不断前进。

职场打地鼠游戏:谁有空就让谁做

在某家公司,岗位说明书大概和尼斯湖水怪一样神秘:人人都听过,但没人真正见过。招聘时HR说你是软件开发工程师,入职后才发现除了后端开发之外,也要承担前端开发、数据库开发等一大堆开发事项,还要负责使用Excel手动处理数据、甚至在年会中担任活动主持和参与节目表演。日常的工作中,领导说得最多的口头禅是:“XX,你最近手头有空吧?这个临时的任务交给你了!”至于小李的本职工作到底是开发、测试、设计、还是文员,全凭领导当天的心情随机定义。

在这个职场环境下,员工入职时领的不是岗位说明书,而是一套职场变形金刚的口头指南:今天你是数据分析师,明天化身工厂调解员,后天可能被临时任命为团队年会总导演。领导对此理直气壮:“年轻人要成为多面手,争取从多个角度进行锻炼!”仿佛工作职责是健身房年卡,全身上下的肌肉练得越杂就越值回票价。一位员工私下吐槽:“上次工作写文档到半夜,全是因为领导一时兴起,要求我在下班前突然要一份从未写过的技术方案。”

这种全员多面手的模式,初看像极了武侠小说里的全能门派:人人会编程、懂测试、能写稿、擅沟通、会做Excel和PPT、甚至还会进行短视频的策划和拍摄。但现实却是,当设计师被拉去做测试,程序员被逼着去当项目经理,产品经理突然接手人事招聘,每个人都成了样样通、样样松的职场半吊子。有一位员工在离职的个人总结里面写道:“我在这家公司学会了十项技能,但我最终离开时甚至说不清自己到底算什么岗位。”更荒诞的是,当项目出了问题,干活最多最杂的那个人都成了无辜的背锅侠。无论说什么“这不是我的职责啊!”“当初是你说让我帮忙的!”的话语都无法改变老板的决定。权责不清的恶果远不止效率低下。在某次项目会议中,由于权责没有划分清晰,导致每个人都说自己没有过错。而事后追责会上,领导痛心疾首:“你们缺乏主人翁意识!”却绝口不提自己从未明确过谁是“主人翁”。这种责任大锅饭文化,让团队逐渐学会了两大生存法则:“干得好是团队的功劳,干得差是个人的失误”,以及“谁认真谁倒霉”。

全员打杂的工作模式,表面看是资源最大化利用,实则是管理者懒政的遮羞布。当招聘时喊着专注细分领域,入职后却要求十八般武艺样样精通,本质是把团队的管理成本转嫁给了员工。讽刺的是,管理者往往将这种权责混乱美化为扁平化创新。每次开会的时候领导总会激情澎湃:“我们打破岗位边界,激发员工潜能!”,“很早之前,我们的老员工就承担了万能工程师的角色,任何事情都能够搞定。”私下里,新来的员工们苦不堪言:“潜不潜能不知道,但我的血压潜能确实被激发了。”

更荒诞的是责任认定的罗生门。当项目延期和偏离主线的时候,领导拍桌子质问:“为什么没人提前预警?”而真相是:实习生三天前就汇报过风险,但当时他正被借调去参加团队的节目表演;产品经理本想同步进度,但临时被派去其他地方进行测试项目;技术负责人刚打开文档,就被拉去领导的办公室进行项目沟通。这种“谁有空谁填坑”的逻辑,让企业成了职场版的《鱿鱼游戏》:你永远不知道下一关要突然解锁什么技能,但所有人都默契地不提面试沟通的岗位职责和实际的工作半毛钱关系都没有。

而那些真正重要的工作,往往在混乱中永久性搁浅。某团队曾高薪聘请资深开发架构师,结果他60%的时间在整理各种文档和ppt、提交各种各样的临时材料,直到离职时才说出真相:“入职N个月,我设计的系统架构文档还在电脑里吃灰。”更讽刺的是,管理层例会上总有人痛心疾首:“我们缺乏核心竞争力!”却选择性忽略核心竞争力早被琐碎任务肢解成了碎片。就像医院院长让外科医生天天帮患者挂号取药,还抱怨外科医生的手术成功率低。这种管理模式的终极代价,是团队的管理者亲手培养出一支空心化团队。当员工把50%以上的精力花在应付临时任务、厘清责任边界、表演虚假忙碌上,所谓的核心竞争力就成了贴在墙上的过期标语。某次会议,领导在全员会上怒吼:“为什么没有人对项目整体负责?”台下员工在私下讨论:“上次领导让某某专家对项目整体负责的时候,某某专家还在亲自剪辑短视频给领导汇报工作呢。”

当能者多劳成为默认规则,劣币驱逐良币的戏码便天天上演。勤快的人被塞进更多杂活,聪明的老油条则学会了装忙摸鱼。某些优秀员工总结出“三不原则”:不主动、不拒绝、不负责。只要不主动认领任务,就没人能定义这是你的分内事;只要不拒绝领导派活,就能混个态度积极的好名声;只要不签字担责,就能在出事时全身而退。于是,真正重要的项目总在踢皮球中烂尾,而办公室晚上总是永远挤满了看起来很忙的演员。

要终结这场职场闹剧,或许该从承认一个常识开始:专业的人做专业的事,才是对效率最大的尊重。明确岗位边界不等于官僚主义,而是让员工在清晰的赛道上深耕价值。当企业停止把员工当人肉补丁,他们反而能缝补好真正的管理漏洞。如果一家公司把所有岗位都变成全能战士或者耗材,那么它的未来注定是没有专业性的。

周一和节后不准请假:是谁在给管理者的懒惰买单?

每个周末和假期结束后,总有一群打工人在周一的清晨挣扎着起床,不是因为他们懒惰,而是因为公司那条不成文的规定——“周一和节后返工第一天严禁请假”。领导们振振有词:“假期堆积的工作没人做怎么办?”仿佛员工是永不停转的齿轮,必须严丝合缝地卡在岗位上。但这条规定背后,暴露的何止是管理者的傲慢?它更像是一块遮羞布,掩盖了管理规划的无能与对人性的漠视。

这种“周一不准请假”的规定,像极了现代职场版的“何不食肉糜”——领导们坐在空调房里,一边喝着刚磨好的咖啡和泡好的茶,一边对着考勤表指指点点,却永远理解不了为什么有人会在长假后需要多睡一天。他们似乎坚信,员工的大脑和电脑一样,按下开机键就能瞬间满血运转。可现实是,人类的生理节律从不会为KPI让路:周一的早高峰地铁里,多少双布满血丝的眼睛盯着手机,机械地刷着工作群消息,灵魂却还在假期里游荡。

将不准请假视为解决工作堆积的法宝,本质上是管理者对自身失职的狡辩。若一个团队因一人请假就陷入瘫痪,只能说明分工机制早已漏洞百出——为什么没有备份人员?为什么假期前不提前分配任务?更讽刺的是,许多领导自己享受着长假后“缓一缓再上班”的特权,却对普通员工的请假需求如临大敌。这种“双标”背后,是权力对效率的误读:把员工当作随时待命的工具,而非需要缓冲和尊重的活生生的人。

更荒诞的是,这种规定往往伴随着一套冠冕堂皇的说辞:“公司离了谁都能转,但你要对自己的岗位负责!”翻译成人话就是:“离了你公司当然能转,但你必须转得比公司更快。”于是,打工人不得不修炼出一身影分身术:发着烧也要写方案,家里漏水也要开电话会,甚至亲人住院也要边陪护边回邮件。仿佛请一天假就成了十恶不赦的职场逃兵,却没人敢问一句:“如果公司真的离了谁都能转,为什么偏偏不敢让一个人停下来喘口气?

这种管理的讽刺性在于,它总爱把“竞争文化”、“拼搏精神”、“奋斗者”挂在嘴边,实际干的却是“杀鸡取卵”的勾当。就像逼着马拉松选手用百米冲刺的速度跑完全程,还美其名曰激发潜能。结果呢?员工在高压下透支健康,管理者在收割着员工的产出。最令人啼笑皆非的是,当员工因长期疲惫而效率低下时,领导们又会搬出另一套说教:“要学会时间管理!”“要提高执行力!”仿佛只要打工人修炼成时间管理大师,就能在24小时里挤出48小时的产能。但他们永远不愿承认,真正的效率杀手,正是那些拍脑袋想出的反人性制度。毕竟,让员工在身心俱疲的状态下假装忙碌,可比优化管理流程、合理分配任务容易多了。

要打破这种恶性循环,企业必须从“堵”转向“疏”。允许远程办公、设立“缓冲日”让员工逐步进入状态,远比强制出勤更明智。同时,优化请假制度、建立AB岗互备机制、提前规划假期任务,才是根治工作堆积的正道。而管理者更需要一场思维革命:从挥舞权力的监工蜕变为服务团队的设计师,承认请假危机本质是管理失职的预警。

说到底,“周一不准请假”不过是一面照妖镜,照出了某些管理者掩耳盗铃式的懒惰:他们宁可花十年时间用制度逼员工表演勤奋,也不愿花十天时间梳理工作流程;宁可把员工逼到离职再高价招聘新人,也不愿反思如何让现有人才可持续地创造价值。这种管理的黑色幽默在于,它总在追求短期的全员到岗,却亲手埋下了长期的全员离心。

真正的管理高手,懂得用机制激发人性而非对抗人性。当管理者把员工当作人,员工才会把工作当作事业;若始终将员工视为随时可替换的零件,那么零件的报复,从低效到流失再到口碑崩塌,终将成为管理者最昂贵的代价。或许有一天,当某个坚持“周一不准请假”的团队因人才流失而倒闭时,它的管理者依然不会明白:真正击垮团队的从来不是员工的请假单,而是那颗拒绝与时俱进的脑袋。

每天都有紧急任务:到底是公司着火,还是管理者的脑子着火?

职场办公室里最魔幻的谎言,莫过于领导拍着桌子喊出的那句“这个任务非常紧急!今天必须完成!”——更魔幻的是,这句话昨天刚听过,前天刚听过,甚至上个月的同一天也一字不差地出现过。当紧急成了工作常态,当突击成了企业文化,打工人的时间被切割成满地碎渣,低头捡芝麻时,一抬头却发现一堆西瓜早就烂在了地里。

这些紧急任务往往披着金光闪闪的外衣:“客户明天就要!”“老板亲自盯的!”“关系到公司战略!”但掀开底牌一看,不过是上周就该规划的会议纪要、某个领导一时兴起的创意,或是其他部门拖延甩来的烂摊子。一位员工曾自嘲:“我们公司最大的战略,就是没有战略,所以每天都是战略级救火。”更荒诞的是,当员工连续三天熬夜完成紧急项目或者写完某份ppt之后,才发现客户和领导根本没空看方案——所谓十万火急,不过是管理者掩饰混乱的烟雾弹。

这些永无止境的紧急任务,像极了职场版的《土拨鼠之日》——每天重复着相同的慌乱,却永远找不到问题的出口。早晨刚打开电脑,工作消息便如丧尸围城般涌来:“速拉群!立刻同步进展!”、“速度去办公室现场开会!”、“下班前必须给到!”领导们仿佛集体得了紧迫感饥渴症,非要把每件小事都贴上特急标签,才能确认自己的权威还在运转。而员工则成了人肉陀螺,抽一鞭子转一圈,停下来反倒成了罪过。

这种突击文化最狠毒的副作用,是让职场人逐渐退化成只会条件反射的机器人。上午写方案,下午改PPT,中途插进来三个电话会,晚上十点收到微信:“明天汇报框架要全部重做!”——当大脑被迫在10个任务间高频切换,人只会变得越来越擅长复制粘贴,却彻底丧失深度思考的能力。频繁切换任务会导致效率暴跌和错误率激增。但管理者们似乎坚信,只要把员工逼到极限,他们就能学会分身术。

更隐秘的伤害在于,这种碎片化的工作模式正在系统性消灭专业主义。医生被行政报表挤占问诊时间,工程师被日报周报打断代码思路,教师被每节课的上下课打卡签到消耗备课精力——当所有行业都在向即时响应看齐,所谓的工匠精神便成了挂在年终总结里的笑话。就像建筑工人被要求五分钟砌一块砖,同时还要接电话、回邮件、填考勤,最后却要接受“为什么造不出金字塔”的灵魂拷问。

更讽刺的是,当员工被琐碎任务淹没时,领导却在会议上痛心疾首:“你们为什么没有长远眼光?为什么不主动创新?”仿佛忘记了自己才是那个天天往团队里扔手榴弹的人。某些员工透露,他曾在季度总结中写道“本月完成35个紧急需求”,却被领导批注:“缺乏重点,思考深度不足。”这像极了逼着厨师五分钟炒一盘菜,还嫌他没有雕出萝卜花。

而那些制造混乱的始作俑者,往往拥有最理直气壮的借口:“市场变化快啊!”“客户需求多啊!”但是口头沟通内容中,前三条赫然写着:

  1. 计划?计划赶不上变化,没必要做计划。
  2. 复盘?上次的教训下次一定改,没时间复盘。
  3. 招人?反正现有的人加班也能干,甚至让他们春节不回家都是可行的,所以不必招人。

而那些制定规则的人,往往身处突击风暴的安全区。高管们喝着养生茶讨论员工幸福感,中层拿着管理权杖表演奋斗者精神,只有基层在工作消息的紧急轰炸中逐渐麻木。在长期熬夜的氛围中,HR的年度报告却写着:“员工的主动性待提升,建议增加执行力培训。”

这场荒唐游戏的最大代价,是企业亲手阉割了自己的未来。当所有人都在疲于应付虚假的紧急,就没人敢停下来思考真正重要的问题:为什么总是突击?为什么永远缺人?为什么客户总在最后一刻反悔?当团队丧失战略耐心,企业便陷入“越忙越乱,越乱越忙”的死循环。就像一位创业者反思:“我们曾经用三个月紧急开发了一款没人要的产品,却错过了真正该做的市场调研。”

要打破困局,或许该从戳破紧急的谎言开始。把优先级交给数据而非领导的心情,用缓冲期替代最后期限,允许员工每周有半天免打扰时间专注核心任务。毕竟,当员工不再被当成人形U盘随时插拔,他们或许真能腾出手来,修好那把早就该补的房顶破洞。破局之道或许藏在反紧急的勇气里。当企业愿意给紧急任务设置门槛,真正的优先级才会浮出水面。毕竟,如果所有事情都重要,那就意味着什么都不重要。

立刻马上成为职场办公室中的最高准则,我们便亲手把办公室变成了思想的废墟——这里堆满了即时回复的瓦砾,却再也长不出未来的种子。

职场人士的自学方法

每天固定一个小时,是成年人自学最可行的节奏。
对大多数职场人来说,整块的学习时间极其稀缺,但这不代表无法系统学习。关键在于设定一个固定的“学习黄金时段”——不论是早起的一小时、晚上睡前的一小时,或是午休中的半小时+晚间半小时。固定时间不仅有助于养成习惯,也能降低找时间带来的心理阻力。一小时虽短,但坚持三个月,就足以掌握一门技能的入门。如果一个小时的整块时间比较难以寻找,可以尝试使用半小时工作法,寻找半个小时的专注时间即可。但是,如果只是为了学习英语而去学习英语就意义不大了,可以找一些自己喜欢的方向或者内容来进行学习。

学习的同时做笔记,是构建长期记忆的关键步骤。
很多人自学时只是“看完了”“听懂了”,却无法真正记住或应用。解决这个问题的有效方式,是在学习时同步整理笔记。笔记不是照抄内容,而是提炼结构、记录疑问、用自己的语言解释概念。建议使用数字工具如云笔记、云盘、纸质笔记本等,将笔记打标签、分类、更新,逐渐形成属于自己的知识体系。

遵循“输入—总结—输出”的三步循环,才能真正学会。
成人自学最常见的问题不是缺资源,而是学了就忘。最有效的学习流程是:先输入(如阅读、听课、看视频),再总结(归纳要点、整理框架、做小结),最后输出(写一篇心得总结、录一段讲解视频、讲给他人听)。只有通过输出,我们才能暴露知识漏洞,加深理解,真正将信息转化为能力。而且输出有持续的正反馈,特别适合成年人的工作习惯,有正反馈才会有源源不断的学习动力。

不追求完美,而追求完成+复盘,才能持续推进。
很多职场人在自学时容易陷入完美主义:这套课程不够系统、笔记写得不好、输出不够精致……结果常常是半途而废。事实上,学习的关键在于完成和反复,不是第一次就做到极致,而是每次完成后都比上一次理解更深一点。通过周期性复盘——比如每周日晚上花20分钟回顾一周的学习,就能不断迭代、加固成果。放弃完美,直接开始才是战胜拖延症的法宝。持续不断地总结,有助于将零碎的知识进行系统化的整理,塑造出自己的知识体系。

将学习融入生活,而非与生活对抗,是长久坚持的基础。
成年人有太多不可控变量:突发工作、家庭琐事、情绪波动。要让自学成为长期行为,就不能让它和生活抢资源,而要主动融入日常。例如,把学习内容与工作任务关联、在健身时听书、与朋友组建学习小组。这些学习与生活的微调可以显著提升学习的可持续性,也让学习本身变得更轻松、有趣。学习只是生活中的一部分,不要将学习本身从生活中完全剥离开,将两者结合到一起才能够促使自己的进步。

一个月,胜过一年:当我跳进大模型的真正洪流

最近整理了一下自己的技术文章撰写记录,忽然发现一个有点惊讶的事实:在过去的 2025 年 4 月份,我已经输出了五六篇与 AI 大模型相关的技术内容,覆盖了 RAG、Ollama、Milvus 等方法和开源框架。而再往前看一年多的时间里,我也不过断断续续写了两三篇技术文章。

是我变了吗?也许个人确实有一点变化。但更关键的,是我所处的技术氛围变了。

以前的节奏更偏稳定,任务导向混乱,创新探索非常稀缺,每个团队的能力形成了一个又一个的孤岛。很多 AI 新技术的讨论停留在“看看”、“以后试试”,大家对大模型也多是远观式的接触,能够用聊天框进行沟通和写代码就已经算是使用 AI 了,跟不懂技术的人使用 AI 毫无区别;要是能够调个开源的接口,能问问 ChatGPT,就算是了解了 AI。即便 AI 大模型有新技术冒头,在原有的工作氛围下,也很难真正在团队中找到一个可以深聊、共创的空间。过去的技术氛围是偏稳的,项目也多是用熟不求新,甚至使用了一些错误的开源框架在做事情。虽然也挂着“AI”、“智能化”这样的口号,但实际落地的内容往往止步于一些传统模型调用,或者是基于既有框架的功能叠加,创新空间不大。一旦想研究点新东西,经常会被劝“先把业务做完”、“先进行项目交付”等。

在以前的环境中,大家的技术分享也流于形式,更多是一种 KPI 式的应付,毕竟在工作时间内技术专家也不允许组织和进行技术分享,只能在晚上加班和周末时间来进行义务分享。长期以往,每个人在进行分享的时候只是为了完成工作任务,而不是出于真正的热情与沉淀。大家的精力毕竟也是有限的,没有人有心情一直在额外的时间内完成一些 KPI 式的工作任务,而且这些工作任务甚至都不能算作工作量,而且在某些管理者眼里面 AI 也只能够作为锦上添花,算不上团队的核心交付。在这种工作氛围中,持续干技术类型的活也是持续让自己减值,而不是升值。

直到最近一个月,我主动进入了一个真正密度极高的技术环境。信息流是动态的、实时的、扎实的。在这个大环境下,不是谁在刻意地展示自己的工作成果,而是每个人都在不停地参与和使用开源模型。开源社区的演化轨迹、最新论文的细节实现、从 API 到落地系统的技术栈差异……几乎每天我都在打开一个新的窗口。很多以前我以为很遥远的东西,现在成了每天要接触、要思考、要尝试的日常工作。

这种状态下,技术文章的输出变得非常自然。我其实并不是为了写点什么,而是为了整理、对齐、验证这些快速涌入的新知识。文章不是炫技,而是思考的副产物。你不写,就理不清;你一理清,就想分享。而这些输出,也反过来构成了进一步深入的基础。在过去的一个月里面,我仿佛被卷入了一股奔腾不息的洪流。这里的节奏紧张但充满活力,大家都在思考如何用大模型赋能业务,而不是等大模型成熟了再说。大模型的使用不再只是 ChatGPT 式的玩具对话,而是真正围绕 Retrieval-Augmented Generation、Agent 调度系统、多模态理解、模型微调与工具调用来展开落地。从基础组件到工程实践,从系统架构到数据治理,每一块都在挑战我对“AI 算法”、“AI 工程化”的已有认知。

这种技术成长的加速感,是在之前的环境中前所未有的,从未体验过的。工作的产出不是靠加班时间长来换的,而是靠工作氛围的沉浸深来推的。当你处在一个前沿、高频、鼓励探索的语境里,成长就像是自动发生的结果。你不再是一个单点地摸索,而是置身在集体智能中被裹挟着向前。身边的同学们的技术素养都非常高,而且愿意分享。无论是技术文章、开源代码、实战经验,都有很多同事在工作时间持续分享,很多我曾经觉得以后再看也来得及的概念,现在每天都在眼前被应用、被验证、被推翻再重构。

我开始意识到:技术成长从来不是孤独的练习,而是被更高水平的集体氛围持续激发的结果。当你周围都是在往前冲的人,你根本没有躺平的理由;当你看到别人把一个抽象的想法快速落地成原型,你自然也想挑战自己;当知识流动不再依赖个人自驱,而是组织天然具备高效的协同机制,你就很容易被带着不断升级。反之,如果你身边的人都是一群每天想着怎么复制粘贴、推卸责任、把别人的成果据为己有的人,那你努力向上的动力也将随之消失。

同时,我也开始更清楚地意识到:一个人对技术的理解,不只是靠代码能力和书本知识,更取决于他每天在接触怎样的问题、怎样的讨论、和怎样的人一起构建。以前会觉得,做技术靠的是自律、自学、自我驱动。现在才明白,自我驱动确实重要,但真正决定你能走多远的,是你所在的技术环境中是否能持续点燃你。就像游泳,自己扑腾当然能前进,但如果你跳进的是一条顺流而下的河,你的推进速度将被彻底改变。

过去一年,我努力地走着;这一个月,我被卷着飞跑。并不是因为我更聪明了,而是我终于明白,选对方向、接对电流,比一个人用力更重要得多。

所以这篇文章,也写给每一个还在犹豫和原地探索的人:当你发现自己进步缓慢,不妨回头看看,是不是该换条河流、换个风口,重新沉入真正涌动的浪潮中。技术,不只是一个人的修行,也是一群人的流动。如果你也在思考是否要换一条跑道,不妨问问自己:你所在的地方,是在带你前进,还是让你维持?有时候,我们真正需要的,不是更努力的自己,而是一个让你愿意更努力的环境。

从小模型到大模型:算法工程师如何高效转型入门大模型技术

近年来,大语言模型如 GPT、LLaMA、Claude、Gemini、DeepSeek 等在自然语言处理任务中展现出前所未有的能力,已经成为技术界与产业界关注的核心。从算法模型到软件产品,从科研论文到应用落地,大模型不仅改变了人们对人工智能的认知,也正在重塑整个技术生态。在任何行业都面临着这场来自于 AI 的挑战,无论是互联网、新能源汽车还是农业,都有着许多实际的场景等待 AI 的接入。对于有机器学习和深度学习基础,甚至在工业界具备小模型实践经验的算法工程师而言,进入大模型的世界,不仅是一场技术能力的升级,更是一场思维范式的转变,不及时转型大模型的话,可能未来在市场中的就业前景会比较差。

有的人对大模型的理解还停留在“模型更大、训练更贵”这类直观感受上,实际上,大模型的发展远不止于此。它的核心在于能力泛化与范式重塑:过去我们依赖于大量小模型分别完成各类任务,如文本分类、情感分析、命名实体识别等,而如今一个统一的大模型通过预训练加提示学习,便可以泛化执行多个任务。而且使用不同的模型大小,往往会有不同的效果。如果是应对线上耗时极为敏感的业务,选择0.5B这类模型反而可能是较好选择;如果是需要接近人类的问答业务,那自然要选择算法效果最好的模型。这种变化不仅体现在架构设计上,也深刻影响着数据处理、系统部署与业务集成的方式。理解这一点,有助于我们更清晰地把握大模型带来的真正价值,以及入门所需要的新思维方式。

大模型的技术入门可以从实践出发。对于刚开始接触这一领域的工程师,最直接的方式是先从大模型的 API 使用开始,熟悉其基本能力。通过调用 OpenAI 或者国内主流模型服务,可以快速体验大模型在文本生成、问答、摘要、翻译等方面的表现。除此之外,还可以使用 Ollama 进行本地模型的部署和使用,如果本地电脑的配置较好,甚至还可以使用效果较好的模型。更进一步,程序员还可以尝试通过提示词工程(Prompt Engineering)技巧调整模型输出,比如使用 Zero-shot、One-shot、Few-shot、Role Prompting 或思维链(Chain-of-Thought)来提升任务完成效果。在这个过程中,如果有个人或者本地的知识库,则可以使用 LangChainLlamaIndex 等框架可以帮助更高效地构建 LLM 驱动的应用,如智能问答系统、RAG 检索增强模型等。

比如你可以从一个简单的任务开始:用开源模型或者 Ollama 来搭建一个本地的问答机器人。此时,你将面临模型选择(各种大小从0.5B到230B的模型)、环境(Windows、Mac、Linux)的模型部署、RAG 检索增强、对话记忆管理、响应优化等多个模块,每一步都能对应学习一类技术。完成一个完整的端到端的 Demo,所收获的理解深度远比看十篇教程来得扎实。随着项目难度的提升,你可以逐步加入更多工程化的能力,如服务的日志监控、模型热更新、服务的负载均衡、API 的接口设计等,将本地的问答机器人从做出来变成做得稳。

当作为程序员的你对模型应用有一定了解之后,则建议逐步深入底层原理与机制。Transformer 架构是理解大模型的基石,掌握 Attention 机制如何运作,有助于理解模型为何具备强大的上下文理解能力。进一步,可以学习大模型的训练流程,包括预训练、指令微调(Instruction Tuning)、RLHF(基于人类反馈的强化学习)等,这些流程构成了大模型从“会说话”到“懂你在说什么”的核心路径。此外,近年来轻量化微调技术如 LoRA、QLoRA、P-Tuning 等方法也非常值得了解,它们极大降低了模型微调的成本,为个人开发者和中小企业提供了更多地使用大模型的可能性。

在掌握理论和微调技术的基础上,工业部署能力将成为你的核心竞争力之一。大模型的推理开销巨大,因此推理优化至关重要。学习量化、剪枝等优化手段,可以帮助你在不牺牲太多效果的前提下,大幅提升推理效率。同时,vLLMTritonDeepSpeed 等微调和部署工具,能帮助你将大模型高效运行于生产环境。当前已经有不少开源模型,如 DeepSeek、Qwen、Baichuan、Mistral、LAMMA 等,都提供了成熟的推理和部署方案,完全可以在本地尝试构建属于你自己的大模型应用。

随着模型能力的增强,仅仅调用模型已经不能满足复杂的业务场景需求。智能体(Agent)架构成为大模型进一步落地的关键。从调用外部工具、维护任务记忆,到执行多轮推理和状态管理,Agent 模型已经逐步走向工程实用层面。学习 AutoGPTCrewAILangGraph 等框架,将帮助你构建具备任务自主性和长期记忆的复杂智能系统。如果你对前沿感兴趣,也可以探索多模态大模型、长文本处理、Agent 协同等领域,这些都代表着下一阶段技术演进的方向。

对于有小模型研发经验的工程师来说,大模型并不是从零开始的挑战。你原有的数据处理能力、模型评估习惯、工程部署经验,依然在大模型系统中非常有价值。唯一需要转变的,是工程思维的广度和系统设计的复杂度。在大模型时代,更多的是系统级 AI 架构思维,而不仅是模型本身的精调。与此同时,大模型也能反过来助力你的日常开发,从代码生成到接口设计、测试覆盖,模型本身可以成为你高效工作的伙伴。

在这样一个飞速演化的领域中,持续学习显得尤为重要。建议建立一套“输入—实践—输出”的闭环机制:通过订阅高质量技术博客、关注 arXiv 的热门论文和 GitHub 热门项目持续输入,结合业务的实战来做一个实用的小项目或复现案例进行实践,再将实践成果通过博客、文档或开源项目进行输出,这样的闭环能帮助你不断沉淀、持续提升。同时,当前大模型领域更新极快,如果只靠碎片学习(刷一两篇公众号、调试一两个脚本)是很难形成系统认知的。没有实践,就没有深度;没有输出,就没有沉淀。应当通过读论文、复现项目、搭建 Demo、写总结、录视频等方式,形成正向成长闭环,这样才能在快速变动的环境中稳定前进。

从小模型到大模型,是一次从点状技术向整体系统能力的跃迁。虽然学习曲线稍微有点陡峭,但对于有算法经验的你来说,这更是一次站在更高起点的技术升级机会。在 AI 的这次浪潮中,可以选择一个你感兴趣的方向,从实战切入并不断迭代,很快你就会在这场 AI 变革浪潮中找到属于自己的位置。

周末团建:你的休息我来安排

周末到了,别人家的员工早上九点还在被窝里打滚,我们在周末早上七点就已经在地铁口、公交车站或者各个地方准备人挤人,即将“奔赴山林、回归自然”。你以为我们要去出差或者旅行?错了!我们是在参加每个季度、甚至每个月的强制团建计划——据说团建能提升团队的凝聚力,实际上凝的可能是膝盖积液。如果你要问我们为什么那么早出门呢?是因为某些景区早上八点之前进门可以门票,毕竟团建经费有限。

每个季度的周末团建都是一场充满集体主义的活动:团建没有包车?自行解决,体现每个员工的自立自强,住的远的同事为了完成任务甚至自费打车前往;不包饭?没事,还有瓜子、辣条和各种小零食,嚼着也算团魂升华;没有经费?没事,可以去爬山、逛公园、去博物馆,甚至还可以去马路上散步。不准请假?所有同事要有纪律观念,少一个人队形就散了。这样高度考验个人素质的团建实在是有温度的团队文化的极致体现。

每当进入团建现场时,所有员工都会感受到一种莫名的使命感。员工们不但要参与,还要展示出一副积极向上的笑容。爬山、教练式拉练、体育运动,公园快走打卡,每一个环节都安排得像军训,又硬说是放松,毕竟没有在处理工作上的事情。走一步、停一下,完美模拟了一次职场生活。最精彩的是,有的同事背着相机拍照留影,仿佛这是一次自愿报名的欢乐春游,其实大家笑得都比项目PPT里的KPI还僵硬。

而每当我们快进行完团建活动的时候,团建的意义终于显现出来:身体疲惫、腿脚酸痛、心力交瘁,但仍要面带微笑,假装兴奋地等待下一个环节——合影。谁能想到,这原本是公司为我们精心安排的美好周末?能不能告诉员工,这种让员工每个季度至少付出一个周末的时候参加活动的行为,是怎么拉近彼此的心灵距离的?

每次季度的周末团建都像一场行为艺术:表面其乐融融,实则疲惫不堪;说是自愿参与,实际不来就特别关注。这项活动的重心并不在于团队精神,而是如何在员工的痛苦中找寻意义,并坚信这是公司关爱的体现——要想让员工免费加班可以直说在空调房也可以干活没必要每次都搞周末团建

更可怕的是,团建结束后,大家还是得一一领取团建任务。团建任务包括但不限于制作团建的ppt、短视频、文章稿件等内容。你以为你参加了个放松活动就已经结束了,结果它变成了一个又一个的工作任务,不同的员工承担不同的模块。在周末团建的时候,有的同事为了不耽误工作,连电脑都带上了,随时准备接到项目上的电话,开始真正的义务工作。

建议下次团建不如直接改名叫精神内耗研修班,主题是《如何在周末身心俱疲中保持微笑》。每次团建之后,大家都可以准备个团建纪实,记录下每个被剥夺的周末,看看自己究竟在周末参与了多少的公司活动。

如果说团建是一种仪式感,那我希望这种仪式可以走心一点,而不是走脚底板。公司若真想促进团队交流,不如把眼光放到日常的工作管理上——比如少点内耗、少点无意义加班、多点信任、多点培训、少点形式主义。比起爬山,我们更愿意看到流程的优化;比起拍照留念,我们更需要有话语权的表达。说到底,员工不是通过周末出汗来增加归属感的,而是通过被理解、被尊重、被支持来找到价值感。如果连最基本的周末休息权都得不到保障,那再多的企业文化也只是包装纸,包不住员工内心的疲惫与失望。

故事含虚构创作,如有雷同纯属巧合

别被困在知识的孤岛里

“别学了,实战就是最好的老师。”“别看那个培训链接了,上班时间该干活就干活。”如果你在职场中频繁听到这样的声音,请警惕:你可能正被困在一个“知识垄断者”的团队里。

表面上,这样的领导是在强调效率与实战经验,实则背后潜藏着领导对权力流失的深层焦虑。他们最怕的不是你工作出错,而是你成长得太快。他们深知:一旦员工拥有了独立学习和思考的能力,那种“唯命是从”的管理模式就不再稳固,更有可能出现员工批量跳槽的情况。

于是,他们开始设下无形的“学习禁令”。比如:不允许员工上班时间参加行业培训、阅读学习资料,哪怕你只是利用碎片时间浏览一个五分钟的微课链接,都会被冠以“不务正业”的帽子。表面理由往往是“学习影响工作效率”,但真正的逻辑是:只允许你从他身上学,确保你只能在他的经验体系中循环打转。

这种控制,最终会将整个团队变成一个“信息孤岛”:不接触外部知识,不吸纳新鲜理念,不培养跨界能力。更可怕的是,员工在这样的环境中逐渐被训练得不再主动求知,把“干好当前这点事”视为全部,不知不觉被塑造成“高执行、低判断”的职业耗材。而那些懂得学习、不断升级思维的人才,自然会选择离开。剩下的团队,只剩下一群被剪掉翅膀的人。

类比闭区间套原理,技术学习被限定为“只能向领导请教”,这仿佛是一种荒诞的“知识闭区间套”——每一代员工的认知范围,被严格限制在上一代领导划定的区间内,既不能扩展,也不容突破。领导的知识是[a1,b1][a1,b1],员工的学习只能局限在[a2,b2]⊆[a1,b1][a2,b2]⊆[a1,b1],再下一代则是[a3,b3]⊆[a2,b2][a3,b3]⊆[a2,b2],代代缩小,层层收紧,最终收敛于一个点:听话。不再有新知输入,不再有独立判断,只剩下“经验复读”。他们用制度封死了上下限,让知识从传承走向塌缩,把组织变成一间封闭的“思想套娃”。

别再被那句“实战就是最好的学习”洗脑。真正有远见的领导,应该是推动团队终身学习的人,是让团队成员站在更高处思考的人,而不是把知识当成私有财产,死死攥在手中当权杖用。知识垄断,或许能维持一时的管理权威,但绝不会塑造一个真正有竞争力的团队。别让你的未来,被困在一个惧怕你变聪明的人手里。

当你意识到领导在有意压制你的学习、团队变成“信息孤岛”、任何成长尝试都被视为“越界”时,不必惊慌,更不能躺平。即使身处一个对知识极度吝啬的环境,你依然可以构建自己的突破通道。

一、打造隐性学习系统,悄悄成长不声张
当上班时间学习被视为“不务正业”,你需要为自己建立一套“隐性学习系统”。通勤路上听播客、午休时看一个五分钟微课、晚饭后读几页专业电子书……碎片时间被很多人浪费掉,但对你来说,它是进化的窗口。安静积累,不用宣扬,成长自然发生。

二、主动拓展平行网络,突破公司内的信息天花板
当一个组织封闭了知识流通渠道,就意味着你只能“向上讨知识”。但外部世界广阔,你可以通过加入专业交流群、参加行业沙龙、订阅优质内容平台,建立自己的“外脑网络”。别等公司喂你认知,你要自己长出触角。

三、构建个人知识库,长期积累变现力
学习的效果不止于听懂,更在于整理和输出。你可以利用工具等,将日常学到的知识分类、拆解、笔记,形成自己的“认知地图”。时间久了,你就会发现,很多困扰你的问题,其实早有答案藏在你的知识库里。

四、明确长期目标,倒推当前行动路径
不被眼前事务淹没的前提,是你清楚自己想去哪里。你可以设定1年或3年内的目标(如成为内容主理人、技术管理岗、运营策略负责人),再倒推需要的能力、经验与影响力。当你从未来出发看今天,所有琐碎就有了意义。

五、培养提问型思维,从执行者走向思考者
成长的关键在于:不要只接收任务,更要理解任务背后的逻辑。学会在工作中多问“为什么这样做?”、“还有没有其他方案?”、“这个目标对业务的核心价值是什么?”你会发现,提问本身就是认知升级的开始,也是在训练你的独立判断力。

六、为离开做准备,而不是等机会来临
最后的底牌是“选择权”。你应该定期整理简历、更新作品集,与猎头或业内朋友保持交流,掌握市场行情。即使暂时不跳槽,也要让自己拥有随时能走的能力。很多时候,成长不是为了留下,而是为了不被困住。

每一条建议,都是你走出“被动执行—知识受限—长期边缘化”循环的阶梯。你不需要一次做完所有,但从今天开始,选一件开始做。即使没人支持你学习,你也能靠自己,活出职场上的“信息自由”。

LlamaIndex:如何在大模型领域构建自己的知识库

LlamaIndex入门

LlamaIndex简介

LlamaIndex(原名 GPT Index)是一个开源的 Python 库,其擅长简化大规模文本数据的索引、存储和查询操作。它将语言模型与文本数据的高效索引结合起来,使得开发者可以轻松地为复杂的文本信息检索和问答任务构建解决方案。通过构建倒排索引或向量索引,LlamaIndex 可以处理大量的文档,并为每个查询提供上下文感知的答案,显著提高了大规模数据的查询效率和准确性。它特别适用于法律、医学、科研、公司内部知识库等领域中需要处理和分析大量文本数据的场景。

LlamaIndex 不仅支持多种数据源,如文本文件、网页和数据库,还能够与先进的向量数据库(如 Milvus或者Pinecone)进行集成,进一步提升查询速度和准确度。通过与大语言模型(如 Ollama、DeepSeek等开源模型或者GPT的API等)结合使用,LlamaIndex能够在复杂的问答系统、自动摘要、个性化推荐等应用中提供强大的文本理解和推理能力。无论是建立企业内部的知识库,还是创建智能客服系统,LlamaIndex 都能有效地处理大量文档,并提供实时、精准的查询结果。

LlamaIndex的安装

LlamaIndex可以通过pip进行安装,其命令是

pip install llama-index

还可以通过源代码进行安装,首先用git clone 代码

git clone https://github.com/jerryjliu/llama_index.git

然后执行:pip install -e . 或者 pip install -r requirements.txt 就可以安装成功。

LlamaIndex的使用

在docs这个文件夹中放入team_structure.txt这个文件,该文件的内容如下所示:

B公司人力资源部(HR)负责公司的招聘、培训、员工关系管理、绩效考核等职能。人力资源部的组织架构分为三个主要小组:招聘组、培训组和员工关系组。
招聘组负责公司各类职位的招聘,筛选候选人,组织面试并安排入职培训。招聘组目前有5名成员,主要负责技术岗位和管理岗位的招聘。
培训组负责公司内部员工的职业发展培训,组织新员工培训、领导力培训和技能提升课程。培训组目前有3名成员,分别负责技术培训、软技能培训和高管培训。
员工关系组负责员工关系的维护,解决员工与公司之间的各类问题,组织公司文化活动,提升员工满意度。员工关系组目前有4名成员。
人力资源部总监为李晓红,负责整体管理,向公司CEO汇报。每月与各小组负责人召开一次会议,评估部门目标和完成情况。
招聘组负责所有岗位的招聘,包括技术岗位、市场岗位、财务岗位等。技术岗位的招聘由王刚负责,市场岗位招聘由张婷负责,财务岗位招聘由刘峰负责。
培训组目前在进行年度员工培训计划,2025年的重点是提升员工的领导力和跨部门协作能力。
员工关系组正在策划一项关于员工福利的提升项目,预计将在2025年初开始实施。

于是,一个简单的搜索功能可以用以下代码来实现,只输出Top2相似的结果。

代码说明:

  1. 文档加载:代码使用 SimpleDirectoryReader 从指定的文件夹(例如 docs)中加载文本文件。这些文本文件可以是任何格式的文本文件(如 .txt)。SimpleDirectoryReader 会自动扫描指定文件夹中的所有文件并加载其内容。
  2. 创建索引:使用 VectorStoreIndex.from_documents(documents) 将加载的文档转化为向量索引。我们还在构造索引时应用了 SentenceSplitter,用于将文档拆分成小块以便更高效的处理。
  3. 查询引擎通过 index.as_query_engine() 创建一个查询引擎,可以在该引擎上执行查询并返回最相关的文档或文本块。
  4. 查询执行:代码通过 query_engine.query(query) 执行用户的查询,并返回与查询最相关的结果。在这个例子中,查询的是 “B公司人力资源部的组织架构是怎样的?”
  5. 输出:最后,代码会打印检索结果。
import logging
import sys
from llama_index.core import PromptTemplate, Settings, SimpleDirectoryReader, VectorStoreIndex
from llama_index.core.node_parser import SentenceSplitter
from llama_index.embeddings.huggingface import HuggingFaceEmbedding

# Step 1 设置日志
# 设置日志记录的最小级别为 WARNING,避免输出 DEBUG 和 INFO 信息
logging.basicConfig(stream=sys.stdout, level=logging.WARNING)  # 只输出 WARNING 及以上级别的日志

# 如果你只想屏蔽来自 llama_index 的日志,也可以使用下面的代码来禁用它
logging.getLogger("llama_index").setLevel(logging.WARNING)  # 设置 llama_index 的日志级别为 WARNING

# Step 2 配置 LlamaIndex 使用本地的嵌入模型(可选)
Settings.llm = None
Settings.embed_model = HuggingFaceEmbedding(
    model_name="/Users/avilazhang/PycharmProjects/models/BAAI/bge-large-zh-v1.5"  # 使用 BGE 中文嵌入模型
)

# Step 3 定义文档路径,假设文档存储在名为 "docs" 的文件夹中
docs_directory = 'docs'

# Step 4 读取文档并构建索引
# 使用 SimpleDirectoryReader 读取文件夹中的所有文本文件
documents = SimpleDirectoryReader(docs_directory).load_data()  # 读取 docs 文件夹中的所有 txt 文件
index = VectorStoreIndex.from_documents(documents, transformations=[SentenceSplitter(chunk_size=256)])

# Step 5 存储向量索引
index.storage_context.persist(persist_dir='doc_emb')  # 保存向量索引到本地目录

# Step 6 构建查询引擎,搜索TopK。
query_engine = index.as_query_engine(similarity_top_k=2)

# Step 7 模拟用户查询并执行检索
query = "B公司招聘组负责什么内容?"
response = query_engine.query(query)

# Step 8 打印检索结果
print("检索结果:", response)

检索的结果如下图所示,只有两个文档信息,因为TopK的值等于2。

除此之外,LlamaIndex还支持在现有索引的基础上读取索引,并且新增索引。

RAG

RAG的整体流程

一个标准的RAG整体流程如下所示,可以从数据库、文档、API中获取数据并形成Index,然后query提问的时候可以通过Index获得相应的数据(relevant data),再把prompt、query和relevant data输入大模型,即可得到优化后的回答(response)。

所以,RAG的主要阶段就包括载入、索引、存储、提问、评估。

Embedding模型

llama_index同样可以存储index,并且llama_index可以读取数据库、pdf、txt等类型文档。可以使用嵌入模型来做数据的嵌入工作,并且计算其数据之间的相似度。

from sentence_transformers import SentenceTransformer

# 模型的本地地址,可以使用以下命令来进行下载到本地的某个地址
# modelscope download --model BAAI/bge-large-zh-v1.5 --local_dir /Users/avilazhang/PycharmProjects/models/BAAI/bge-large-zh-v1.5
# 嵌入模型
embedding_models = '/Users/avilazhang/PycharmProjects/models/BAAI/bge-large-zh-v1.5'

# 方法一:
sentences_1 = ["样例数据-1", "样例数据-2"]
sentences_2 = ["样例数据-3", "样例数据-4"]
model = SentenceTransformer(embedding_models)
embeddings_1 = model.encode(sentences_1, normalize_embeddings=True)
embeddings_2 = model.encode(sentences_2, normalize_embeddings=True)
similarity = embeddings_1 @ embeddings_2.T
print(similarity)
# [[0.8553333  0.8520634 ]
#  [0.87456274 0.8557937 ]]
 
 
# 方法二:
queries = ['query_1', 'query_2']
passages = ["样例文档-1", "样例文档-2"]
instruction = "为这个句子生成表示以用于检索相关文章:"

model = SentenceTransformer(embedding_models)
q_embeddings = model.encode([instruction+q for q in queries], normalize_embeddings=True)
p_embeddings = model.encode(passages, normalize_embeddings=True)
scores = q_embeddings @ p_embeddings.T
print(scores)
# [[0.3372506  0.20507795]
#  [0.22591084 0.38495794]]

LlamaIndex与Ollama

用LlamaIndex和Ollama可以构建模型的RAG的知识库并输出:

import logging
import sys
from llama_index.core import PromptTemplate, Settings, SimpleDirectoryReader, VectorStoreIndex
from llama_index.core.node_parser import SentenceSplitter
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
import ollama
from llama_index.core import Document

# Step 1️⃣ 设置日志
# 设置日志记录的最小级别为 WARNING,避免输出 DEBUG 和 INFO 信息
logging.basicConfig(stream=sys.stdout, level=logging.WARNING)  # 只输出 WARNING 及以上级别的日志

# 如果你只想屏蔽来自 llama_index 的日志,也可以使用下面的代码来禁用它
logging.getLogger("llama_index").setLevel(logging.WARNING)  # 设置 llama_index 的日志级别为 WARNING


# Step 2️⃣ 定义 system prompt
SYSTEM_PROMPT = """You are a helpful AI assistant."""
query_wrapper_prompt = PromptTemplate(
    "[INST]<<SYS>>\n" + SYSTEM_PROMPT + "<</SYS>>\n\n{query_str}[/INST] "
)

# Step 4️⃣ 配置 LlamaIndex 使用 BAAI/bge-base-zh-v1.5 作为嵌入模型
Settings.llm = None
Settings.embed_model = HuggingFaceEmbedding(
    model_name="/Users/avilazhang/PycharmProjects/models/BAAI/bge-large-zh-v1.5"  # 使用 BGE 中文嵌入模型
)

# Step 5️⃣ 定义 B公司人力资源部的组织架构及业务分工文档
docs = [
    "B公司人力资源部(HR)负责公司的招聘、培训、员工关系管理、绩效考核等职能。人力资源部的组织架构分为三个主要小组:招聘组、培训组和员工关系组。",
    "招聘组负责公司各类职位的招聘,筛选候选人,组织面试并安排入职培训。招聘组目前有5名成员,主要负责技术岗位和管理岗位的招聘。",
    "培训组负责公司内部员工的职业发展培训,组织新员工培训、领导力培训和技能提升课程。培训组目前有3名成员,分别负责技术培训、软技能培训和高管培训。",
    "员工关系组负责员工关系的维护,解决员工与公司之间的各类问题,组织公司文化活动,提升员工满意度。员工关系组目前有4名成员。",
    "人力资源部总监为李晓红,负责整体管理,向公司CEO汇报。每月与各小组负责人召开一次会议,评估部门目标和完成情况。",
    "招聘组负责所有岗位的招聘,包括技术岗位、市场岗位、财务岗位等。技术岗位的招聘由王刚负责,市场岗位招聘由张婷负责,财务岗位招聘由刘峰负责。",
    "培训组目前在进行年度员工培训计划,2025年的重点是提升员工的领导力和跨部门协作能力。",
    "员工关系组正在策划一项关于员工福利的提升项目,预计将在2025年初开始实施。"
]

# Step 6️⃣ 读取文档并构建索引
documents = [Document(text=doc) for doc in docs]  # 将文档转化为 LlamaIndex 的文档对象
index = VectorStoreIndex.from_documents(documents, transformations=[SentenceSplitter(chunk_size=256)])

# Step 7️⃣ 存储向量索引
index.storage_context.persist(persist_dir='doc_emb')  # 保存向量索引到本地目录

# Step 8️⃣ 构建查询引擎,搜索TopK。
query_engine = index.as_query_engine(similarity_top_k=5)

# Step 9️⃣ 模拟用户查询并执行检索
query = "B公司人力资源部的组织架构是怎样的?"
response = query_engine.query(query)

# Step 10️⃣ 打印检索结果
print("检索结果:", response)

# Step 11️⃣ 构造 Ollama 生成答案的 Prompt
prompt = f"""
请根据以下背景知识回答用户的问题:

【背景知识】
{response}

【问题】
{query}

【回答】
"""

# Step 12️⃣ 使用 Ollama DeepSeek-R1:32b 模型生成答案
print("🤖 正在生成回答...\n")

# 使用 Ollama 调用 DeepSeek-R1:32b 模型进行流式输出
stream = ollama.chat(
    model="deepseek-r1:32b",
    messages=[{"role": "user", "content": prompt}],
    stream=True
)

# Step 13️⃣ 流式输出结果
response_buffer = ""
for chunk in stream:
    delta = chunk.get("message", {}).get("content", "")
    print(delta, end="", flush=True)  # 实时输出
    response_buffer += delta

# Step 14️⃣ # 能流式输出最终生成的答案
print("\n\n生成的答案:", response_buffer)

用多条数据查询之后得到以下结论:

查询回答(来自 RAG + LLM)结论
B公司人力资源部的组织架构是怎样的?B公司的人力资源部负责公司的招聘、培训、员工关系管理以及绩效考核等职能。该部门的组织架构分为三个主要小组:招聘组、培训组和员工关系组。 1. 招聘组: 负责公司各类职位的招聘,包括技术岗位、市场岗位、财务岗位等。 招聘组目前有5名成员,分别由王刚负责技术岗位招聘,张婷负责市场岗位招聘,刘峰负责财务岗位招聘。 2. 培训组: 负责入职培训及其他类型的员工培训,提升员工的技能和工作表现。虽然背景信息中未详细说明该组的具体情况,但可以推断其在培养员工能力方面起着关键作用。 3. 员工关系组: 负责维护员工与公司之间的关系,解决各类问题,组织公司文化活动以提升员工满意度。 该组目前有4名成员,致力于促进积极的职场环境和增强团队凝聚力。 人力资源部的整体管理由总监李晓红负责,她定期召开会议评估部门目标的完成情况,并向公司CEO汇报。这种层级分明、分工明确的组织架构确保了人力资源各项职能的有效执行。 正确
B公司人力资源部2025年有哪些任务? B公司人力资源部在2025年的任务包括: 1. 年度员工培训计划:重点是提升员工的领导力和跨部门协作能力。这是由培训组负责的任务。 2. 员工福利提升项目:员工关系组正在策划并预计将在2025年初开始实施这一项目。 此外,虽然招聘组负责公司各类职位的招聘工作,但并未提到具体的2025年任务目标。人力资源部总监李晓红每月与各小组负责人召开会议,评估部门目标和完成情况,这也是其常规职责的一部分,但未特别指出为2025年的具体任务。 正确 
B公司人力资源部的招聘工作有哪些人在负责?我需要找到他们。 B公司人力资源部的招聘工作由以下人员负责: 1. 王刚 – 负责技术岗位招聘 2. 张婷 – 负责市场岗位招聘 3. 刘峰 – 负责财务岗位招聘  这三位人员分别负责各自领域的招聘工作,如果您需要联系他们,可以按照上述信息进行。正确
什么是生物学?根据提供的背景信息,未提及“生物学”的相关内容。如需了解生物学的定义,请参考可靠的科学资源或教科书。不太好,需要修改Prompt
网络监控是什么?网络监控是指通过各种技术和工具持续监测计算机网络的状态和活动,以便及时发现并解决潜在的安全威胁、性能问题或异常行为。其主要目的是确保网络安全、优化网络性能、预防未经授权的访问,并在出现问题时快速响应。 网络监控通常包括以下方面:1. 流量分析:监控数据流量以检测异常模式或潜在攻击。2. 入侵检测和防御:使用防火墙、入侵检测系统(IDS)等工具防止未经授权的访问。3. 性能管理:优化网络资源分配,确保服务质量和高可用性。4. 日志记录与分析:跟踪网络活动,便于审计和故障排查。 这些措施帮助企业保护敏感数据,维护业务连续性和客户信任。正确
请介绍下数学分析有哪些内容?根据提供的背景信息,数学分析的具体内容并未被提及。背景信息主要涉及公司人力资源部的组织结构和职责,包括招聘组、培训组和员工关系组的工作内容。如果您有关于数学分析的具体问题或需要其他帮助,请提供更多相关信息,我会尽力为您解答。不太好,需要修改Prompt

参考资料

  1. LlamaIndex:https://docs.llamaindex.ai/en/stable/
  2. GitHub链接:https://github.com/run-llama/llama_index
  3. 魔搭社区的嵌入模型:https://www.modelscope.cn/models/BAAI/bge-large-zh-v1.5/summary
  4. LlamaIndex中文文档:LlamaIndex 🦙 0.6.18
  5. Pinecore文档工具:Pinecone Database – Pinecone Docs

Milvus:高性能的向量数据库

Milvus简介

Milvus背景

在人工智能与大模型迅速发展的当下,向量数据库作为支撑语义搜索、图像识别、多模态理解等关键应用的底层基础设施,正扮演着越来越重要的角色。Milvus,作为当前最主流的开源向量数据库之一,专为处理大规模、高维向量的相似性检索而设计,具备高性能、高可扩展性和丰富的索引支持。无论是构建基于文本 embedding 的知识问答系统,还是处理亿级图像的相似性匹配任务,Milvus 都能以其强大的索引能力和灵活的接口,成为 AI 应用中的“记忆引擎”。它的出现,不仅填补了传统数据库在向量检索领域的空白,也为构建下一代智能应用提供了坚实的技术基石。

Milvus特点

Milvus支持的场景包括检索增强生成(RAG)、图像搜索、多模态搜索、混合搜索、GraphRAG等方向。非结构化数据(如文本、图像和音频)格式各异,蕴含丰富的潜在语义,因此分析起来极具挑战性。为了处理这种复杂性,Embeddings被用来将非结构化数据转换成能够捕捉其基本特征的数字向量。然后将这些向量存储在向量数据库中,从而实现快速、可扩展的搜索和分析。在这个背景下,Milvus提供强大的数据建模功能,使用户能够将非结构化或多模式数据组织成结构化的Collections。它支持多种数据类型,适用于不同的属性模型,包括常见的数字和字符类型、各种向量类型、数组、集合和 JSON,为您节省了维护多个数据库系统的精力。

Milvus 提供三种部署模式,涵盖各种数据规模–从 Jupyter Notebooks 中的本地原型到管理数百亿向量的大规模 Kubernetes 集群:

  1. Milvus Lite是一个 Python 库,可以轻松集成到您的应用程序中。作为 Milvus 的轻量级版本,它非常适合在 Jupyter Notebooks 中进行快速原型开发,或在资源有限的边缘设备上运行。对于新人学习而言,可以直接使用Milvus的Lite版本,轻松集成并使用。
  2. Milvus Standalone是单机服务器部署,所有组件都捆绑在一个 Docker 镜像中,方便部署。
  3. Milvus Distributed可部署在Kubernetes集群上,采用云原生架构,专为十亿规模甚至更大的场景而设计。该架构可确保关键组件的冗余。
Milvus的特点详细解释
向量搜索支持亿级向量的ANN(近似最近邻)TopK检索
混合搜索基于多个向量场进行 ANN 搜索。
范围搜索查找查询向量指定半径范围内的向量。
全文搜索基于 BM25 的全文搜索。
重排序(Rerankers)根据附加标准或辅助算法调整搜索结果顺序,完善初始 ANN 搜索结果。
获取根据主键检索数据。
查询使用特定的表达式检索数据。
多模型支持支持不同维度的向量(text/image embedding)
存储引擎支持多种存储后端(如本地磁盘、S3、MinIO)
横向扩展分布式架构,支持大规模扩容
高效搜索算法Milvus支持多种内存和磁盘索引/搜索算法,包括 IVF、HNSW、DiskANN 等
插件生态与Faiss、HNSW、ANN等索引算法对接
访问接口支持RESTful API、SDK(Python/Go/Java/Nodejs)/C#(微软提供)/gRPC API
向量管理支持批量导入、删除、版本管理等操作

Milvus的云原生和高度解耦的系统架构确保了系统可以随着数据的增长而不断扩展。可以借助 Kubernetes 或公共云轻松扩展。此外,Milvus 的各个组件都有很好的解耦,其中最关键的三项任务–搜索、数据插入和索引/压实–被设计为易于并行化的流程,复杂的逻辑被分离出来。这确保了相应的查询节点、数据节点和索引节点可以独立地向上和向下扩展,从而优化了性能和成本效率。

Milvus 高度解耦的系统架构

Milvus与AI的集成路径

Milvus与AI的结合方式主要集中在Embedding(嵌入)、Rerank(重排序)、RAG(检索增强生成)这三个方向上。

  1. Embeddings 模型集成:Embedding 模型将非结构化数据转换为其在高维数据空间中的数字表示,以便您能将其存储在 Milvus 中。目前,PyMilvus(Python SDK)集成了多个嵌入模型,以便您能快速将数据准备成向量嵌入。
  2. Reranker 模型集成:在信息检索和生成式人工智能领域,Reranker 是优化初始搜索结果顺序的重要工具。PyMilvus 也集成了几种 Rerankers 模型,以优化初始搜索返回结果的顺序。
  3. LangChain和其他人工智能工具集成:在 GenAI 时代,LangChain 等工具受到了应用程序开发人员的广泛关注。作为核心组件,Milvus 通常在此类工具中充当向量存储。

Milvus使用

Milvus的安装

开始之前,请确保本地环境中有Python 3.8+可用。安装pymilvus,其中包含 python 客户端库和 Milvus Lite。同时还可以把Milvus的model模型都安装上。

pip install -U pymilvus
pip install "pymilvus[model]"

安装好了之后可以通过pip list看到下面两个package安装成功。

如果有torch安装错误的提示,可以使用命令重新安装

conda install pytorch::pytorch torchvision torchaudio -c pytorch

并且可以使用代码来判断pytorch是否安装正常:

import torch
print(torch.__version__)
# 2.5.1

Milvus的数据库

在 Milvus 中,数据库是组织和管理数据的逻辑单元。为了提高数据安全性并实现多租户,你可以创建多个数据库,为不同的应用程序或租户从逻辑上隔离数据。例如,创建一个数据库用于存储用户 A 的数据,另一个数据库用于存储用户 B 的数据。它支持Python、Go、Java、NodeJS等语言去操作数据库。

可以使用 Milvus RESTful API 或 SDK 列出所有现有数据库并查看其详细信息。同时,还可以管理数据库的属性,包括更改、删除等操作。

Milvus 数据库中,collection 和 schema 是用于组织和管理数据的两个核心概念,主要用于处理和存储高维向量数据。

Collection

在 Milvus 中,collection 是一个数据的集合,可以理解为一个数据库表格的概念,用来存储和管理向量数据及相关的元数据。它的作用是:

  1. 一个 collection 由多个向量数据(如图像、文本等的向量表示)构成;
  2. 每个 collection 可以包含多个字段(例如,ID、向量、标签等)。
  3. 你可以创建、插入、查询、删除和更新集合中的数据。

Collection 是一个二维表,具有固定的列和变化的行。每列代表一个字段,每行代表一个实体。下图显示了一个有 8 列和 6 个实体的 Collection。

通常在创建集合时,需要定义向量的维度(比如 128 维、256 维等)以及其他属性(如数据类型)。例如:

from pymilvus import Collection

# 创建一个名为 "example_collection" 的集合
collection = Collection("example_collection")

Schema

schema 是定义一个 collection 中各个字段的结构和数据类型的描述。它类似于传统数据库中的表结构(如字段名和数据类型)。它的作用是:

  1. schema 确定了 collection 中各个字段的数据类型(例如整数、浮动小数、向量等),以及这些字段是否为可查询的或索引字段。
  2. 对于向量数据,schema 还定义了向量字段的维度和索引方式。向量字段(如 embedding 或 vector)是存储向量数据的核心字段。其他常规字段(如整型、浮动小数、字符串等),用于存储与向量相关的附加信息(例如文本、标签等)。

例子:

from pymilvus import MilvusClient, DataType, Collection

# Step 1️⃣ 创建 Milvus 客户端并初始化 Collection
# MilvusClient 是与 Milvus 服务进行交互的客户端,连接到指定的数据库。
client = MilvusClient("milvus_rag_zh_demo_2.db")  # 假设使用一个本地数据库文件作为存储

# COLLECTION_NAME 是我们想要操作的集合名
COLLECTION_NAME = "zh_rag_demo_2"

# Step 2️⃣ 删除已有的 Collection(如果存在)
# 如果该集合已经存在,我们删除旧的集合以重新创建
if client.has_collection(COLLECTION_NAME):
    print(f"Collection '{COLLECTION_NAME}' already exists. Dropping it.")
    client.drop_collection(COLLECTION_NAME)  # 删除集合

# Step 3️⃣ 定义 Collection 的 Schema
# Collection Schema 用于定义集合中的字段,包括数据类型、维度等。
schema = MilvusClient.create_schema(
    auto_id=False,  # 不自动生成 ID(我们手动指定 ID)
    enable_dynamic_field=True,  # 启用动态字段支持
)

# Step 4️⃣ 添加字段到 Schema
# 每个字段需要指定字段名称、数据类型,以及其他一些属性(如是否是主键)
schema.add_field(field_name="my_id", datatype=DataType.INT64, is_primary=True)  # 主键字段
schema.add_field(field_name="my_vector", datatype=DataType.FLOAT_VECTOR, dim=5)  # 向量字段,维度为5
schema.add_field(field_name="my_varchar", datatype=DataType.VARCHAR, max_length=512)  # 字符串字段,最大长度为512

Milvus Lite 目前仅支持 Ubuntu 和 MacOS 操作系统。如果在 Windows 系统上运行上述代码,将会遇到此错误。另外,使用Milvus的时候,要确保Milvus已经在本地或者远程服务器运行,否则会报错。Milvus的启动和运行建议使用Docker的方式执行。

一个 Collections Schema 有一个主键、最多四个向量字段和几个标量字段。下图说明了如何将文章映射到模式字段列表。

搜索系统的数据模型设计包括分析业务需求,并将信息抽象为模式表达的数据模型。例如,搜索一段文本必须 “索引”,通过 “嵌入 “将字面字符串转换为向量,并启用向量搜索。除了这一基本要求外,可能还需要存储出版时间戳和作者等其他属性。有了这些元数据,就可以通过过滤来完善语义搜索,只返回特定日期之后或特定作者发表的文本。您还可以检索这些标量与主文本,以便在应用程序中呈现搜索结果。每个标量都应分配一个唯一标识符,以整数或字符串的形式组织这些文本片段。这些元素对于实现复杂的搜索逻辑至关重要。

Milvus与Embedding

在当今的信息检索和智能问答系统中,Embedding(向量表示)技术成为了连接自然语言与高效计算的桥梁。通过将文本、图像等非结构化数据转化为高维向量,我们可以实现更精确的语义匹配和内容理解。而Milvus作为一款开源的向量数据库,专为此类场景而生。它支持大规模向量的高效存储与相似度检索,为构建智能搜索引擎、推荐系统及 AI 应用提供了强大的基础设施。下面将结合实际案例,介绍如何利用 Embedding 技术与 Milvus 搭建一套完整的语义检索流程。

于是,在pymilvus中可以引入embedding的模型工具,用于未来的向量输出和检索:

# 从 pymilvus 中引入用于 embedding 的模型工具
from pymilvus import model

# 如果访问 huggingface 官方地址失败(如网络受限),可以取消下面的注释
# 设置环境变量,切换为 huggingface 镜像地址(例如清华、阿里等镜像)
# import os
# os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'

# 初始化一个默认的 embedding 函数,会自动下载一个小型的句子向量模型:
# paraphrase-albert-small-v2(约 50MB),适合快速测试或演示用途。
embedding_fn = model.DefaultEmbeddingFunction()

# 定义待向量化的文本列表,每条文本都是一个独立的文档或知识片段。
docs = [
    "Artificial intelligence was founded as an academic discipline in 1956.",
    "Alan Turing was the first person to conduct substantial research in AI.",
    "Born in Maida Vale, London, Turing was raised in southern England.",
]

# 使用 embedding 函数将文本转化为向量(embedding)
# 得到的结果是一个 list,每条向量为一个 numpy 数组,维度为 768
vectors = embedding_fn.encode_documents(docs)

# 输出向量
print("vectors:", vectors)

# 输出向量维度信息(用于对齐 Milvus 中 Collection 的字段设计)
# embedding_fn.dim 表示当前模型生成的向量维度
# vectors[0].shape 表示第一条向量的维度
print("Dim:", embedding_fn.dim, vectors[0].shape)  # 预期输出 Dim: 768 (768,)

# 组织向量数据为结构化的格式,准备后续插入 Milvus:
# 每条记录包含:
# - id:唯一编号
# - vector:生成的 embedding 向量
# - text:原始文本内容(可用于展示/检索返回)
# - subject:人为指定的分类标签(这里用作 metadata 过滤的演示)
data = [
    {"id": i, "vector": vectors[i], "text": docs[i], "subject": "history"}
    for i in range(len(vectors))
]

# 打印生成数据的基本信息:
# - 实体数量
# - 每条记录包含哪些字段
# - 向量维度是多少
print("Data has", len(data), "entities, each with fields: ", data[0].keys())
print("Vector dim:", len(data[0]["vector"]))

除此之外,在模型选择方面,还可以选择 Sentence Transformers、BGE M3、SPLADE、instructor、nomic、mGTE、Model2Vec,另外OpenAI、gemini、Voyage、Jina AI、Cohere、Ministral AI的模型需要相应的API-KEY才能使用。

嵌入函数类型API 或开源
openai密集API
sentence transformer密集开源
SPLADE稀疏开源
bge-m3混合开源
远航密集型应用程序接口
jina密集API
cohere密集API
指导员密集开源
Mistral AI密集应用程序接口
Nomic密集API
mGTE混合型开源
Model2Vec混合型开源
双子座混合型私有

可以参考代码进行修改,在model这个部分进行修改即可:

# 从 pymilvus 中引入用于 embedding 的模型工具
from pymilvus import model

# 如果访问 huggingface 官方地址失败(如网络受限),可以取消下面的注释
# 设置环境变量,切换为 huggingface 镜像地址(例如清华、阿里等镜像)
# import os
# os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'

# 初始化一个默认的 embedding 函数,会自动下载一个小型的句子向量模型:
# paraphrase-albert-small-v2(约 50MB),适合快速测试或演示用途。
# embedding_fn = model.DefaultEmbeddingFunction()

# sentence transformers 模型
embedding_fn = model.dense.SentenceTransformerEmbeddingFunction(
    model_name='all-MiniLM-L6-v2',  # Specify the model name
    device='cpu'  # Specify the device to use, e.g., 'cpu' or 'cuda:0'
)

# # BGE M3 模型
# embedding_fn = model.hybrid.BGEM3EmbeddingFunction(
#     model_name='BAAI/bge-m3',  # Specify the model name
#     device='cpu',  # Specify the device to use, e.g., 'cpu' or 'cuda:0'
#     use_fp16=False  # Specify whether to use fp16. Set to `False` if `device` is `cpu`.
# )

# # splade 模型
# embedding_fn = model.sparse.SpladeEmbeddingFunction(
#     model_name="naver/splade-cocondenser-selfdistil",
#     device="cpu"
# )

# 定义待向量化的文本列表,每条文本都是一个独立的文档或知识片段。
docs = [
    "Artificial intelligence was founded as an academic discipline in 1956.",
    "Alan Turing was the first person to conduct substantial research in AI.",
    "Born in Maida Vale, London, Turing was raised in southern England.",
]

# 使用 embedding 函数将文本转化为向量(embedding)
# 得到的结果是一个 list,每条向量为一个 numpy 数组,维度为 768
vectors = embedding_fn.encode_documents(docs)

# 输出向量
print("vectors:", vectors)

# 输出向量维度信息(用于对齐 Milvus 中 Collection 的字段设计)
# embedding_fn.dim 表示当前模型生成的向量维度
# vectors[0].shape 表示第一条向量的维度
print("Dim:", embedding_fn.dim, vectors[0].shape)  # 预期输出 Dim: 768 (768,)

# 组织向量数据为结构化的格式,准备后续插入 Milvus:
# 每条记录包含:
# - id:唯一编号
# - vector:生成的 embedding 向量
# - text:原始文本内容(可用于展示/检索返回)
# - subject:人为指定的分类标签(这里用作 metadata 过滤的演示)
data = [
    {"id": i, "vector": vectors[i], "text": docs[i], "subject": "history"}
    for i in range(len(vectors))
]

# 打印生成数据的基本信息:
# - 实体数量
# - 每条记录包含哪些字段
# - 向量维度是多少
print("Data has", len(data), "entities, each with fields: ", data[0].keys())
print("Vector dim:", len(data[0]["vector"]))

下面代码的整体流程是:连接 Milvus 客户端并创建集合,初始化一个嵌入模型并将文本转化为向量,组织数据结构并插入到 Milvus,使用一个问题进行语义查询,获取最相似的文本内容。

# 引入必要的库:pymilvus 中的模型工具和客户端类
from pymilvus import model
from pymilvus import MilvusClient

# 初始化一个 Milvus 客户端,连接到本地或指定路径的数据库文件
client = MilvusClient("milvus_demo.db")

# 如果已存在名为 "demo_collection" 的集合,先删除(避免重复创建时报错)
if client.has_collection(collection_name="demo_collection"):
    client.drop_collection(collection_name="demo_collection")

# 创建一个新的集合(Collection),用于存储向量数据
# 参数说明:
# - collection_name:集合名称
# - dimension:向量的维度(本例使用的是 768 维)
client.create_collection(
    collection_name="demo_collection",
    dimension=768,
)

# ⚠️ 如果无法连接 huggingface 官方模型仓库(比如被墙),可以使用国内镜像站点:
# 设置 HF_ENDPOINT 环境变量来更改默认的 huggingface 地址,例如使用清华镜像:
# import os
# os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'

# 初始化一个默认的 embedding 函数,会自动下载 paraphrase-albert-small-v2 模型
# 模型体积小,加载快,适合用于快速测试/演示
embedding_fn = model.DefaultEmbeddingFunction()

# (可选)你也可以使用更强的模型,例如 SentenceTransformer、BGE M3、Splade 等
# 下面是一些替代方案(按需取消注释):

# 使用 sentence-transformers 模型
# embedding_fn = model.dense.SentenceTransformerEmbeddingFunction(
#     model_name='all-MiniLM-L6-v2',
#     device='cpu'  # 或使用 'cuda:0' 来使用 GPU
# )

# 使用 BGE M3 多任务嵌入模型
# embedding_fn = model.hybrid.BGEM3EmbeddingFunction(
#     model_name='BAAI/bge-m3',
#     device='cpu',
#     use_fp16=False
# )

# 使用稀疏向量模型 Splade(适用于稀疏向量检索场景)
# embedding_fn = model.sparse.SpladeEmbeddingFunction(
#     model_name="naver/splade-cocondenser-selfdistil",
#     device="cpu"
# )

# 准备文本数据:这些将作为示例文档被嵌入为向量
docs = [
    "Artificial intelligence was founded as an academic discipline in 1956.",
    "Alan Turing was the first person to conduct substantial research in AI.",
    "Born in Maida Vale, London, Turing was raised in southern England.",
]

# 使用嵌入函数将文本转换为向量
# 返回值为一个列表,每个元素是一个 numpy 数组(维度为 768)
vectors = embedding_fn.encode_documents(docs)

# 打印生成的向量(可以注释掉以避免打印过多内容)
print("vectors:", vectors)

# 打印嵌入函数维度和实际向量维度(用于确认维度一致性)
print("Dim:", embedding_fn.dim, vectors[0].shape)

# 将向量数据组织为结构化格式,便于后续插入到 Milvus 中
# 每个字典代表一条记录,包括:
# - id:唯一编号
# - vector:对应的嵌入向量
# - text:原始文本
# - subject:可选分类标签(可用于后续过滤查询)
data = [
    {"id": i, "vector": vectors[i], "text": docs[i], "subject": "history"}
    for i in range(len(vectors))
]

# 打印数据结构信息:
print("Data has", len(data), "entities, each with fields: ", data[0].keys())
print("Vector dim:", len(data[0]["vector"]))

# 将数据插入到 Milvus 中的 demo_collection 集合
res = client.insert(collection_name="demo_collection", data=data)

# 打印插入结果(通常包含成功插入的数量等信息)
print("res:", res)

# 接下来执行向量搜索(即:语义检索)
# 使用同样的嵌入函数对查询语句进行编码,得到向量
query_vectors = embedding_fn.encode_queries(["Who is Alan Turing?"])

# ⚠️ 如果没有 embedding 函数,也可以使用随机向量模拟查询(仅限演示用)
# import random
# query_vectors = [ [ random.uniform(-1, 1) for _ in range(768) ] ]

# 在 demo_collection 中执行向量检索
res_search = client.search(
    collection_name="demo_collection",  # 检索目标集合
    data=query_vectors,  # 查询向量
    limit=2,  # 返回最相似的 2 条记录
    output_fields=["text", "subject"],  # 指定返回的字段(原始文本和标签)
)

# 打印检索结果(包括匹配文本和相似度等信息)
print("res_search:", res_search)

# 提取并打印搜索结果中的具体条目
print(list(res_search[0])[0])  # 第一个查询返回的第一条结果
print(list(res_search)[0][1])  # 第一个查询返回的第二条结果

同时,文件夹下会出现一个milvus_demo.db,用于保存向量数据。

如果画一个流程图的话,是按下面的流程来运行的。

由于Milvus Lite的所有数据都存储在本地文件中,因此即使在程序终止后,你也可以通过创建一个带有现有文件的MilvusClient ,将所有数据加载到内存中。例如,这将恢复 “milvus_demo.db “文件中的 Collections,并继续向其中写入数据。

from pymilvus import MilvusClient
client = MilvusClient("milvus_demo.db")

如果想删除某个 Collections 中的所有数据,可以通过以下方法丢弃该Collections:

# Drop collection
client.drop_collection(collection_name="demo_collection")

Milvus与Rerankers

在现代语义检索系统中,检索流程通常被划分为两个阶段:初始召回(First-Stage Retrieval)与重排序(Re-ranking)。Milvus 作为一个开源、高性能的向量数据库,专为处理大规模高维向量检索任务而设计,广泛应用于初始召回阶段。其核心能力在于高效构建和查询向量索引(如 IVF、HNSW、DiskANN 等),支持近似最近邻(ANN)算法,以实现对查询向量在大规模语料中的快速相似度搜索。通过将文本、图像等非结构化数据嵌入为向量,Milvus 能够在亚秒级时间内返回与输入语义最接近的候选项,为后续精排阶段提供基础支撑。

而 Rerankers(重排序模型)主要作用于检索系统的第二阶段。它通常采用更精细的模型架构(如基于 Transformer 的 Cross-Encoder),以逐对方式对候选文本与查询进行交互式建模,从而输出更精准的相关性评分。尽管计算开销相较于向量检索更高,Rerankers 在精度上的提升对于提高系统整体性能具有关键意义。因此,将 Milvus 用于高效召回,再通过 Rerankers 对候选结果进行精细排序,已成为构建高质量语义检索系统的主流范式。

常见的Rerankers功能包括以下五种,有开源模型和应用程序接口。

Rerankers 功能应用程序接口或开源开源地址
BGE开源https://ollama.com/zyw0605688/bge-reranker-v2-m3
交叉编码器开源https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2
Voyage应用程序接口 
Cohere应用程序接口 
Jina AIAPI 

如果使用BGE的重排序模型来构建的话,可以使用以下代码的案例:

# 从 pymilvus.model.reranker 模块中引入 BGE 重排序模型函数
from pymilvus.model.reranker import BGERerankFunction

# ----------------------------------------------------------
# 初始化 Reranker(重排序器):
# 使用 BAAI(智源研究院)提供的 BGE-Reranker-v2-M3 模型。
# 该模型基于 Cross-Encoder 架构,通过对 query 和文档对进行语义交互建模,
# 输出相关性打分,用于对初始检索结果进行排序提升精度。
# ----------------------------------------------------------
bge_rf = BGERerankFunction(
    model_name="BAAI/bge-reranker-v2-m3",  # 模型名称,默认即为该模型
    device="cpu"  # 计算设备,可改为 'cuda:0' 使用 GPU 加速
)

# ----------------------------------------------------------
# 定义一个查询(query),用于检索历史相关信息。
# ----------------------------------------------------------
query = "What event in 1956 marked the official birth of artificial intelligence as a discipline?"

# ----------------------------------------------------------
# 定义候选文档列表(documents):
# 模拟从 Milvus 检索返回的初步候选文本片段(Top-K),
# 接下来将使用 Reranker 进一步对它们进行精排。
# 文档集合里面有四个元素,从0到3编号。
# ----------------------------------------------------------
documents = [
    "In 1950, Alan Turing published his seminal paper, 'Computing Machinery and Intelligence,' proposing the Turing Test as a criterion of intelligence, a foundational concept in the philosophy and development of artificial intelligence.",
    "The Dartmouth Conference in 1956 is considered the birthplace of artificial intelligence as a field; here, John McCarthy and others coined the term 'artificial intelligence' and laid out its basic goals.",
    "In 1951, British mathematician and computer scientist Alan Turing also developed the first program designed to play chess, demonstrating an early example of AI in game strategy.",
    "The invention of the Logic Theorist by Allen Newell, Herbert A. Simon, and Cliff Shaw in 1955 marked the creation of the first true AI program, which was capable of solving logic problems, akin to proving mathematical theorems."
]

# ----------------------------------------------------------
# 执行重排序操作:
# 将 query 与每个文档组合进行相关性评分,输出按分值降序排列的 Top-K 文档。
# top_k 参数指定只保留得分最高的前 K 条(这里设为 3)。
# 返回结果为一个包含 RerankResult 对象的列表,每个对象包含:
# - index:原文档在输入列表中的索引位置
# - score:query 与该文档的语义相关性打分(越高越相关)
# - text:文档原文内容
# ----------------------------------------------------------
results = bge_rf(
    query=query,
    documents=documents,
    top_k=3,  # 返回得分最高的前 3 条
)

# ----------------------------------------------------------
# 遍历输出精排结果:
# 展示每条候选文档的原始索引、得分(保留 6 位小数)、文本内容。
# 注意结果已按 score 排序,score 越高代表与 query 越匹配。
# ----------------------------------------------------------
for result in results:
    print(f"Index: {result.index}")  # 文本在原始 documents 中的位置
    print(f"Score: {result.score:.6f}")  # 重排序得分
    print(f"Text: {result.text}\n")  # 文本内容


如果将query和document修改成中文,同样可以找到结果。查询是:

query = "1956年标志着人工智能正式诞生的事件是什么?"

候选文档是:

documents = [
    "1950年,图灵发表了著名论文《计算机器与智能》,提出了图灵测试,这是人工智能哲学的重要基石。",
    "1956年达特茅斯会议被广泛认为是人工智能作为一个学科诞生的标志,在这次会议上,“人工智能”这一术语首次被提出,并确立了研究目标。",
    "1951年,英国数学家图灵开发了一个可以下棋的程序,展示了早期的人工智能应用。",
    "1955年,艾伦·纽厄尔与赫伯特·西蒙等人发明了“逻辑理论家”程序,这是第一个能够自动证明定理的人工智能系统。"
]

其搜索的结果是:

如果需要使用交叉编码器,那么可以参考HuggingFace上面的链接(https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2),输入以下代码即可计算两个文档之间的相似度。

from sentence_transformers import CrossEncoder

model = CrossEncoder('cross-encoder/ms-marco-MiniLM-L6-v2')
scores = model.predict([
    ("How many people live in Berlin?", "Berlin had a population of 3,520,031 registered inhabitants in an area of 891.82 square kilometers."),
    ("How many people live in Berlin?", "Berlin is well known for its museums."),
])
print(scores)

# [ 8.607141 -4.320079]

还可以用以下多种模型进行选择:

Model-NameNDCG@10 (TREC DL 19)MRR@10 (MS Marco Dev)Docs / Sec
Version 2 models   
cross-encoder/ms-marco-TinyBERT-L2-v269.8432.569000
cross-encoder/ms-marco-MiniLM-L2-v271.0134.854100
cross-encoder/ms-marco-MiniLM-L4-v273.0437.72500
cross-encoder/ms-marco-MiniLM-L6-v274.339.011800
cross-encoder/ms-marco-MiniLM-L12-v274.3139.02960
Version 1 models   
cross-encoder/ms-marco-TinyBERT-L267.4330.159000
cross-encoder/ms-marco-TinyBERT-L468.0934.52900
cross-encoder/ms-marco-TinyBERT-L669.5736.13680
cross-encoder/ms-marco-electra-base71.9936.41340
Other models   
nboost/pt-tinybert-msmarco63.6328.82900
nboost/pt-bert-base-uncased-msmarco70.9434.75340
nboost/pt-bert-large-msmarco73.3636.48100
Capreolus/electra-base-msmarco71.2336.89340
amberoad/bert-multilingual-passage-reranking-msmarco68.435.54330
sebastian-hofstaetter/distilbert-cat-margin_mse-T2-msmarco72.8237.88720

下面我们使用cross-encoder/ms-marco-MiniLM-L12-v2模型来进行相似度的计算:

from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch
from sentence_transformers import CrossEncoder

# 方法一:
model = CrossEncoder('cross-encoder/ms-marco-MiniLM-L12-v2')
scores = model.predict([
    ("How many people live in Berlin?", "Berlin had a population of 3,520,031 registered inhabitants in an area of 891.82 square kilometers."),
    ("How many people live in Berlin?", "Berlin is well known for its museums."),
])
print(scores)

# 方法二:
model = AutoModelForSequenceClassification.from_pretrained('cross-encoder/ms-marco-MiniLM-L12-v2')
tokenizer = AutoTokenizer.from_pretrained('cross-encoder/ms-marco-MiniLM-L12-v2')

features = tokenizer(['How many people live in Berlin?', 'How many people live in Berlin?'], ['Berlin had a population of 3,520,031 registered inhabitants in an area of 891.82 square kilometers.', 'Berlin is well known for its museums.'],  padding=True, truncation=True, return_tensors="pt")

model.eval()
with torch.no_grad():
    scores = model(**features).logits
    print(scores)

如果要进行重排序的话,可以参考下面的文档:

# 从 pymilvus.model.reranker 模块中导入交叉编码器重排序函数
from pymilvus.model.reranker import CrossEncoderRerankFunction

# ✅ 步骤 1:定义交叉编码器(Cross Encoder)重排序函数
# 该函数内部会自动下载 Hugging Face 上的模型并用于 rerank
ce_rf = CrossEncoderRerankFunction(
    model_name="cross-encoder/ms-marco-MiniLM-L12-v2",  # 使用指定的 cross-encoder 模型(支持语义匹配任务)
    device="cpu"  # 指定模型运行设备,如 'cpu' 或 'cuda:0'(GPU)
)

# ✅ 步骤 2:定义用户查询(Query)
query = "What event in 1956 marked the official birth of artificial intelligence as a discipline?"
# 中文翻译:1956年哪一事件标志着人工智能作为一门学科的正式诞生?

# ✅ 步骤 3:准备待重排序的候选文档(Documents)
# 每个字符串都是一个候选答案,Cross Encoder 会将它们与 Query 组合成一个个句对进行评分
documents = [
    "In 1950, Alan Turing published his seminal paper, 'Computing Machinery and Intelligence,' proposing the Turing Test as a criterion of intelligence, a foundational concept in the philosophy and development of artificial intelligence.",
    # 图灵1950年的论文,提出图灵测试,为AI发展奠定哲学基础

    "The Dartmouth Conference in 1956 is considered the birthplace of artificial intelligence as a field; here, John McCarthy and others coined the term 'artificial intelligence' and laid out its basic goals.",
    # 1956年达特茅斯会议,被广泛认为是AI的诞生标志

    "In 1951, British mathematician and computer scientist Alan Turing also developed the first program designed to play chess, demonstrating an early example of AI in game strategy.",
    # 图灵在1951年开发了下棋程序,展示早期AI在博弈中的应用

    "The invention of the Logic Theorist by Allen Newell, Herbert A. Simon, and Cliff Shaw in 1955 marked the creation of the first true AI program, which was capable of solving logic problems, akin to proving mathematical theorems."
    # 1955年“逻辑理论家”程序是首个能解逻辑问题的AI程序
]

# ✅ 步骤 4:调用重排序函数进行语义匹配排序(Reranking)
# Cross Encoder 会对 (query, document) 成对输入进行语义评分,返回得分最高的 top_k 条
results = ce_rf(
    query=query,
    documents=documents,
    top_k=3,  # 返回得分最高的前 3 个文档
)

# ✅ 步骤 5:遍历结果,输出每条结果的索引、分数、文本内容
# Cross Encoder 输出的是基于语义匹配的相关性打分,越高越相关
for result in results:
    print(f"Index: {result.index}")       # 文档在原始列表中的索引
    print(f"Score: {result.score:.6f}")   # Cross Encoder 计算出的相关性得分
    print(f"Text: {result.text}\n")       # 对应的文档内容

Milvus与RAG

RAG简介

Retrieval-Augmented Generation(RAG)是一种结合了生成模型与外部知识库的问答与文本生成框架,它通过引入检索机制增强了语言模型的上下文感知能力与事实一致性。传统的预训练语言模型(如 GPT、BERT 等)虽然在多种自然语言任务中表现优异,但其生成内容完全依赖于固定参数中的知识,难以动态更新、覆盖长尾信息或应对实时变化。RAG 模型通过“检索-生成”的两阶段流程克服了这一局限:首先基于输入查询从外部文档库中检索相关文本段落(通常以嵌入向量为索引),然后将检索结果与原始查询共同输入生成模型,从而生成更丰富、准确且可溯源的回答。

Milvus 作为一款专注于向量检索的高性能数据库,在 RAG 框架中扮演着关键的知识检索组件。它能够高效地存储和检索大规模嵌入文档,利用近似最近邻(ANN)算法快速定位与查询语义最接近的上下文。通过将文本数据嵌入为高维向量并存入 Milvus,RAG 系统可以在每次生成任务中实时访问结构化外部知识,从而动态增强语言模型的生成能力。

RAG 与 Milvus 的集成,使得模型生成不仅更具上下文相关性,同时具有良好的可扩展性与知识更新能力。该组合为构建高质量的问答系统、智能客服、科研助手等提供了坚实的技术基础,并代表了当前生成式 AI 系统从封闭式向开放式知识访问的演进方向。

一个简单的模式就是如下图所示的案例:

Retrieval-Augmented Generation(RAG)框架通过将外部知识检索与语言模型的生成能力结合,有效增强了模型的事实一致性与动态更新能力。本文所采用的 RAG 系统主要包括三个核心阶段:文档嵌入与索引构建、在线查询与检索生成、以及可选的重排序增强。

一、文档嵌入与索引构建

首先,系统从原始知识库中收集结构化或非结构化的文档内容。通过分段与预处理操作,每个文档被切分为若干语义清晰的片段。这些片段随后输入至预训练的文本嵌入模型(如 Sentence Transfomers、BGE M3、Instructor、Model2Vec等),将文本转化为固定维度的语义向量。所有向量及其对应的文本片段被统一存储于向量数据库 Milvus 中。Milvus 支持高效的向量索引构建(如 HNSW、ANN、DiskANN 等),为大规模语义检索提供底层支撑。

二、在线检索与生成

当用户提交自然语言查询后,系统首先将查询文本通过同样的嵌入模型转化为查询向量。随后,该向量被用于在 Milvus 中进行近似最近邻检索,系统返回与查询语义最接近的 Top-K 文本片段。此阶段主要实现高召回率的候选过滤,是整个生成流程的语义支撑部分。

三、重排序与上下文拼接(可选增强)

为进一步提升检索结果的相关性,系统可引入 Reranker 模块对 Milvus 返回的候选片段进行重排序。Reranker 通常采用基于 Transformer 的 Cross-Encoder 架构逐对计算候选段与查询之间的交互得分,以获得更高精度的排序结果。或者BGE的Reranker模型来获取排序结果。排序后的文本被选取若干条,并与原始用户查询共同拼接为生成模型的输入上下文。

四、语言模型生成回答

最终,上下文与用户查询被输入至大型语言模型(如GPT、LLaMA、ChatGLM、DeepSeek等),模型基于输入内容生成语言自然、语义准确、并融合外部知识的响应文本。该流程实现了生成式AI系统与结构化外部知识库之间的协同融合,兼具生成能力与知识可控性。

RAG与Milvus的示例

用Milvus以及相应的embedding和rerankers可以获得相应知识库的问答功能。现在给一个demo示例,假设我们有一个公司A的组织架构和部门内容介绍(纯属虚构,如有雷同,纯属巧合),我们将其放入知识库中,形成一个docs的文档数据,然后把这些数据放入Milvus的数据库中,再通过Client去检索和重排,得到数据context_text之后将其作为背景知识放入输入的数据prompt中,最后用Ollama的流式输出得到结果。

from pymilvus import MilvusClient
from pymilvus import model
from pymilvus.model.reranker import CrossEncoderRerankFunction
from sentence_transformers import SentenceTransformer
import ollama
import time

# Step 1️⃣ 创建 Milvus 客户端并初始化 Collection
client = MilvusClient("milvus_rag_zh.db")
COLLECTION_NAME = "zh_rag_demo"

# 若已存在,删除原 Collection
if client.has_collection(COLLECTION_NAME):
    client.drop_collection(COLLECTION_NAME)

# 创建新的向量集合,维度要和选用的 embedding 模型一致
client.create_collection(
    collection_name=COLLECTION_NAME,
    dimension=768,  # 使用默认模型生成的是 768 维向量
)

# Step 2️⃣ 中文句向量模型加载,用于对文档和查询编码
embedding_model = model.DefaultEmbeddingFunction()


# 准备中文知识库文档(可视为 RAG 的数据库),伪造的数据,如有雷同,纯属巧合。
docs = [
    "A公司由五个一级部门组成:战略规划部、产品研发部、市场销售部、人力资源部与财务管理部。",
    "战略规划部负责公司整体战略制定与年度业务目标设定,由高级副总裁王蕾领导。",
    "产品研发部下设三个小组:智能算法组、后端架构组、移动客户端组,分别由赵新宇、韩飞和李倩倩负责。",
    "人力资源部目前有6名成员,涵盖招聘、培训、绩效、薪酬等模块,负责人为HR总监陈蓉。",
    "市场销售部主要负责B端客户开拓与服务,目前设有北京、上海、深圳三个销售大区。",
    "财务管理部由CFO黄志明牵头,下设预算组、税务组与资金组,分别管理不同的财务职责。",
    "A公司CEO为沈立峰,CTO为冯启航,两人每季度召开一次高管战略会,协调部门合作。",
    "智能算法组正在负责天眼项目的模型迭代,预计Q3完成V2版本部署。",
    "后端架构组正在推动服务中台的容器化改造,目前已完成40%的微服务迁移。",
    "移动客户端组刚完成v6.2.0版本的迭代,新增了消息推送与报表订阅功能。"
]

# 将中文文档编码为向量(embedding)
vectors = embedding_model.encode_documents(docs)

# 组织结构化数据,插入到 Milvus 中
data_to_insert = [
    {"id": i, "vector": vectors[i], "text": docs[i], "tag": "公司组织架构"}
    for i in range(len(docs))
]

client.insert(collection_name=COLLECTION_NAME, data=data_to_insert)

# Step 3️⃣ 用户输入查询(中文)
query = "谁是A公司的CTO?"

# 查询向量化
query_vector = embedding_model.encode_documents([query])

# Step 4️⃣ 从 Milvus 中基于向量检索 Top-K 最相关文档
search_results = client.search(
    collection_name=COLLECTION_NAME,
    data=query_vector,
    limit=5,
    output_fields=["text"]
)

# print(search_results)
# print(list(search_results[0]))

# 提取原始文本内容
retrieved_texts = [doc["entity"]["text"] for doc in list(search_results[0])]

# Step 5️⃣ 使用 CrossEncoder 进行重排序,提升相关性排名
reranker = CrossEncoderRerankFunction(
    model_name="cross-encoder/ms-marco-MiniLM-L12-v2",
    device="cpu"
)

reranked = reranker(
    query=query,
    documents=retrieved_texts,
    top_k=3  # 可以根据需要调整返回数量
)

# 拼接重排序后的文档,作为 LLM 的上下文
context_text = "\n".join([r.text for r in reranked])

# Step 6️⃣ 构造 prompt,准备传入 LLM 生成回答
prompt = f"""
请根据以下背景知识回答用户提出的问题:

【背景知识】
{context_text}

【问题】
{query}

【回答】
"""

# Step 7️⃣ 使用 Ollama + DeepSeek 模型生成回答(流式输出)
print("🤖 正在生成回答...\n")

# 调用 Ollama SDK,使用 streaming=True 获取流式输出
stream = ollama.chat(
    model="deepseek-r1:32b",
    messages=[{"role": "user", "content": prompt}],
    stream=True
)

# Step 8️⃣ 打印流式输出结果
response_buffer = ""
for chunk in stream:
    delta = chunk.get("message", {}).get("content", "")
    print(delta, end="", flush=True)  # 实时输出
    response_buffer += delta

通过更换query的内容,可以获得以下结论:

  1. 向量嵌入和Rerank存在优化空间,包括模型的选型、参数配置等内容,否则知识库无法精确找出相关知识;
  2. 找出的个性化词条作为输入是不会影响外部公开问题的正常回答的。
查询回答(来自 RAG + LLM)结论
谁是A公司的CTO?冯启航是A公司的CTO。正确
A公司哪个小组负责天眼项目?A公司的天眼项目负责人尚未明确,但根据背景知识,该项目可能由产品研发部的其中一个小组负责。具体来说: 1. 智能算法组:负责AI和数据分析相关的工作。2. 后端架构组:负责应用程序的后台结构。3. 移动客户端组:负责移动端应用开发。 如需确定具体负责人,请提供更多项目细节。错误,原因是搜索的时候没有找到天眼项目这个信息。
A公司中产品研发部下有哪些组?A公司中产品研发部下有智能算法组、后端架构组和移动客户端组三个小组。正确
A公司的预算组是哪位负责?根据提供的背景知识,无法确定A公司预算组的具体负责人。虽然预算管理通常由财务管理部负责,但背景信息中并未提及该部门的负责人或相关细节。因此,基于现有信息,我们不能确定预算组的负责人是谁。 【答案】根据提供的背景知识,无法确定A公司的预算组是由谁负责,因为相关信息未提及。错误,原因是搜索的时候没有找到预算组这个信息。关键字的搜索不够好。 
王蕾负责什么?王蕾是公司的高级副总裁,负责领导战略规划部,主要职责包括制定公司整体战略和设定年度业务目标。正确
什么是数学分析?数学分析是研究函数的性质及其变化规律的一个重要学科,主要涵盖微积分、实变函数、复变函数等内容,广泛应用于物理学、工程学和经济学等领域。正确,没有受到知识库的影响
物理学有哪些研究方向?物理学是一门广泛而深入的科学,涵盖了许多不同的研究方向和分支领域。以下是一些主要的研究方向: 1. 经典力学:研究物体在宏观尺度下的运动和相互作用,包括牛顿力学、拉格朗日力学和哈密顿力学。正确,没有受到知识库的影响

同时,可以查看Collection的数据库信息。

from pymilvus import MilvusClient

# 创建 Milvus 客户端并连接数据库
client = MilvusClient("milvus_rag_zh.db")
COLLECTION_NAME = "zh_rag_demo"

# 获取集合的collection信息。要查看数据库中的所有集合,你可以使用 list_collections() 方法,它将返回当前数据库中的所有集合名称。
collection_list = client.list_collections()
print("List of Collections:", collection_list)

# 查看集合的统计信息,要查看集合中包含的实体数量,你可以使用 get_collection_stats() 方法。它将返回集合的统计信息,其中包括存储的向量数量(即实体数量)。
collection_stats = client.get_collection_stats(COLLECTION_NAME)
print("Collection Stats:", collection_stats)

# 还可以获取特定 Collection 的详细信息
desc_collection = client.describe_collection(collection_name=COLLECTION_NAME)
print("Describe Collection:", desc_collection)

Milvus总结

综上所述,Milvus 是一个开源的高性能向量数据库,专为处理大规模、高维度数据的存储与检索而设计。它支持多种数据类型的高效索引和快速检索,特别适用于机器学习、人工智能和数据分析领域中的相似性搜索任务。Milvus 能够处理从文本、图像到视频等多种格式的向量数据,并且具有出色的扩展性,能够应对大数据量的挑战。通过提供如 IVF、HNSW、Annoy 等多种索引方式,Milvus 能显著提升高维向量检索的速度和效率,是实现高效数据检索和实时分析的重要工具。

参考资料

  1. Milvus的官网:https://milvus.io/zh
  2. Milvus的GitHub:https://github.com/milvus-io/milvus
  3. 用Python操作Milvus向量数据库的简明教程:https://www.dboop.com/ops/用python操作milvus向量数据库的简明教程/#创建索引

RAG与大模型的结合:让LLM更智能的关键

1.  RAG的定义

大模型(Large Language Models,LLMs)的发展经历了从小规模模型到如今大规模、深度学习技术不断突破的过程。最早的语言模型主要依赖规则和手工特征,虽然能够进行一定的语言理解和生成,但缺乏足够的灵活性和准确性。随着深度学习的兴起,尤其是深度神经网络的应用,大规模语言模型开始崭露头角。

从最初的GPT(Generative Pre-trained Transformer)到BERT(Bidirectional Encoder Representations from Transformers)再到如今的GPT-4、DeepSeek-R1等,语言模型的规模和能力迅速提升。大模型通常包含数十亿到数百亿个参数,通过海量数据进行预训练,能够捕捉到语言中的复杂关系和语境信息。大模型的预训练使其具备了强大的迁移学习能力,能够在多个任务上取得优秀的性能,无论是文本生成、问答、翻译还是推理任务。大模型的发展不仅在技术层面突破了许多原有的限制,还在应用上带来了巨大的变革。比如,基于大模型的自然语言处理技术已经广泛应用于智能助手、自动翻译、内容生成等领域,极大地提高了人机交互的效率和质量。从自然语言处理的发展历程来看,LLM已经是近期最热门的研究方向之一。

同时,大模型的研究方向是非常宽泛的,包括但不限于LLM本身,还包括提示词工程,检索增强生成及其各种变形,Agent LLM,LLM 应用框架等方向。

检索增强生成(Retrieval-augmented generation,RAG)是指对大型语言模型输出进行优化,使其能够在生成响应之前引用训练数据来源之外的权威知识库。大型语言模型(LLM)用海量数据进行训练,使用数十亿个参数为回答问题、翻译语言和完成句子等任务生成原始输出。在 LLM 本就强大的功能基础上,RAG 将其扩展为能访问特定领域或组织的内部知识库,所有这些都无需重新训练模型。这是一种经济高效地改进 LLM 输出的方法,让它在各种情境下都能保持相关性、准确性和实用性。下图展示了有RAG和没有RAG的两种完全不同的答案。

2.  RAG的重要性

LLM 是一项关键的人工智能(AI)技术,为智能聊天机器人和其他自然语言处理(Natural Language Processing,NLP)应用程序提供支持。目标是通过交叉引用权威知识来源,创建能够在各种环境中回答用户问题的机器人。不幸的是,LLM 技术的本质在 LLM 响应中引入了不可预测性。此外,LLM 训练数据是静态的,并引入了其所掌握知识的截止日期。

LLM 面临的已知挑战包括

  • 在没有答案的情况下提供虚假信息。
  • 当用户需要特定的当前响应时,提供过时或通用的信息。
  • 从非权威来源创建响应。
  • 由于术语混淆,不同的培训来源使用相同的术语来谈论不同的事情,因此会产生不准确的响应。

可以将大语言模型看作是一个过于热情的新员工,他拒绝随时了解时事,但总是会绝对自信地回答每一个问题。不幸的是,这种态度会对用户的信任产生负面影响,这是您不希望聊天机器人效仿的!

RAG 是解决其中一些挑战的一种方法,它会重定向 LLM,从权威的、预先确定的知识来源中检索相关信息。组织可以更好地控制生成的文本输出,并且用户可以深入了解 LLM 如何生成响应。

上图呈现了一个简单的RA-LLMs框架。

3.  RAG的优势

3.1 经济高效

聊天机器人开发通常从基础的大模型开始。基础模型是在广泛的广义和未标记数据上训练的 API 可访问 LLM。针对组织或领域特定信息重新训练的计算和财务成本很高。RAG 是一种将新数据引入 LLM 的更加经济高效的方法。它使生成式人工智能技术更广泛地获得和使用。

3.2 信息的及时性

即使 LLM 的原始训练数据来源适合您的需求,但保持相关性也具有挑战性。RAG 允许开发人员为生成模型提供最新的研究、统计数据或新闻。他们可以使用 RAG 将 LLM 直接连接到实时社交媒体提要、新闻网站或其他经常更新的信息来源。然后,LLM 可以向用户提供最新信息。

3.3 增强信任度

RAG 允许 LLM 通过来源归属来呈现准确的信息。输出可以包括对来源的引文或引用。如果需要进一步说明或更详细的信息,用户也可以自己查找源文档。这可以增加对您的生成式人工智能解决方案的信任和信心。

3.4 增加控制权

借助 RAG,开发人员可以更高效地测试和改进他们的聊天应用程序。他们可以控制和更改 LLM 的信息来源,以适应不断变化的需求或跨职能使用。开发人员还可以将敏感信息的检索限制在不同的授权级别内,并确保 LLM 生成适当的响应。此外,如果 LLM 针对特定问题引用了错误的信息来源,他们还可以进行故障排除并进行修复。组织可以更自信地为更广泛的应用程序实施生成式人工智能技术。

4.  RAG的工作原理

如果没有 RAG,LLM 会接受用户输入,并根据它所接受训练的信息或它已经知道的信息创建响应。RAG 引入了一个信息检索组件,该组件利用用户输入首先从新数据源提取信息。用户查询和相关信息都提供给 LLM。LLM 使用新知识及其训练数据来创建更好的响应。下图显示了将 RAG 与 LLM 配合使用的概念流程。

4.1 创建外部数据

LLM 原始训练数据集之外的新数据称为外部数据。它可以来自多个数据来源,例如 API、数据库或文档存储库。数据可能以各种格式存在,例如文件、数据库记录或长篇文本。另一种称为嵌入语言模型的 AI 技术将数据转换为数字表示形式并将其存储在向量数据库中。这个过程会创建一个生成式人工智能模型可以理解的知识库。

4.2 检索相关信息

下一步是执行相关性搜索。用户查询将转换为向量表示形式,并与向量数据库匹配。例如,考虑一个可以回答组织的人力资源问题的智能聊天机器人。如果员工搜索:“我有多少年假?”,系统将检索年假政策文件以及员工个人过去的休假记录。这些特定文件将被退回,因为它们与员工输入的内容高度相关。相关性是使用数学向量计算和表示法计算和建立的。

4.3 增强LLM提示

接下来,RAG 模型通过在上下文中添加检索到的相关数据来增强用户输入(或提示)。此步骤使用提示工程技术与 LLM 进行有效沟通。增强提示允许大型语言模型为用户查询生成准确的答案。

4.4 更新外部数据

下一个问题可能是——如果外部数据过时了怎么办? 要维护当前信息以供检索,请异步更新文档并更新文档的嵌入表示形式。您可以通过自动化实时流程或定期批处理来执行此操作。这是数据分析中常见的挑战——可以使用不同的数据科学方法进行变更管理。

5.  检索增强生成和语义搜索

5.1 两者的定义

RAG(Retrieval-Augmented Generation):RAG的核心目标是通过检索外部知识(通常是文档、数据库、或其他文本资源)来增强生成式模型的回答能力。RAG结合了信息检索(retrieval)和生成模型(generation),它首先从大规模的文本库中检索相关内容,再利用生成模型(例如大型语言模型)结合这些内容生成最终的回答。这种方法特别适合用于生成需要依赖大量背景知识的文本,像是问答、文档摘要等任务。

语义搜索(Semantic Search):语义搜索的核心任务是通过理解查询的语义信息来找到与查询最相关的文档或片段。与传统的基于关键词的搜索方法不同,语义搜索基于向量表示和深度学习技术,能够理解查询和文档之间的深层语义关系,从而提供更相关的搜索结果。它通常用于搜索引擎中,目的是提高搜索结果的准确性和相关性。

5.2 两者的相关性

语义搜索可以提高 RAG 结果,适用于想要在其 LLM 应用程序中添加大量外部知识源的组织。现代企业在各种系统中存储大量信息,例如手册、常见问题、研究报告、客户服务指南和人力资源文档存储库等。上下文检索在规模上具有挑战性,因此会降低生成输出质量。

语义搜索技术可以扫描包含不同信息的大型数据库,并更准确地检索数据。例如,他们可以回答诸如 “去年在机械维修上花了多少钱?”之类的问题,方法是将问题映射到相关文档并返回特定文本而不是搜索结果。然后,开发人员可以使用该答案为 LLM 提供更多上下文。

RAG 中的传统或关键字搜索解决方案对知识密集型任务产生的结果有限。开发人员在手动准备数据时还必须处理单词嵌入、文档分块和其他复杂问题。相比之下,语义搜索技术可以完成知识库准备的所有工作,因此开发人员不必这样做。它们还生成语义相关的段落和按相关性排序的标记词,以最大限度地提高 RAG 有效载荷的质量。

6.  RAG的发展历程

6.1 RAG的成长树

大模型涉及的主要阶段包括预训练、微调和推理。随着大型语言模型(LLMs)的出现,RAG的研究最初集中于利用LLMs强大的上下文学习能力,主要集中在推理阶段。随后,研究逐渐深入,逐步与LLMs的微调过程结合。研究人员还在探索通过检索增强技术,在预训练阶段提升语言模型的能力。下图是RAG(检索增强生成)研究的技术发展路线图。

RAG过程在问答任务中的一个典型实例。它主要包括三个步骤:

  1. 索引:将文档拆分成若干块,编码成向量,并存储在向量数据库中。
  2. 检索:根据语义相似性,检索与问题最相关的前k个文档块。
  3. 生成:将原始问题和检索到的文档块一起输入到大型语言模型(LLM)中,生成最终答案。

6.2 RAG的三种形式

RAG可以分成三种形式,下图是RAG三种形式的比较:

(左)朴素RAG主要包括三个部分:索引、检索和生成。

(中)先进RAG提出了围绕预检索和后检索的多种优化策略,其过程类似于简单RAG,仍然遵循链式结构。

(右)模块化RAG继承并发展自前述范式,整体展示出更大的灵活性。其特点在于引入了多个具体的功能模块,并可以替换现有模块。整体过程不再局限于顺序的检索和生成,还包括迭代式和自适应检索等方法。

6.2.1 朴素的RAG

Naive RAG(朴素的检索增强生成模型)是最早的研究范式之一,它在 ChatGPT 被广泛采用后迅速获得了关注。Naive RAG 采用传统的 检索-生成(Retrieve-Generate)流程,主要包括三个步骤:索引、检索和生成。这一流程也被称为“检索-阅读”(Retrieve-Read)框架。

1. 索引(Indexing)

索引阶段首先是清洗和提取原始数据,这些数据通常来自不同的格式,如 PDF、HTML、Word 或 Markdown 文件,然后将其转换为统一的纯文本格式。为了适应语言模型的上下文限制,文本会被分割成较小的块(chunk)。这些文本块会使用嵌入模型(embedding model)转化为向量表示,并存储在向量数据库中。这一步对于后续检索阶段的高效相似度搜索至关重要。

2. 检索(Retrieval)

当用户提出查询时,RAG 系统使用在索引阶段相同的编码模型将查询转换为向量表示。然后,它计算查询向量与索引中每个文本块的向量之间的相似度分数。系统会优先检索与查询最相关的 Top K 个文本块,这些文本块会作为扩展上下文,供后续生成阶段使用。

3. 生成(Generation)

在生成阶段,用户提出的查询和检索到的相关文档会被组合成一个一致的提示(prompt),输入到一个大语言模型(LLM)中,任务是生成一个回应。模型生成回应的方式可以根据具体任务的要求而变化,模型可能会利用其内在的参数知识,也可以限制其回答只基于提供的文档内容。如果是多轮对话,现有的对话历史也可以被整合到提示中,以便模型能够进行多轮对话交互。

Naive RAG 的挑战和缺点

尽管 Naive RAG 有其优势,但它也存在一些显著的缺点和挑战:

1. 检索挑战

检索阶段通常面临精确度和召回率的挑战,可能会导致选择到与查询不相关或不对齐的文本块,或者无法检索到关键的有用信息。

2. 生成困难

在生成回答时,模型可能会面临 幻觉(Hallucination) 的问题,即生成的内容与检索到的上下文无关,甚至会出现生成的内容完全不准确的情况。生成的回答可能会出现无关、毒性或偏见的问题,影响回答的质量和可靠性。

3. 增强问题

将检索到的信息与不同任务进行整合时可能会遇到困难,有时会导致输出内容不连贯或不一致。检索到的信息可能存在冗余,例如从多个来源检索到类似的信息,从而导致重复的响应。此外,确定不同段落的意义和相关性,并确保输出的风格和语气一致,也是一个难点。

4. 复杂问题的处理

在面对复杂问题时,单次检索可能不足以获得足够的上下文信息。生成模型可能过于依赖检索到的增强信息,导致输出的内容仅仅是检索内容的重复,而缺乏深入的分析或综合信息。

6.2.2 增强的RAG

Advanced RAG(高级检索增强生成模型)通过引入特定的改进,旨在克服 Naive RAG 的局限性,重点提升检索质量。与朴素的 RAG 方法不同,Advanced RAG 采用了预检索(Pre-Retrieval)和后检索(Post-Retrieval)策略来优化检索过程,进一步改善了索引和检索的效率。

1. 预检索过程(Pre-Retrieval)

在预检索阶段,重点是优化索引结构和原始查询。通过提升索引的质量和优化查询,提升检索的精度和相关性。

优化索引

  • 增强数据粒度:提高数据分割的细致程度,使得每个数据块(Chuck)更具针对性,便于后续的精确检索。
  • 优化索引结构:调整数据存储和索引的方式,使其更加高效,支持快速检索。
  • 添加元数据:在索引中加入额外的信息(如时间戳、来源等元数据),提高检索时的上下文理解能力。
  • 对齐优化:确保数据之间的一致性和对齐,使得索引的构建更加精确。
  • 混合检索:结合不同的检索方法,进一步提高检索的多样性和精准性。

优化查询

  • 查询重写(Query Rewriting):通过重写用户的查询,使其更简洁、清晰,便于检索模型理解。
  • 查询转换(Query Routing):将用户的查询转换成更加结构化或易于理解的格式,以提高检索效果。
  • 查询扩展(Query Expansion):通过扩展查询的关键词,涵盖更多可能的相关信息,提高检索的全面性。

2. 后检索过程(Post-Retrieval)

在检索到相关内容后,后检索阶段的任务是将检索到的内容有效整合与用户的查询进行融合,从而生成准确的响应。

  • 重排(Re-ranking):对检索到的内容进行重排序,将最相关的文本块移至提示的边缘,以增强模型对关键内容的关注度。这个策略已经在一些框架中得到了应用,如 LlamaIndexLangChainHayStack
  • 摘要(Summary)与上下文压缩(Context Compression):提炼出关键的信息,直接将所有相关文档输入到大语言模型(LLM)中,可能会导致信息过载,使得模型难以集中注意力在关键信息上。因此,后检索阶段的重点是选择最重要的信息,强调关键部分,并压缩上下文,去除不必要的冗余内容。
  • 融合(Fusion):将各种信息融合到一起。

3. 优化策略

Advanced RAG 采用了多种优化方法,旨在提升整个检索过程的效果,特别是在检索的精确性和生成的相关性方面:

  • 增强检索质量:通过预检索和后检索策略,Advanced RAG 可以显著提高检索到的信息质量,使得生成的答案更加准确和相关。
  • 减少信息过载:后检索阶段通过重排和压缩上下文,减少了不相关信息的干扰,使得生成过程更加高效。

6.2.3 模块化的RAG

Modular RAG(模块化检索增强生成模型)在之前的 Naive RAGAdvanced RAG 基础上进一步发展,提供了更高的适应性和灵活性。它通过引入不同的模块来改进模型的各个部分,从而提高检索和处理能力。与传统的顺序处理方式不同,模块化 RAG 支持更加灵活的模块替换与配置,适应不同的任务需求。

1. 新模块(New Modules)

Modular RAG 框架引入了一些额外的专用组件,以增强其检索和处理能力。以下是一些关键的新模块:

  • Search 模块:适应特定场景,支持跨多个数据源(如搜索引擎、数据库和知识图谱)的直接检索。通过大语言模型(LLM)生成的代码和查询语言,实现对各种信息源的访问。
  • RAG Fusion 模块:解决传统检索的局限性,采用多查询策略,将用户的查询扩展为多种视角。通过并行的向量搜索和智能重排序,挖掘显式和转化性知识。
  • Memory 模块:利用 LLM 的记忆功能引导检索,创建一个无限制的记忆池。通过迭代自我增强,使文本与数据分布更加对齐,从而提高检索的准确性。
  • Routing 模块:在 RAG 系统中引导不同数据源的检索,选择最优的路径进行查询。无论是总结、特定数据库检索,还是合并多个信息流,Routing 模块都能进行灵活处理。
  • Predict 模块:通过生成上下文来减少冗余和噪音,直接通过 LLM 生成相关且准确的内容,从而提升信息的相关性和质量。
  • Task Adapter 模块:为不同的下游任务定制 RAG。通过少量示例生成任务特定的检索器,自动进行零-shot 输入的提示检索,支持更广泛的应用场景。

这些模块不仅使检索过程更加流畅,而且显著提升了检索信息的质量和相关性,适应了各种任务和查询,提供了更高的精度和灵活性。

2. 新模式(New Patterns)

Modular RAG 提供了极大的适应性,允许根据特定的挑战替换或重新配置模块。这使得 Modular RAG 超越了 Naive 和 Advanced RAG 固定结构的限制,能够根据任务需求灵活调整模块的交互流程。

  • Rewrite-Retrieve-Read 模型:利用 LLM 的能力通过重写模块和语言模型反馈机制优化查询,提升任务性能。
  • Generate-Read 模型:替代传统的检索过程,使用 LLM 生成的内容作为上下文,减少对传统检索的依赖。
  • Recite-Read 模型:强调从模型权重中检索知识,提升模型处理知识密集型任务的能力。
  • 混合检索策略(Hybrid Retrieval):综合关键字检索、语义检索和向量检索,适应多样化的查询需求。通过子查询和假设文档嵌入(HyDE),提高检索的相关性,专注于生成答案与实际文档之间的嵌入相似性。
  • 模块化模块流(Modular RAG Flow):通过 FLARE 和 Self-RAG 等技术,支持适应性检索,依据不同场景评估检索的必要性。这种灵活的架构不仅可以提高检索效率,还可以更容易地与其他技术(如微调或强化学习)进行集成。

3. 模块化 RAG 的优势

Modular RAG 提供了比 Naive 和 Advanced RAG 更加灵活的架构,能够动态调整模块交互和流向。其优点包括:

  • 灵活的模块替换:可以根据具体任务需求替换或重构模块,适应不同的应用场景。
  • 增强的信息检索能力:通过多种检索策略(如混合检索、并行检索等),提高了信息检索的精确性和全面性。
  • 自我增强和记忆功能:通过 Memory 模块,LLM 可以不断优化检索过程,提供更为精准的上下文信息。
  • 跨任务适应性:通过 Task Adapter 模块,RAG 可以根据不同的下游任务自动调整,以满足多种任务需求。

6.3 RAG与微调(Fine-Tuning)

RAG与其他模型优化方法在“是否需要外部知识”和“是否需要模型适应”方面的比较。提示工程(Prompt Engineering)对模型和外部知识的修改要求较低,主要侧重于利用大型语言模型(LLMs)本身的能力。而微调则涉及对模型的进一步训练。在RAG的早期阶段(简单RAG),对模型修改的需求较低。随着研究的进展,模块化RAG与微调技术的结合变得更加紧密。

6.4 检索(Retrieval)

RAG(检索增强生成模型)依赖外部知识来增强大语言模型(LLM)的能力,而检索源的类型和检索单元的粒度都会影响最终的生成结果。

1. 数据结构(Data Structure)

检索源的演变:最初,文本是主要的检索来源,随后扩展到半结构化数据(如PDF)和结构化数据(如知识图谱, KG)。除了从外部源进行检索外,近期的研究趋势还包括利用LLM自身生成的内容进行检索和增强。

检索单元的粒度:检索单元的粒度也会影响检索的效果。粗粒度的检索单元(如文档或句子)理论上可以提供更相关的信息,但也可能包含冗余内容,干扰下游任务。而细粒度的检索单元(如词语或短语)增加了检索的负担,且不能保证语义的完整性。选择合适的检索粒度是一种简单有效的策略,可以提升密集检索器的性能。

  • 文本中的粒度:从细粒度到粗粒度,粒度包括词语、短语、句子、命题、段落、文档等。DenseX 提出了使用命题作为检索单元的概念,命题被定义为文本中的原子表达,每个命题都封装了一个独特的事实信息,形式简洁、独立,旨在提高检索的精度和相关性。
  • 知识图谱中的粒度:在知识图谱中,检索粒度包括实体、三元组和子图等。粒度的选择也可以根据下游任务调整,如在推荐任务中检索物品ID,或者在问答任务中检索句子对等。

2. 索引优化(Indexing Optimization)

在索引阶段,文档会被处理、分段并转化为嵌入向量,存储在向量数据库中。索引的质量决定了检索阶段是否能获取到正确的上下文。

分段策略(Chunking Strategy):最常见的做法是将文档按照固定的令牌数进行分段(例如 100、256、512 等)。较大的分段能够捕捉更多上下文,但也会产生更多噪音,需要更长的处理时间和更高的成本。较小的分段可能无法完整传达必要的上下文,但噪音较少。为了解决这一问题,采用递归分割和滑动窗口的方法进行优化,使得不同的检索过程能够跨多个分段获取全局相关信息。

元数据附加(Metadata Attachments):分段可以通过附加元数据(如页码、文件名、作者、时间戳等)来丰富,从而在检索时基于元数据进行过滤,限制检索范围。元数据的不同权重可以在检索过程中实现时间感知 RAG,确保所用知识的时效性。

结构化索引(Structural Index):建立文档的层级结构可以有效提高检索效率。通过构建层级索引,RAG 系统可以快速检索和处理相关数据。知识图谱索引能够帮助保持一致性,并减少检索时的误差。此外,知识图谱还能将信息检索过程转化为 LLM 能够理解的指令,增强知识检索的精度和生成的上下文连贯性。

3. 查询优化(Query Optimization)

传统的 Naive RAG 依赖于用户原始查询进行检索,然而用户提问不够精确或清晰时,检索效果会受到影响。特别是,当查询本身很复杂,或者语言不够规范时,RAG 系统容易出现问题。

查询扩展(Query Expansion)

  • 多查询(Multi-Query):通过 LLM 进行查询扩展,将一个查询转化为多个并行查询,提供更丰富的上下文,确保生成答案的相关性。
  • 子查询(Sub-Query):将复杂的查询分解为一系列更简单的子问题,通过组合这些子查询来完整回答原始问题。这种方法类似于查询扩展,能提供更好的上下文。
  • 验证链(Chain-of-Verification,CoVe):扩展后的查询通过 LLM 进行验证,从而减少幻觉现象,提高检索结果的可靠性。

查询转化(Query Transformation)

  • 查询重写(Query Rewrite):LLM 可以重写查询,帮助生成更符合检索需求的问题。在实际应用中,像 BEQUE 就利用查询重写增强了对于长尾查询的召回效果。
  • 假设文档生成(HyDE):通过 LLM 生成假设性文档(即假设答案),在检索过程中计算查询和假设问题之间的相似度,从而缩小查询和答案之间的语义差距。
  • 退后提示(Step-back Prompting):将原始查询抽象成高层次概念问题,用于生成更有针对性的检索结果。

查询路由(Query Routing):基于查询的不同特点,路由到不同的 RAG 管道中,适应多样化的场景需求。

  • 元数据路由(Metadata Router):从查询中提取关键词(如实体),然后基于元数据进行过滤,缩小搜索范围。
  • 语义路由(Semantic Router):利用查询的语义信息进行路由,结合元数据和语义的混合路由方法,以提升查询路由效果。

4. 嵌入(Embedding)

在 RAG 系统中,通过计算查询和文档段落嵌入的相似度(例如余弦相似度)来实现检索。嵌入模型的语义表示能力在其中起着关键作用。

混合检索(Mix/Hybrid Retrieval):稀疏检索模型和密集检索模型可以互补,通过结合两者的优势,提升检索的多样性和准确性。例如,可以使用稀疏模型提供初步的搜索结果,再通过密集检索模型进行精细化检索。

微调嵌入模型(Fine-tuning Embedding Model):在某些领域,特别是在专业领域(如医疗、法律等)中,微调嵌入模型是必需的,以减少与预训练语料库的差异。通过使用 LLM 的结果作为监督信号进行微调,可以提高模型的性能。

5. 适配器(Adapter)

在微调模型时,可能会遇到一些问题,例如 API 集成或计算资源限制。因此,某些方法采用外部适配器来帮助对齐。

轻量级适配器(UPRISE):通过训练一个轻量级的提示检索器,自动从预构建的提示池中检索适合给定零-shot 任务输入的提示,从而优化 LLM 的多任务能力。

增强适配器(AAR):设计了一种通用适配器,能够适应多个下游任务,并提高在特定任务上的性能。

6.5 增强生成(Augmented Generation)

在RAG(检索增强生成)领域,标准的做法通常是先进行一次性检索,然后进行生成。这种方式可能导致效率低下,尤其对于需要多步推理的复杂问题,它提供的信息范围有限。为了解决这一问题,许多研究对检索过程进行了优化。除了最常见的单次检索,RAG还包括三种类型的检索增强过程。

(左) 迭代检索涉及在检索和生成之间交替进行,使每一步都能从知识库中获得更丰富、更有针对性的上下文。

(中)递归检索则通过逐步细化用户查询,将问题分解为子问题,然后通过检索和生成不断解决复杂问题。

(右)自适应检索侧重于使RAG系统能够自主判断是否需要外部知识检索,并决定何时停止检索和生成,通常使用LLM生成的特殊标记进行控制。

6.5.1 迭代检索(Iterative Retrieval)

迭代检索是一种基于初始查询和迄今为止生成的文本,反复检索知识库的方法,为LLM(大语言模型)提供更全面的知识基础。这种方法已被证明能够增强后续生成答案的鲁棒性,通过多次检索迭代,提供更多的上下文信息。然而,迭代检索可能会受到语义不连续性和冗余信息累积的影响。ITER-RETGEN提出了一种协同方法,将“检索增强生成”与“生成增强检索”结合起来,用于需要复现特定信息的任务。该模型利用生成的内容作为检索相关知识的上下文基础,从而在后续的迭代中生成更为精准的答案。

6.5.2 递归检索(Recursive Retrieval)

递归检索在信息检索和自然语言处理(NLP)中常用于提高搜索结果的深度和相关性。这个过程涉及基于先前搜索结果不断优化查询。递归检索旨在通过反馈循环逐渐接近最相关的信息,从而改善搜索体验。IRCoT使用了思维链(chain-of-thought)来指导检索过程,并基于获得的检索结果优化思维链。ToC则创建了一个澄清树,系统地优化查询中模糊的部分。递归检索尤其适用于复杂的搜索场景,其中用户需求从一开始就不完全明确,或者所需信息非常专业或细致。递归过程允许系统不断学习和适应用户需求,从而通常能提高搜索结果的满意度。

为了应对特定的数据场景,递归检索与多跳检索技术可以结合使用。递归检索涉及结构化索引,以分层方式处理和检索数据,这可能包括在执行检索之前对文档或长PDF进行总结。随后,基于这些摘要进行二次检索,体现了递归过程的特点。与此相对,多跳检索则旨在深入挖掘图结构数据源,提取相互关联的信息。

6.5.3 自适应检索(Adaptive Retrieval)

自适应检索方法通过允许LLM主动决定最佳的检索时机和内容,优化了RAG框架,从而提高了信息来源的效率和相关性。例如,Flare和Self-RAG就是通过这种方法来优化检索过程。随着这一趋势的发展,越来越多的LLM开始在其操作中主动做出判断,例如在模型代理(如AutoGPT、Toolformer和Graph-Toolformer)中也能看到这种趋势。Graph-Toolformer 就是将检索过程分为多个步骤,LLM主动使用检索器、应用Self-Ask技术,并采用少样本提示来发起搜索查询。这种主动的策略使得LLM能够决定何时需要检索信息,类似于代理在使用工具时的判断。

WebGPT引入了强化学习框架,训练GPT-3模型在文本生成过程中自主使用搜索引擎。它通过特殊的标记来导航这一过程,包括搜索引擎查询、浏览结果和引用参考文献,从而通过外部搜索引擎扩展GPT-3的能力。Flare则通过监控生成过程的置信度(如生成词汇的概率)来自动化检索时机,当概率低于某个阈值时,激活检索系统收集相关信息,从而优化检索周期。Self-RAG引入了“反思标记”,让模型能够自我反思其输出。这些标记有两种类型:“检索”和“批评”。模型可以自主决定何时启动检索,或者通过预设阈值触发检索过程。在检索过程中,生成器通过在多个段落中进行碎片级束搜索,得出最连贯的序列。批评分数用于更新细分分数,并且可以在推理过程中调整这些权重,从而量身定制模型的行为。Self-RAG的设计避免了额外分类器或依赖自然语言推理(NLI)模型,从而简化了何时启用检索机制的决策过程,提高了模型在生成准确回答时的自主判断能力。下图是Self-RAG的整体架构图。

6.6 RAG生态系统

综上所述,RAG生态系统如下图所示:

RAG的评价指标如下,其中包含了一些基准线(benchmark)和工具(tool)。

6.7 RAG的未来发展方向

RAG的未来发展方向包括:

  • RAG与长文本:长文本往往超出了传统模型能够处理的上下文长度。许多模型有输入长度的限制,当文本长度过长时,可能会出现截断现象。这会影响模型对全文的理解,尤其是当重要信息被截断时,系统可能无法提供完整的答案。长文本中的不同部分可能涉及不同的主题、背景或情节,如何确保检索到的信息与当前生成的内容保持一致性至关重要。
  • RAG的健壮性:RAG可能会面临检索过程中引入的噪声,例如与查询无关的文档或片段,或是检索到的文本含有误导性信息。噪声数据会影响生成结果的准确性和相关性。有时需要处理用户提出的模糊、含糊不清的查询,这些查询可能没有明确的意图或是包含多重意思。在这种情况下,RAG系统需要有效地推理和生成相关答案。
  • RAG的扩展规律(Scaling Law):随着数据集的增大,检索过程的复杂度会显著提升。需要优化检索算法和数据结构,以保持检索效率。通常,扩大检索规模可以提高生成结果的质量,但同时也可能增加不相关信息的干扰。
  • 生产级RAG:指已经优化并可以在实际环境中稳定运行的RAG系统。这类系统不仅要求具有高效的检索和生成能力,还需要具备可扩展性、低延迟和高可靠性等特点。
  • 混合方法:混合方法是指将多种不同的技术或模型结合起来,以优化RAG系统的性能。常见的混合方法包括将稀疏检索(例如BM25)与密集检索(例如BERT架构)结合,或者将规则驱动的系统与深度学习模型结合使用。
  • 多模态的RAG:图片、音频、视频、代码等作为知识库和信息输入也是存在着一定的挑战。

7.  参考资料

  1. Gao Y, Xiong Y, Gao X, et al. Retrieval-augmented generation for large language models: A survey[J]. arXiv preprint arXiv:2312.10997, 2023, 2.
  2. Gao Y, Xiong Y, Zhong Y, et al. Synergizing RAG and Reasoning: A Systematic Review[J]. arXiv preprint arXiv:2504.15909, 2025.
  3. Li X, Jia P, Xu D, et al. A Survey of Personalization: From RAG to Agent[J]. arXiv preprint arXiv:2504.10147, 2025.
  4. Arslan M, Ghanem H, Munawar S, et al. A Survey on RAG with LLMs[J]. Procedia Computer Science, 2024, 246: 3781-3790.
  5. Fan, Wenqi, et al. “A survey on rag meeting llms: Towards retrieval-augmented large language models.” Proceedings of the 30th ACM SIGKDD Conference on Knowledge Discovery and Data Mining. 2024.

GPT4All:本地部署的开源大语言模型

1.  GPT4All简介

1.1 开源项目

GPT4All 是由 Nomic AI 开发的一个开源项目,旨在让用户能够在个人设备上本地运行大型语言模型(LLM),无需依赖云服务。 这一项目自发布以来,已成为 GitHub 上增长最快的开源项目之一,拥有超过 7 万个 GitHub 星标。

1.2 适用场景

使用GPT4All的话有以下优势:

  • 隐私保护:处理敏感数据时,确保信息不外泄。
  • 离线使用:在没有网络连接的环境中使用 AI。
  • 教育与研究:用于教学、研究或学习目的。
  • 定制化需求:根据特定需求定制 AI 模型。

2.  核心特点

2.1. 完全本地运行,无需互联网连接

GPT4All 允许用户在 Windows、macOS 和 Linux 等操作系统上本地运行 LLM。 用户可以下载模型文件(通常为 1GB 至 8GB),并在没有网络连接的情况下使用 AI 聊天。

2.2 支持多种硬件平台

该项目支持多种硬件平台,包括支持 AVX 指令集的 CPU,以及 Apple M 系列芯片、AMD 和 NVIDIA GPU 等。 这使得用户能够在不同的设备上体验本地 LLM。

2.3 隐私优先

GPT4All 强调数据隐私,默认情况下,用户的对话数据不会离开本地设备。 如果用户选择使用远程模型或参与数据共享,系统会明确提示并征得同意。

2.4 丰富的模型支持

GPT4All 支持多种开源模型,包括 LLaMa、Mistral、DeepSeek R1、Nous-Hermes 等。 用户可以根据需求选择不同的模型进行本地部署。详情可以参考链接:https://github.com/nomic-ai/gpt4all/blob/main/gpt4all-chat/metadata/models3.json

2.5 集成本地文档支持

GPT4All 提供 LocalDocs 功能,允许用户将本地文档(如 PDF、TXT、Markdown 等)导入系统,与 AI 进行交互。 这对于处理敏感或私密信息非常有用。

3.  快速上手指南

3.1 下载并安装软件

访问下载适用于您操作系统(Windows、Mac、Linux)的安装包。

3.2 添加模型

启动应用程序后,点击“+ Add Model”按钮,选择并下载您需要的模型。

3.3 开始聊天

下载模型后,进入“Chats”界面,选择已加载的模型,开始与 AI 进行对话。并且还提供上传本地文件资料的功能,实现知识库的搜索。

3.4 使用Python的SDK

3.4.1 大语言模型

GPT4All 提供了 Python SDK,方便开发者将其集成到自己的项目中。 此外,项目采用 MIT 开源许可证,允许用户进行自定义和二次开发。

安装方法:

pip install gpt4all

使用方法:

可以按照官方提供的模板进行使用,如果模型没有提前下载的话,在第一次使用的时候,代码会自动下载模型。

from gpt4all import GPT4All
model = GPT4All("Meta-Llama-3-8B-Instruct.Q4_0.gguf") # downloads / loads a 4.66GB LLM
with model.chat_session():
    print(model.generate("How can I run LLMs efficiently on my laptop?", max_tokens=1024))

如果想要进行流式输出或者一次性输出,可以使用streaming这个参数进行控制,参考代码:

from gpt4all import GPT4All

def output_with_stream_control(prompt: str, model_name: str = "Meta-Llama-3-8B-Instruct.Q4_0.gguf", max_tokens: int = 1024, streaming: bool = False):
    model = GPT4All(model_name)  # 加载指定模型

    # 创建一个对话会话
    with model.chat_session() as session:
        response_buffer = ""

        if streaming:
            # 启用流式输出
            for chunk in model.generate(prompt, max_tokens=max_tokens, streaming=streaming):
                response_buffer += chunk
                print(chunk, end='', flush=True)  # 实时输出生成的文本
            print("\n\n生成的完整答案:", response_buffer)
        else:
            # 批量输出(等待完整生成后返回)
            response_buffer = model.generate(prompt, max_tokens=max_tokens, streaming=streaming)
            print("\n生成的完整答案:", response_buffer)

        return response_buffer

if __name__ == "__main__":
    prompt = "用中文回答,什么是化学?"
    result = output_with_stream_control(prompt, streaming=False)
    print('result:', result)

模型的选择范围很多,当前支持的部分模型可以参考表格:

GPT4All model nameFilesizeRAM RequiredParametersQuantizationDeveloperLicenseMD5 Sum (Unique Hash)
Meta-Llama-3-8B-Instruct.Q4_0.gguf4.66 GB8 GB8 Billionq4_0MetaLlama 3 Licensec87ad09e1e4c8f9c35a5fcef52b6f1c9
Nous-Hermes-2-Mistral-7B-DPO.Q4_0.gguf4.11 GB8 GB7 Billionq4_0Mistral & Nous ResearchApache 2.0Coa5f6b4eabd3992da4d7fb7f020f921eb
Phi-3-mini-4k-instruct.Q4_0.gguf2.18 GB4 GB3.8 billionq4_0MicrosoftMITf8347badde9bfc2efbe89124d78ddaf5
orca-mini-3b-gguf2-q4_0.gguf1.98 GB4 GB3 billionq4_0MicrosoftCC-BY-NC-SA-4.00e769317b90ac30d6e09486d61fefa26
gpt4all-13b-snoozy-q4_0.gguf7.37 GB16 GB13 billionq4_0Nomic AIGPL40388eb2f8d16bb5d08c96fdfaac6b2c

同时,SDK的所有参数可以参考链接:https://docs.gpt4all.io/gpt4all_python/ref.html#gpt4all.gpt4all.GPT4All.list_models

3.4.2 嵌入模型

除了大语言模型之外,它还提供三种嵌入模型,其本地调用的使用案例如下所示:

from nomic import embed
embeddings = embed.text(["String 1", "String 2"], inference_mode="local")['embeddings']
print("Number of embeddings created:", len(embeddings))
print("Number of dimensions per embedding:", len(embeddings[0]))

其嵌入模型有三个:

NameUsing with nomicEmbed4All model nameContext LengthEmbedding DimensionsFile Size
Nomic Embed v1embed.text(strings, model=”nomic-embed-text-v1″, inference_mode=”local”)Embed4All(“nomic-embed-text-v1.f16.gguf”)2048768262 MiB
Nomic Embed v1.5embed.text(strings, model=”nomic-embed-text-v1.5″, inference_mode=”local”)Embed4All(“nomic-embed-text-v1.5.f16.gguf”)204864-768262 MiB
SBertn/aEmbed4All(“all-MiniLM-L6-v2.gguf2.f16.gguf”)51238444 MiB

4.  参考资料:

  1. GPT4All的GitHub地址:https://github.com/nomic-ai/gpt4all
  2. GPT4All的文档:https://docs.gpt4all.io/
  3. nomic的官网:https://www.nomic.ai/
  4. 模型的选择范围:https://github.com/nomic-ai/gpt4all/blob/main/gpt4all-chat/metadata/models3.json

让工作充满热爱:如何通过目标感激发员工潜能

对于每一个打工人而言,目标感在职场中的重要性不可忽视,它不仅是打工人动力的源泉,更能激发打工人源源不断的创造力。对于企业而言,重视并提升员工的目标感,针对不同的员工设计不同的目标,让员工从工作本身找到热爱与归属,将企业的目标和员工的目标尽量地放在同一条轨道上。只有当员工对自己的工作充满热情,感知到个人目标与企业愿景的紧密契合,他们才会全身心投入其中,持续创新并不断突破自我。目标感激发了员工的主动性和创造力,促进了工作效率的提升,并加强了对企业的忠诚度,这对于任何希望长期发展并维持竞争力的组织来说,都是至关重要的。

在当今快速发展的职场中,企业需要的已不仅仅是完成任务的工人,而是能够创造价值、推动创新的创造型人才。创造型工作强调的是员工的思维能力、问题解决能力和创新意识,而不仅仅是简单的重复劳动。企业应当通过提供能够激发员工创造力的工作内容和环境,吸引那些有志于实现自我价值的优秀人才。通过这样的方式,企业不仅能够招募到技术娴熟的执行者,更能吸引到具有独立思考和创新精神的战略性人才,这些人才将推动公司持续发展并在长期竞争中脱颖而出。

对于企业而言,吸引并留住优秀人才是每个企业都面临的挑战。为了做到这一点,除了在招聘的时候,尽可能地争取各种各样的优秀人才之外,在日常的管理中企业的管理者也需要按照既定的目标分解任务,并以员工对工作内容本身的热爱为核心出发点,尽可能地给员工安排其喜欢的工作内容。同时,管理者可以通过定期与员工交流,帮助他们发现或唤醒内在的目标感,从而提升他们的工作积极性和忠诚度。以下是管理者可以询问员工的五个关键问题,它们能够帮助员工找回对工作的热情,激发他们的潜能。

1. 你擅长做什么工作?

作为管理者,第一步是帮助员工认识到自己的强项,尤其是应届生和刚入职公司没多久的员工。管理者可以通过提问:“你擅长做什么工作?”“在同样的工作量下,哪些工作你花费的精力较少?”可以帮助员工时刻进行自我审视,并在日常繁重的工作中找到自己的优势所在。这两个问题不仅能够让员工思考自身的核心能力,还能帮助他们意识到自己在团队中的独特价值,从而激发他们更积极地发挥这些优势。

2. 你喜欢做什么工作?

每个人都希望做自己热爱的工作,毕竟兴趣是最好的老师。管理者可以通过询问员工:“你喜欢做什么工作?”“在正常的工作日,你最期待做哪些任务?”来帮助员工发现他们的工作激情。在企业中,工作不应该仅仅是任务的堆砌,它还应当是员工内心充满动力和喜悦的源泉。当员工能够做自己喜欢的工作时,他们不仅能提高效率,还会感受到工作带来的满足感。

3. 什么类型的工作让你感到最有价值?

对于每个员工来说,虽然大部分人工作的目的是为了生计,但我想更高的层次是为了实现个人价值和职业目标。管理者还可以问员工:“在过去的一段时间里,哪些工作成果让你感到最为自豪?”“你完成了哪些对团队或组织至关重要的任务?”管理者可以帮助员工识别他们的工作对组织的重要性,甚至可以把更重要的工作安排给合适的员工。这些问题能够让员工看到他们工作的内在价值,并激发他们为更高目标而努力的动力。

4. 是什么给了你前进的动力?

每个人在工作中都有一个驱动力,管理者可以通过“你学到了哪些将来会用到的技能?”“你今天所做的工作是否让你更接近自己的愿望?”等问题,帮助员工发现自己的前进方向。工作不仅是为了眼前的任务,它还是员工通往未来目标的桥梁。通过明确自己的目标,员工将更加清晰地看到自己努力的方向和动力来源,从而更有动力去追求更高的成就。

5. 你如何与同事相处?

团队协作是现代职场中不可或缺的一部分。管理者可以通过提问:“你与哪些同事关系最适合?”“如果整个办公室的同事都是你喜欢的人,场景会是怎样的?”来帮助员工思考如何与同事建立更好的人际关系。工作中良好的合作氛围不仅能增强团队的凝聚力,还能让员工感到他们在工作中找到了归属感,从而增强工作的意义感。

结语

通过这五个简单而深刻的问题,管理者能够帮助员工更清晰地认识自己、发现自己的热情,进而激发他们的内在目标感。当员工能够在工作中找到自己的价值与意义时,他们不仅能为企业创造更大的价值,也能够在职业生涯中获得更多的满足与成就。为了吸引和留住优秀人才,重新设计工作本身,让员工找到对工作的热爱,将是成功的关键所在。

给的很少,要的很多:职场中的奇怪要求

在职场上,有的时候会出现一种奇怪的现象,正在悄无声息地消耗着人的价值。

在招聘的时候,岗位的职责和内容明明写的是“算法工程师”,但是在候选人入职之后却要背负起后端开发、前端搭建、数据分析、测试开发,甚至是各种边边角角的杂活。对于一名算法工程师而言,不仅要做会议记录,要做服务器维护,连日常的excel数据报表也得一个个出,还有想象不到的各种各样项目对接、繁重的流程和技术文档撰写、流程混乱的跨部门沟通,这些已经统统被塞进算法工程师的日常待办里。最讽刺的是,当这些杂乱无章的任务终于在一片疲惫中堆叠完成时,管理者却开始反问算法工程师:“你怎么在算法上没有成果?怎么AI项目还没有突破?还不能够让AI做到减少人力和减轻负担的效果?”

在这种岗位上,一个典型的算法工程师,明明是在专攻机器学习、深度学习这些复杂课题的技术人才,结果突然变身为项目经理,跨部门沟通小能手,后端开发大神,前端布局专家,甚至还得做数据清洗、做测试开发,和测试人员一起深夜守在业务旁边死磕。唯一的共同点是——每个任务都没有时间给你真正专注做。于是,身为一位“全能”的技术人才,他被要求同时兼顾这些不同领域的工作,连各种各样的日报、周报、双周报、月报、季度报、半年报和年报都得自己来。反而最需要投入深度的算法研究,被推到了“闲暇时间”的角落,长期等着“有空再做”的状态。

对于某些公司而言,算法的突破,仿佛是在碎片化劳动、疲于奔命中,凭空诞生的奇迹。仿佛一个工程师,只要加班熬夜、不断堆工时,就能自动产出深度学习模型,就能轻松攻克科研课题。仿佛一个工程师,只需要在睡梦中做梦,就能够在梦中实现AI的算法开发达成意想不到算法效果

AI算法开发是需要一定的创新能力的,可真正需要产出创新的岗位,需要的是什么?是深度的思考,是高密度的专注,是反复试错和沉淀,而不是在每天数十个小任务中疲于奔命,不是把注意力分成无数碎片,不是在无休止的救火和打杂中消磨殆尽。简单来说就是给得太少:这里给得太少并不是指工资给得很少,而是管理者不给时间,不给专注的空间,不给明确的边界感。同时,管理者又对算法工程师要得太多:要你全能,要你无所不能,要你在一片杂乱中还能天才地爆发,在服务器都少之又少的前提下还希望有巨大的产出。这本质上,不是对个人的挑战,而是对职业角色的深度误解。

如果管理者希望算法工程师承担起整个产品的研发工作,那不如直接把“全能型人才”的名字印在招聘广告上,标明“招聘全能型工程师”,这样或许更合适——这样的候选人他不仅需要做算法,还得做产品设计,做架构开发,做项目经理,做前后端开发,做数据分析,做项目管理,成为PPT和EXCEL工程师,甚至还要为公司的整体战略和布局负责。

到最后让人不解的是,虽然管理者已经把很多额外的职责都压给他,最终却仍然对他没有任何宽容,反而把对AI成果的期望推得越来越高——“做出AI突破”、“产出创新”,“行业领先”、甚至希望“超越竞争对手”。这一切,似乎都没有考虑到他的时间和精力早已被无限分配。在忙碌完各种需求之后,AI终于有了一定的产出,但是更加让人无奈的是,管理者却又说“AI只是锦上添花,项目交付才是雪中送炭”。真正让人气愤的是,往往这样的要求背后,管理层只会关注短期内的“完成情况”,而忽略了创新和技术突破背后需要长时间的专注和积累。却不见他们提出过“给你更多的资源”、“让你专注做技术”的方案。创新需要土壤,而不是不间断的碎片时间和加班文化

在工作中,每个角色的价值,都是需要被尊重的。让算法工程师做后端、前端、测试、运维,是对专业的稀释;让创意型工作在碎片中挣扎,是对产出的扼杀。当一个岗位需要承担四五个岗位的职责时,其实早已失去了基本的职业尊重。当一个组织习惯于压榨式使用人才时,它正在透支的不仅是人的体力,更是创新力、责任感和未来的可持续发展力。短期看,似乎解决了燃眉之急;但长期看,最宝贵的人才,只会在沉默和疲惫中,悄悄流失。或许对于某些公司而言,招聘的目的并不是提升自身的技术实力,而是在海量招聘中筛选到某些合适的人并长期留用,其他不合适的人只需要及时离开就可以了。

真正成熟的组织,懂得给角色留空间,让专业的人做专业的事,不要让各种各样的杂事拉打扰专业的人。管理者需要懂得设定合理预期,让创新建立在专注、探索和持续打磨之上,而不是建立在无尽打杂之中。想要算法上的突破,就要在管理上先突破短视;想要技术上的飞跃,就要在制度上先尊重专注。别再让“给的很少,要的很多”成为职场的常态。别再让真正有创造力的人,在无意义的疲惫里,变成一颗颗沉默的螺丝钉。

一个合格的企业应该懂得角色的专业性和深度,懂得为创新提供足够的时间和空间,而不是一味要求员工成为“全能神”。真正有眼光的领导,应该知道,技术和创新需要一颗宁静的心,需要日复一日的专注,而不是在千头万绪的琐事中迷失自我。别再让这种“给得很少,要的很多”的荒谬逻辑,成了职场中唯一的标准。让每个岗位都能专注于自己的本职工作,才能创造出真正的价值,才是每个企业应追求的目标。

比技术更难进化的,是人的思维方式

每一段职场故事,都是一面镜子。有人走在前面,有人停在原地,但真正值得敬佩的,往往是那些能够不断进化的人。

曾经,有这样一位技术伙伴。他在一家公司独当一面,凭着过硬的动手能力和坚持不懈的努力,独立搭建起了一套完整且实用的系统。从第一行代码到第一版上线,以及后面的持续迭代工作,他几乎亲历亲为,夜以继日,撑起了一片属于自己的天地,为公司的业务也做到了雪中送炭。

在很长一段时间里,他被视为团队的支柱。后面来了几位新人,他们也怀着敬意向他学习,他的经验成为解决问题的重要凭借,他的方案成为评估技术选型的模板。那段日子,他像一位孤独的工匠,在属于自己的城堡里,雕刻着精致而独特的艺术品。

但时代不会停下来等任何一个人。

后来,随着团队不断扩张,越来越多的社招与校招的新同事加入。他们有着完全不一样的科研和工作背景,他们为团队带来了新的力量、新的想法、新的工具、新的模式。新的风在逐渐吹拂进来,对团队而言带着未知的机会,也带着隐隐的不安。

当有新的同事提出换一种更高效的方式来管理数据,他皱了皱眉头;当有人建议重新设计系统架构以支持未来更大规模的扩展,他下意识地进行反驳;当有人分享外部更先进的工具链时,他则质疑其开源的使用范围、安全性与可控性,并会说“没想到外部的工具竟然那么 low”。渐渐地,他和新同事们之间的讨论不再是协作,而是争论,甚至演变成了角力。

他想尽一切办法守护着自己曾经创造的成果,维护着自己创造的技术栈,就像守护一座渐渐老去的城池。

这段故事里,没有真正的对与错。只是,它让人深刻意识到:比代码更难维护的,是人的认知系统;比技术更容易过时的,是人的思维方式。

所有曾经的光荣和努力,都值得尊重。但如果一个人始终以“我做过”来定义自己的价值,很容易在变化面前筑起一道又一道无形的高墙。时间久了,高墙之内,是自我保护,也是自我设限。

成长,不是抵抗变化,而是接纳变化,驾驭变化。

很多时候,我们以为自己是在守护成果,其实不过是在固守过往的安全感。对变化的排斥,不一定源自傲慢,更多时候,源自恐惧——害怕自己的价值被动摇,害怕新的世界自己跟不上,害怕多年积累的一切被证明“不再先进”,害怕自己不再是团队唯一的核心力量。

于是,怀疑代替了好奇,防御取代了探索,争论遮蔽了倾听。

我们常常低估了自己对稳定的依赖,也低估了世界变化的速度。
技术在飞奔,行业在更迭,每一个曾经自豪的“我做过”,如果无法继续演变成“我们一起做得更好”,就会在不知不觉中,被时代轻轻擦肩而过。真正的危机,并不是新技术到来,也不是新同事提出了不同的方案。真正的危机,是当我们面对变化时,心中只剩下防备和抵触,而没有了好奇与学习的冲动。

思维停滞,比技术落后更可怕。
认知固化,比工具过时更致命。

而且,一个人如果长时间沉浸在“我是功臣”的自我叙事里,就很容易走向两个极端:

  1. 一是,把团队视作威胁,拒绝与其他同事进行分享和共建;
  2. 二是,把规范与体系视作束缚,维护自己开发的所有内容,只愿做自己的孤岛。

但真正长远的事业,真正了不起的团队,永远是靠不断引入新力量,不断自我更新,才能生生不息。有时候,旧有的功臣确实需要做出让步。但这种让步,不是丢掉了自己的价值,而是把自己的价值,升华到了成就更大的整体之中。

反过来说,作为新加入的人,我们也应该有足够的耐心和尊重。理解曾经构建体系的人并不容易,尊重他们的经验和贡献,用行动而不是语言赢得信任,用协作而不是颠覆建立连接。

成长,从来不只是单向的要求。不仅要求自己打开心扉,也要求自己包容别人;既要有挑战旧世界的勇气,也要有修复彼此信任的耐性。

所以,从今天开始,我们可以问问自己:

  • 我是不是还在用“我做过”的故事,替代“我还能做得更好”的探索?
  • 我是不是已经开始本能地抗拒新鲜的事物?
  • 我是不是因为害怕失去过去的成就感,而放弃了拥抱新的成长?

如果答案是肯定的,请不要自责。成长,从来不是一蹴而就的觉醒,而是一次次微小但坚定的自我修正。真正成熟的人,不是守着旧地图固步自封的人,而是能在风起云涌中,不断校准航向,继续出发的人。

愿我们以此为镜:

  • 开放代替封闭,像海绵一样,吸收新的技术、新的思路;
  • 谦虚战胜傲慢,承认世界之大,技术之广,永远有人值得学习;
  • 长期主义压倒短期功利,把眼光放远,把心气放平,把每一次小小的进步积累成未来的跃迁。

别让一时的成就,变成了自我封闭的借口。别让一段历史的光环,变成了前行路上的绊脚石。真正了不起的人,不是站在过去荣誉里的人,而是能在每一次技术更迭、每一次认知崩塌后,依然选择重新学习、重新奔跑的人。要记住:

最值得骄傲的,不是你写过的某一段代码,而是你不断修复、不断优化、不断重构的人生本身。

未来属于那些不断进化的人,愿你我都是那个可以持续升级的自己。

Python代码检测工具

代码规范

对于程序员而言,代码规范不仅仅是为了让代码看起来更整洁,它直接影响着代码的可读性、可维护性和团队的协作效率。统一的代码风格使得团队成员能够快速理解彼此的代码,无论是在日常的开发、代码审查还是修复bug时,都能有效避免因风格差异带来的误解或错误。遵循代码规范还能帮助提高代码质量,降低潜在的bug风险,并且对后期的扩展与重构更加友好。尤其是在大型项目或多团队协作的情况下,良好的代码规范更是保证项目可持续发展的基石。因此,始终坚持良好的代码规范是每个开发者应尽的责任,它不仅仅是为了提升个人编程习惯,更是为了整个团队的协同作战与代码的长期健康。

Python代码规范

Python 提倡简洁、清晰、易读的代码风格,PEP 8 是 Python 社区推荐的官方代码风格指南,它帮助开发者统一代码风格,提高代码的可读性和可维护性。遵循 Python 代码规范不仅有助于开发者之间的协作,还能让代码更加规范化,减少潜在的错误。以下是一些常见的 Python 代码规范。

1. 命名规范

  • 变量、函数和方法的命名:使用小写字母,并通过下划线 _ 分隔单词(即蛇形命名法)。例如:user_age,calculate_total()
  • 类名的命名:使用首字母大写的驼峰命名法。例如:UserProfile,OrderProcessor
  • 常量命名:所有字母大写,单词间使用下划线分隔。例如:MAX_RETRIES,PI
  • 私有变量和方法:以单下划线 _ 开头,表示该变量或方法是内部使用,不应直接访问。例如:_internal_data
  • 避免使用Python保留字(如 class、if、try 等)作为变量名。

2. 缩进与空格

  • 缩进:使用 4 个空格进行缩进,不要使用制表符(Tab)。这是 Python 语法要求的,错误的缩进会导致语法错误。
  • 行内空格:在运算符两边加空格,增强可读性。
    例如:对于赋值:x = 10
    对于运算符:y = x + 5
  • 函数参数的空格:函数定义和调用时,参数列表的两边不要加空格。例如:
def add_numbers(a, b):    
    return a + b
  • 括号内的空格:不要在括号内多余的地方加空格。例如:
my_list = [1, 2, 3]  # 正确
my_list = [ 1, 2, 3 ]  # 错误

3. 行长限制

单行长度:每行代码的长度建议不超过 79 个字符。对于文档字符串(docstring)和长注释,推荐不超过 72 个字符。这有助于提高代码的可读性,尤其是在显示设备宽度有限时。如果行长超过限制,可以使用反斜杠 \ 进行换行,或者在括号、列表、字典等容器中自动换行。

4. 文档字符串(Docstring)

模块和类:在模块和类定义后,添加文档字符串说明其功能。文档字符串应该简洁明了,并且应说明类和模块的主要功能和用途。

class Calculator:    
    """This class performs basic arithmetic operations."""    
    pass
  • 函数和方法:为每个函数和方法提供文档字符串,描述其作用、参数和返回值。
def add(a, b):
    """
    Add two numbers and return the result.
    
    Parameters:
    a (int or float): The first number.
    b (int or float): The second number.
    
    Returns:
    int or float: The sum of a and b.
    """
    return a + b

5. 异常处理

异常捕获:应该尽量避免使用过于宽泛的 except 块,避免捕获不必要的异常。应当明确捕获特定异常。

try:
    x = 1 / 0
except ZeroDivisionError as e:
    print(f"Error: {e}")

多个异常捕获:如果需要捕获多种异常,可以使用元组来列出这些异常类型。

try:
    some_code()
except (TypeError, ValueError) as e:
    print(f"Error: {e}")

6. 导入顺序

标准库导入:首先导入 Python 标准库模块,如 os、sys 等。

第三方库导入:其次导入外部安装的第三方库,例如 numpy、pandas、requests 等。

本地应用库导入:最后导入你自己编写的模块或应用库。

按照以上顺序,导入部分每一类模块之间应该留一行空行。例如:

import os
import sys

import numpy as np
import pandas as pd

from mymodule import my_function

7. 避免重复代码

Python 提供了许多库和工具,可以避免代码重复。如果发现自己写了类似的代码片段多次,应考虑将其提取成函数或类,提升代码的复用性。适当使用 Python 的标准库,如 itertools、functools 等,避免自己手动实现复杂的功能。

遵循 Python 代码规范能够帮助我们编写更简洁、更易于理解和维护的代码。最重要的规范包括命名规则、缩进与空格、行长限制、文档字符串、异常处理等。在大型项目中,团队成员遵循统一的规范可以提高协作效率,减少因代码风格不一致带来的混乱和错误。因此,开发者应该积极遵循 PEP 8 等官方规范,并利用代码规范检查工具(如 flake8、pylint 等)来保持代码质量。

圈复杂度

圈复杂度(Cyclomatic Complexity)是衡量一个程序的控制流复杂度的一个指标,它由 Thomas McCabe 于 1976 年提出。圈复杂度的核心思想是衡量程序中独立路径的数量,反映了程序中控制流的复杂程度。简单来说,圈复杂度可以帮助你了解一个程序有多少条不同的执行路径。

为什么圈复杂度重要?

  • 高圈复杂度:意味着代码中有很多的判断、循环和分支,程序的执行路径复杂。高复杂度的代码难以理解、测试和维护。
  • 低圈复杂度:意味着代码结构简单,控制流清晰,容易理解和维护。

计算圈复杂度

圈复杂度的计算公式为:

V(G)=E−N+2P,其中:

  • V(G) 是圈复杂度(Cyclomatic Complexity)。
  • E 是程序图中的边的数量(边代表程序控制流的转移,比如跳转、条件等)。
  • N 是程序图中的节点的数量(节点代表基本块,即一组顺序执行的语句)。
  • P 是程序图中的连通组件的数量(一般情况下 P = 1,即程序是一个连通的整体)。

具体解释:

E:程序的控制流转移数量。例如,if、while、for、case 语句的数量都会增加边的数量。

N:控制流图中节点的数量,代表代码的块,例如顺序执行的语句组。

P:通常程序只有一个连通组件,即 P = 1,代表程序是一个整体。

直观解释

可以通过 控制流图 来理解圈复杂度。控制流图是一个图论的概念,它将程序的每个基本块(例如条件判断、循环等)表示为图中的节点,程序的控制流(跳转)表示为边。圈复杂度就是计算该图中所有独立路径的数量。

例如,下面是一个简单的代码示例:

def example(a):
    if a > 10:
        return "greater"
    else:
        return "lesser"

这段代码的控制流图非常简单,只有两个分支。它的圈复杂度为 2,因为有两个独立的路径(a > 10 和 a <= 10)。

计算圈复杂度的示例:

  1. 简单顺序执行
def simple_function():
    a = 5
    b = 10
    c = a + b
    return c
  • 控制流图:只有一个顺序的执行,没有条件和分支。
  • 圈复杂度:1(只有一个路径,程序从头到尾顺序执行)
  • 条件判断
def function_with_if(a):
    if a > 10:
        return "greater"
    else:
        return "lesser"

控制流图:有一个 if 语句,形成两个分支路径。圈复杂度:2(一个条件判断,两个路径)

  • 循环语句
def function_with_while(a):
    while a > 0:
        a -= 1
    return a

控制流图:有一个 while 循环,形成一个循环路径。

圈复杂度:2(一个循环结构,两个路径:一个是 while 循环路径,另一个是跳出循环后的路径)

如何使用圈复杂度?

  1. 代码可维护性:高圈复杂度意味着代码结构复杂,容易引入 bug,不利于维护。因此,圈复杂度高的代码通常需要重构。
  2. 测试覆盖率:圈复杂度的一个重要应用是 测试路径覆盖,它提供了最小路径集 的数量,这些路径集需要被单元测试覆盖。如果圈复杂度是 10,那么最少需要设计 10 个不同的测试用例来保证所有路径都被测试。
  3. 代码审查和重构:高圈复杂度通常提示代码不易理解或过于复杂,可能需要重构,降低复杂度,提高可读性。

小结:

  • 低圈复杂度:代码清晰,易于理解和维护,测试更容易覆盖。
  • 高圈复杂度:代码难以理解和测试,容易出错,可能需要重构。

圈复杂度是衡量代码复杂度的重要指标,它能帮助开发者评估代码的质量和可维护性。

Python代码检测工具使用指南

本文介绍多种常用的Python代码检测工具(pylint、flake8、ruff),涵盖安装方法基本使用以及项目级检查的实践指导,帮助开发者快速实现代码质量分析与规范检查。

1. Pylint

1.1 安装

使用pip就可以轻松地把pylint这个工具安装好。

pip install pylint

1.2 使用场景

检查单个文件

pylint my_script.py # 检查单个文件

检查文件夹

pylint src/  # 递归检查目录下所有.py文件

检查项目

pylint project/ --recursive=y # 检查项目

1.3 配置与过滤

生成配置文件:

pylint --generate-rcfile > .pylintrc

如果不想看某类错误的时候,我们可以选择忽略特定错误:

pylint my_script.py --disable=E1101,C0114  # 关闭未解析的属性和缺失docstring警告

2. Flake8

2.1 安装

使用pip就可以轻松地把flake8这个工具安装好。

pip install flake8

2.2 使用场景

检查单个文件

flake8 my_script.py  # 检查单个文件

检查文件夹

flake8 src/  # 检查所有.py文件

检查项目

可以通过下述命令来检查当前的目录和所有子目录

flake8 .  # 递归检查当前目录及子目录

同时,flake8默认会使用pep8第三方包检查代码(经常会安装mccabe和pyflakes,安装之后,flake8就会提供个性的功能)。 pep8第三方包只能检查代码是否符合 pep8 代码规范(所以 flake8默认是使用pep8代码规范做检查)。

相对于Pylint ,flake8提供了些特有的功能。

  • 检查代码的圈复杂度(flake8会调用mccabe计算圈复杂度)。
  • 圈复杂度和if语句有关,选择分支越多,圈复杂度越高。
  • 圈复杂度越低越好。圈复杂度高影响代码可读性,代码容易出错。
  • flake8官网建议圈复杂不要超过 12 。

2.3 配置与扩展

配置文件支持:在 setup.cfg 或 .flake8 中配置规则:

pip install flake8-mutable  # 安装可变默认参数检测插件flake8 --enable-extensions MutableDefaultArg

3. Ruff

3.1 安装

使用pip就可以轻松地把ruff这个工具安装好。

pip install ruff
# 或使用独立二进制(无Python环境依赖):
curl -Ls https://github.com/astral-sh/ruff/releases/latest/download/ruff-linux-amd64 | sudo tee /usr/local/bin/ruff >/dev/null && sudo chmod +x /usr/local/bin/ruff

3.2 使用场景

检查单个文件

ruff check my_script.py

检查文件夹/项目

ruff check src/  # 检查目录ruff check .     # 检查整个项目

自动修复问题

ruff check --fix my_script.py

3.3 配置

兼容flake8配置:直接复用 .flake8 或 pyproject.toml,或在 pyproject.toml 中指定规则:[tool.ruff] line-length = 100 ignore = [“E501”, “F401”]

4.  Mccabe

这是用来检查圈复杂度的工具

4.1 安装

pip install mccabe
pip install --upgrade mccabe
pip uninstall mccabe

4.2 使用场景

python -m mccabe --min 5 mccabe.py
("185:1: 'PathGraphingAstVisitor.visitIf'", 5)
("71:1: 'PathGraph.to_dot'", 5)
("245:1: 'McCabeChecker.run'", 5)
("283:1: 'main'", 7)
("203:1: 'PathGraphingAstVisitor.visitTryExcept'", 5)
("257:1: 'get_code_complexity'", 5)

5.  Prospector

5.1 Prospector项目介绍

Prospector 是一款专为 Python 代码设计的强大分析工具,它旨在提供关于错误、潜在问题、规范违规以及复杂性方面的详尽信息。这款工具集成了诸如 Pylint、pycodestyle 和 McCabe 等众多Python代码分析工具的功能于一身。通过自定义配置文件(即“profile”),Prospector 提供了适用于大多数情况的默认配置,旨在帮助开发者在无需大量前期设置的情况下即可开始提升代码质量。它还能够适应项目所依赖的特定库和框架,比如自动调整对 Django 或 Celery 的支持,以减少误报。

5.2 项目快速启动

要迅速开始使用 Prospector,首先确保你的环境中安装了 Python 和 pip。然后,执行以下命令来安装 Prospector:

pip install prospector

安装完毕后,在你的Python项目根目录下运行 Prospector,即可获取到代码审查报告:

cd /path/to/your/python/projectprospector

这将输出可能存在的问题列表,帮助你识别和修正代码中的隐患。对于更定制化的控制,可以添加额外参数,例如使用 –strictness medium 来设定中等严格的检查级别。

prospector --strictness high

5.3 应用案例和最佳实践

在使用 Prospector 时,一个典型的最佳实践是将其集成到持续集成(CI)流程中。比如,通过 .pre-commit-config.yaml 文件配置预提交钩子,确保每次提交前都经过代码质量检查:

repos:
  - repo: https://github.com/PyCQA/prospector
    rev: 1.10.0  # 使用具体版本或'master'以获取最新版本
    hooks:
      - id: prospector
        args: ["--summary-only"]  # 只显示总结,简化输出

对于团队协作项目,通过创建适合自己团队编码风格的配置文件(prospector.yml),可以进一步优化Prospector的行为,确保所有开发者遵循一致的标准。

5.4 典型生态项目

Prospector 在 Python 生态中扮演着重要角色,尤其是在那些重视代码质量和一致性维护的项目中。结合其他生态项目,如 mypy 进行静态类型检查,或 bandit 进行安全审计,可以构建出更全面的质量保障体系。Prospector的设计使其能与这些工具良好协同工作,通过在Prospector中启用相应插件,可以实现多维度的代码检查。

通过简单的配置和灵活的插件机制,Prospector不仅提升了单个项目的开发效率,也促进了整个Python社区代码标准的一致性和代码质量的普遍提升,成为了现代软件开发生命周期中不可或缺的一部分。

参考资料

  1. 代码检查工具文档介绍:https://wangmeng-python.readthedocs.io/en/latest/readability/code-analysis-tools.html
  2. Mccabe的GitHub链接:https://github.com/pycqa/mccabe
  3. Prospector的GitHub链接:https://github.com/prospector-dev/prospector
  4. ruff:https://myapollo.com.tw/blog/python-linter-ruff/

拒绝独行侠:从“我自己做”到“我们一起走得更远”

独角戏固然精彩,然而软件系统的产品设计、开发、运维、迭代,从来都不是一人秀。曾有一位开发者与少数几位小伙伴默契配合,用心构建起一整套系统。从需求调研、架构设计到功能落地,最后实现了项目的交付,每一次的迭代、每一天的开发都倾注了他们的心血与智慧。在那段日子,代码仓库里留下了他们无数次提交的痕迹,客户端、数据库、服务端与 web 前端紧密协作,多种存储与数据库组件共同支撑业务平稳运行——这是一曲动人的合奏。

然而,当团队迎来几位新的技术人员的时候,新的技术人员都具有前司的工作经验,他们也带来了新的视角与实践方法,都希望能够为现有的系统注入更多可能,共同打造一个更好的系统。这位开发者却将自己参与打造的系统视作铁饭碗,对任何替换或重构提议都坚决否决,无论是在私下的会议还是公开的大会上,都会否定新的技术人员提出的建议和解决方案。即使新的技术人员提到可以用某某开源框架和工具,该开发者总会以信息安全、开源限制、商业化等理由来进行反驳。当有新的技术人员提到一些“酷炫”的工具的时候,该开发者也会嗤之以鼻,觉得花里胡哨且有点低端。在某次会议上,该开发者甚至当众抨击新方案的必要性,仿佛那些设计只有他才配得上去维护与进化。

正是这种“我做过”、“我是该系统的创始人”、“必须以我为中心”的思维,给这位开发者孕育出一种自我优越的幻觉。在没有其他开发人员的时候,他自然是团队里面最优秀的开发人员,但是一旦有了其他开发人员的加入,他的能力就不见得是最优的了,提出的解决方案也不见得是行业中最佳的解决方案。在这种受到某种“威胁”的心态下,这位开发者既看不到团队的多元智慧,也忽视了对自身技术的迭代需求,更加没有在业余时间进行技术升级。殊不知,软件生命力的延续正来源于持续的重构与优化。性能调优需要专业视角,架构升级依赖前瞻思考,维护成本则仰赖清晰的规范与文档,缺一不可。在团队发展的历史上,如果将个人贡献无限放大,只会令系统陷入固化,最终拖慢整体进度与创新步伐。

管理者的角度

在《水浒传》中,白衣秀士王伦一开始就凭借自己的智慧与勇气,成功聚集了一群有志之士,建立了梁山泊。然而,尽管他具备领导能力,仍然面临着一个重要的问题——如何在集体中接纳新的力量。尤其是在林冲加入梁山后,王伦的领导地位受到了挑战。最终,林冲凭借着丰富的经验和广泛的影响力,逐渐展现出自己能更好地团结群英、带领梁山走向更大胜利的能力。最终,王伦的固守和排斥新力量的态度,使得他没能顺应时代的潮流,导致了最终的悲剧。

这个故事给我们一个深刻的启示:只有接受新鲜的力量,才能够把事业做大做强。王伦的失败在于,他固守自我,不愿接纳新的力量,最终导致了领导地位的丧失。同样,在现代的企业和团队中,领导者如果不能接受新思想、新技术和新成员的加入,那么这个团队也将面临被时代淘汰的风险。

对于一个团队来说,老员工积累的经验和技术是团队的宝贵财富,但随着时间的推移,技术、市场需求、甚至团队的工作方式都在发生变化。接纳新鲜力量并不是削弱老员工的地位,而是为了让团队能够适应变化,迎接未来的挑战。当新成员带着新的技能、不同的视角和创新的思维进入团队时,他们的加入可以为团队注入新的活力,为现有的工作方式和技术体系带来革新。正是这种新旧力量的融合,才是团队能够突破瓶颈、实现跨越式发展的关键。

然而,接纳新力量并非没有代价。老员工可能会面临某些牺牲和调整。他们需要放下过去的固守,学习新的技术,适应新的工作方法,甚至在某些项目中,他们可能不得不让位给新来的成员。这样的牺牲在短期内可能带来一些不适,但从长远来看,这种调整和改变必将为团队带来更强的竞争力和更广阔的前景。

团队管理者首先需要强调,任何团队的核心目标始终是推动产品和项目的成功,而成功并非单打独斗的结果。通过实际案例或团队的历史数据来说明,团队合作和多元化的思维往往能带来更高效的创新和技术解决方案。例如,可以向这位老员工展示过去团队合作中如何通过集体智慧突破了某个技术瓶颈,或是通过团队成员的不同视角让项目得以成功落地。让他明白,技术上的成就不仅是个人的功劳,团队合作才是达成大目标的关键。失败的项目中没有成功的个人,一个优秀的人的评价标准之一就是看能否带出一群优秀的人。

心态的转变往往需要时间,特别是当一个老员工长期处于自我认同和技术领导的位置时,接受新人的存在可能会让他感到不安或焦虑。作为团队的管理者,可以通过与该开发人员进行一对一的沟通,了解他内心的真实想法和担忧,耐心地给予理解和安慰。这里的沟通,自然不是简单的批评和责怪,而是通过共情和支持让他意识到,团队合作不是威胁而是机会。可以鼓励他与新的技术人员交流,合作完成项目,帮助他从团队的共同努力中获得成就感。

团队管理者还可以通过激励机制来推动这种心态的转变。对于愿意接受新技术、帮助新人融入并发挥作用的老员工,给予充分的认可和奖励,不仅仅是技术上的奖励,还可以是职业发展上的机会。通过奖励积极合作的行为,管理者能够激励老员工放下防备,接受团队的新成员们,并真正融入到集体的共同进步中去。

老员工的角度

那么对于老员工而言,如何从“我自己做”迈向“我们一起做”?

在每一次技术讨论之前,老员工可以带着好奇的心和详尽的问题清单,提前了解新方案的设计初衷与实践案例;建议带着学习的态度,这样会发现许多设计背后的巧思。推行统一且透明的评审流程:让每一次方案评估都有据可循,让客观数据和测试结果说话,减少因角色或资历带来的偏见。构建持续学习的文化:定期举办技术分享会,让团队成员轮流讲解新技术、新工具,哪怕只是短短二十分钟,也能为大家打开一扇新的窗口。

成长从来不是孤行,而是携手并进的旅程。当“我们”成为核心,个体的聪明才智将被放大,团队的合力便能产生超越想象的效应。在相互成就中,技术的直观价值才能转化为项目的长远收益,造就一支无坚不摧的最强战队。

突破自我,接受新来的团队成员,最需要放下的是自我优越感,认识到技术的进步和团队的成功不仅仅依赖于个人的能力,更依赖于集体的智慧。在一个团队内部,每个人的背景、思维方式、工作习惯和技术擅长领域都各不相同,这些多样性带来的冲突和碰撞,往往是创新和进步的源泉。面对新员工的加入,最重要的是保持开放心态,而不是立刻抱有防备和排斥的心理。毕竟,没有谁是完美无缺的,团队内部的多元化,不仅不会削弱现有成员的价值,反而能够提供更多思考的维度和解决问题的办法。因此,突破自我意味着要把自己从“自我中心”的狭小视野中解放出来,给予新人的提案、技术、解决方案更多的耐心与理解。

新员工的角度

对于新人来说,融入一个团队同样充满挑战。新人一定要具备谦逊的态度和学习的心态。尽管新人带着新的思维和技术积累进入团队,但在初期最重要的并不是展示个人能力,而是通过理解团队的工作模式、文化以及现有系统,逐步找到自己的定位。新人可以通过主动学习和请教,融入团队的技术氛围和日常工作流中。这不仅有助于他们快速适应工作节奏,还能建立与团队其他成员之间的信任和友谊。

在日常的工作中,新人也要学会提出建设性意见,而非简单的批评和抱怨。盲目的抱怨和批评是无法给团队带来收益的,甚至还会给自己带来不好的结果。加入一个成熟的团队并不意味着一切都要照已有或者全新的方式来做,而是要学会在团队既有的框架和文化下找到自己的声音。如果能在深入理解现有技术架构和流程的基础上,提出实际可行的改进建议或新技术的应用方案,便能获得团队的尊重和认可。

新成员应该积极参与到团队的讨论和交流中,不仅仅局限于自己的项目或技术范畴,而是广泛地与团队成员分享自己的见解和思考。定期的技术分享会、站立会、代码评审等活动,都是促进团队成员之间互相学习和理解的好机会。通过这些活动,新人可以更好地了解团队的技术水平和需求,同时也能让自己在实践中逐步积累经验,找到自己的立足点。

结束语

无论是新老员工,突破自我,接受彼此,都会为团队带来更强的凝聚力和创新能力。在这样的环境下,每个人都能在互相支持和挑战中不断成长,最终形成一个充满活力、协作高效、技术领先的团队。作为团队的领导者,不仅要看重老员工的经验积累,更要勇于接纳新成员的加入,甚至协助老员工与新员工的合作,并为他们提供充分的支持和机会。通过让老员工和新成员在共同的目标下团结协作,团队才能真正做大做强,迎接更加广阔的未来。

故事含虚构创作,如有雷同纯属巧合