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 前端紧密协作,多种存储与数据库组件共同支撑业务平稳运行——这是一曲动人的合奏。

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

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

管理者的角度

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

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

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

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

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

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

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

老员工的角度

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

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

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

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

新员工的角度

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

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

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

结束语

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

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

从工作心态到目标心态:如何找到职业发展的真正动力?

三种心态

在职场中,我们每个人都有不同的动机和目标,有些人可能在工作中追求薪水和职位的提升,有些人则将职业目标与个人使命紧密结合,充满激情地投入到工作中。在忙碌的工作之余,你是否曾经停下来认真思考过自己在工作中的心态?判断一下你自己是为了薪水而工作,还是为了事业的提升,或是为了一个更高的目标?

今天,我们来讨论一个非常有意义的话题——工作心态、事业心态和目标心态,这个过程可能是你职业生涯中最重要的转变之一。我们再来看一下这三种心态究竟在说什么。

工作心态为了薪水而工作

工作心态,是我们最常见的一种职场状态。简单来说,当我们抱有工作心态时,我们的主要动机就是为了按时领取薪水,可以说这是绝大部分打工人的最真实想法。毕竟每个人都需要养家糊口,打工不为了赚钱为了什么?这类打工人通常会将工作当做日常生活的一部分甚至绝大部分,日常完成领导安排的任务就是为了得到报酬,对工作本身可能并没有那么喜爱。但是也有把工作本身当成热爱的员工,其投入的人力和精力跟前者是不太一样的。

为了薪水而工作的这种心态在初入职场时会比较普遍,特别是在我们从学校刚刚踏入社会的时候,或是在学校期间我们还没有明确职业目标,这种情况下往往就会有打工的心态。很多人会在这一阶段因为需要生活费用、支付房租或是偿还债务而工作。然而,如果这种心态持续太久,可能会让我们陷入职业的“舒适区”或者“倦怠期”,对工作失去激情,对工作产生厌倦,甚至对工作产生非常厌烦的情绪。

警惕:如果你发现自己在工作中只为薪水而工作,而且公司和上级给你的工作内容和责任感不再激发你内心的热情,同时留下来工作的目的也仅仅是为了薪水,那么你可能需要反思自己是不是陷入了工作心态的陷阱。这种状态下,员工可能会感到不满足、空虚或焦虑,因为他们的满足感主要来自于外部奖励,而非内心的成就感和满足感。这种过于依赖外部刺激的工作心态,常常带来短期的满足感,但难以实现真正的长期幸福和职业成就。

事业心态为职位和权力而奋斗

当工作不再只是为了薪水时,一些人开始转向事业心态。他们希望通过工作获得更高的职位、更大的权力,甚至希望通过扩大团队规模、提升控制范围来证明自己的价值。在这个阶段,薪水和职位成为了最主要的动力来源,目标通常是“快速晋升”和“更高的职位”。

事业心态下,员工将更多的精力投入到权力和影响力的扩展上,他们会通过不断的业绩表现、加班和社交努力,去争取公司内的更高职位。这种心态的优点在于它能驱使人快速进步,适应职场的竞争环境,并推动个人实现一定的职业目标。但同时,过度关注权力和职位也可能导致职业发展偏离初衷,尤其是当工作过于侧重个人利益时,很容易忽视团队合作和公司的共同目标。

警惕:如果你总是过度关注自己的晋升或是职位上的变化,忽视了自己的实际工作成就和团队的合作,那么你可能过于陷入事业心态而忘记了真正的职业使命。这种过度的事业心态往往让员工陷入无止境的竞争和权力游戏中,不仅消耗大量的精力,也可能破坏与同事和团队之间的合作关系。虽然事业心态可能带来短期的职场成就,但它也容易让员工自己感到内心的不安、焦虑甚至愤怒,甚至会对同级别、下级员工疯狂地输出自己的情绪。因为事业的这个目标本身太过功利,员工有可能也会缺乏真正的内在满足感。

目标心态:为更广泛的目标而工作

与工作心态和事业心态相比,目标心态则代表了一个更高的职业境界。在这种心态下,员工的工作不仅仅是为了薪水和职位,更是为了实现一个更大的目标,即为个人的成长、团队的成长或关键利益相关者服务

目标心态的员工通常充满激情,富有创意,他们不仅关注自己本职工作的完成,还会通过创新和改进推动团队或公司整体的发展。抱有目标心态的人,会将个人职业目标与公司的整体目标相结合,为公司的使命和愿景付出努力。此类员工会主动承担更多责任,积极推动工作进程,不断寻找提升自己和团队的机会,将利益进行最大化。

这种心态的最大特点是内外一致:内心的职业目标与外部的工作任务和组织目标保持一致。他们不再单纯为薪水而工作,也不单单追求职位的升迁,而是为了更好的职业成就、个人成长,以及对团队和公司的贡献。拥有目标心态的人,往往能够在职场中取得长远的成功。

目标心态的人不仅关注自己在工作中的表现,更注重工作所带来的意义和影响,他们有明确的方向感和使命感。这种心态的人通常能够保持内心的平静和满足感,因为他们的职业目标与个人价值观相一致,且不为个人利益而生,而是为了团队、组织和社会的共同利益而努力。目标心态让人超越了自私的欲望和盲目的追求,达到了工作和生活的和谐与平衡。

如何从工作心态到目标心态转变?

在转变之前,首先你需要判断自己当前处于什么样的心态。坚持记录几周,你就能够判断,自己到底偏向三种心态中的哪一种了。然后,如果已经确定了自己的心态,并且“工作心态”和“事业心态”占据了你半数以上的时间,那么你就一定要提高警惕了,你必须重新根据自身的情况来设定或重新定义你的个人目标。

1. 重新审视自己的职业目标

我们每个人都应该定期反思自己的职业目标。你为什么选择这个行业或职位?你希望未来成为什么样的人?你未来想达成什么样的目标?设定明确的职业发展目标,帮助你找到工作中的意义。

2. 寻找工作的激情与意义

即使工作内容看似枯燥,尝试找到其中有意义的部分,因为想找一个自己100%喜欢的工作是十分困难的。通过将自己的个人目标与公司的整体目标结合,激发自己的工作热情。例如,思考如何通过创新改进工作流程,或者如何在团队中发挥更大的影响力。

3. 持续学习与自我提升

目标心态的员工往往具备高度的自我驱动力和学习欲望。这类员工希望能够不断学习新的技能、提升自己的专业水平,既能增加个人的职业竞争力,也能在工作中感受到成就感与满足感。

4. 关注团队与组织的长远目标

通过关注团队和组织的目标,而不仅仅是个人的利益或职位,能够让你在工作中找到更大的动力。个人与团队成员协作、为组织的共同目标奋斗,不仅能提高工作效率,也能增强团队的凝聚力。

5. 培养积极心态

从“工作心态”到“目标心态”的转变,最重要的是调整心态。你需要培养积极的工作心态,将每一次工作挑战视为成长的机会。不断向更高的目标迈进,会让你感受到更多的满足和成就。

目标心态,职业成功的关键

在职场中,每个人都可能会在不同的时间和环境中表现出佛学中的贪、嗔、痴的不同面向。通过理解佛学的这三种烦恼,我们可以在工作中更好地调节自己的心态,找到真正的职业动力。

序号词语解释例子
1对物质、权力、地位的过度渴望,缺乏满足感,追求短期的满足。贪欲常常导致不平衡的生活,产生焦虑和痛苦。一名员工只为了高薪水而工作,忽视了自己的兴趣和职业发展;或者一个人过度追求名牌和奢侈品,导致经济负担加重。
2愤怒、嫉妒、敌意,常由竞争、得失、对他人的不满等情绪引起。嗔欲通常导致冲突和人际关系的破裂。在职场中,一名员工因升职机会被他人抢占而愤怒,并因此与同事产生矛盾;或者对自己权力被削弱或地位受威胁时产生敌意。
3无知、迷惑、执着,缺乏清晰的认识和判断。痴欲让人做出错误的决策,无法看到事物的真相,导致反复失败。一名员工固执于传统做法,拒绝接受新技术或方法;或者某人因为对某个目标的过度执着,而忽视了其他重要的生活方面,如健康、家庭等。

在工作中,我们需要注意以下事项:

1. 避免“工作心态”的贪:不要仅仅为了薪水而工作,要想办法寻找工作内在的动力。通过提高自身的能力、明确职业目标和意义,让自己从单纯的物质追求中尽快解脱出来。

2. 超越“事业心态”的嗔:避免过度关注权力和职位的提升,要培养团队合作精神和对他人的尊重。在追求职业发展的过程中,要保持谦逊,控制自己的心态和情绪,避免无止境的竞争和焦虑。

3. 追求“目标心态”的智慧:明确自己的职业目标,并将个人目标与团队或社会的共同目标结合起来。这样不仅能获得内在的满足感,还能为更广泛的组织或社会贡献力量。

通过认识和调节自己的心态,我们能够在职场中找到真正的平衡,实现个人价值和职业目标的统一。佛学教导我们,只有超越贪嗔痴的束缚,才能实现内心的平和和事业的长远发展。职场不仅仅是为了赚钱和获得职位,更是一个不断自我提升和实现更大目标的过程。从“工作心态”到“事业心态”,再到“目标心态”的转变,是每一个职场人不断进步的必经之路。只有当你为更广泛的目标而工作时,才能在职业生涯中找到真正的动力和成就感,迈向更高的职业巅峰。今天,你是否已经意识到自己正处于哪种心态之中?是时候从工作心态或事业心态中跳出来,重新审视自己的目标,开始为真正的目标而努力了!

如何增加会议的价值?

让人无奈的临时会议

每一个职场人都曾经历过这样的一天:明明正沉浸在手头的工作中,突然领导的声音从旁边中传来:“大家停下手上的工作,立刻去某个会议室现场开会!”这是一个看似突如其来的通知,却有可能成为了每天工作的常态。更糟糕的是,这种临时会议的召集方式似乎没有任何规律可言——有可能是10:00通知立刻开会,或是13:30突然收到13:45开会的通知,或是在快吃饭的时候急匆匆被喊去会议室,大家赶到现场后,发现会议的内容其实是某个材料的提交、工作纪律的提醒,甚至是领导突然的情绪宣泄,最后甚至脱离主题,扯到其他无关的场景中。

其实,从这种临时且看似紧急会议开始的那一刻,大家带着一种迅速进入状态的紧迫感,毕竟如果没有紧急且重要的事情,是完全没有必要让大家停下手中的所有活去开会的。在开会前,每个人都在焦急地等待着领导整理思路,等待着会议内容的实质性推进。但是,有的时候领导一开口,就让人觉得无奈,竟然是讲一个无关紧要的事情和主题。同时,由于是那些领导自身都准备不足的会议,领导一边在会议中支吾其辞,一边寻找话题的支撑点,会议内容时而不连贯,时而跑题,最后花费了所有员工的时间,却未能真正解决任何实际问题。大家无奈地听着,会议结束后,继续回到任务中,却再也找不回之前的专注和效率。这种无效的会议安排,往往不仅没有明确的目标和有效的输出,反而让所有人感到焦虑和疲惫,最终无功而返。

这种临时的会议安排,在某些地方似乎已经成为了管理中的一种常态,信息量并没有有效地传递,但却在不断消耗着每个人的时间和精力。更为严重的是,这种多次且频繁发生的低效会议,严重影响了开发团队的整体工作节奏,导致很多员工的积极性下降,团队协作的效率也大打折扣。会议本该是信息传递和决策的工具,但现在,它变成了拖延工作、无谓消耗时间的陷阱。

领导如何开会,才能确保高效率?

对于一个团队而言,开会并非一件简单的事情,它不仅是信息传递的途径,更是决策、问题解决和团队凝聚力的体现。领导应当意识到,会议的核心目的并不是为了填充时间,更不是让员工白天开会晚上干活,也不是为了领导个人的表演和侃侃而谈,而是为了确保信息的高效传递与项目目标的达成。因此,领导需要在开会前做足准备,确保每一次会议都能够高效、精准地达到预期目标。

明确会议的目的和议题至关重要。每次开会之前,领导应当提前规划会议的主题和内容,并确保每个参会人员都明确自己在会议中的角色和任务。例如,如果会议是为了讨论某个项目进展,那么所有参会人员应该提前准备好相关的数据和材料,而不是在会议中浪费时间寻找信息和讨论琐事。领导应在会议开始时,简明扼要地阐明会议的目标,让每个参会者都能集中精力,在最短的时间内达到会议目的。在开会之前,领导最好结合需要开会的主题撰写一份在线文档,自己把思路和要讨论的点整理清楚,同时提供相对清晰的会议目标。如果是特别紧急的事情,临时写一份短的在线文档即可;如果有时间的话,就可以事先把在线文档写得全面和完整,这样的话员工在开会的时候就清楚信息的传递以及自己未来的工作安排。

这里为什么要用在线文档呢?因为在线文档可以实时地发送给相关的参会人员,同时让大家在开会的时候就能够阅读文档,甚至编辑文档,这是离线的word、ppt所不能够达到的效果。在开会之前可以让大家先同时在办公室阅读5-10分钟在线文档,同时在文档中做标记、评论,相关人士可以同时做回答,这样的话就可以提升开会的效率和质量。这样就可以从串行到并行,从会议上只能有一个人发言到同时可以多个人发言,大大提升会议效率

领导需要掌控会议的节奏与时间,在开会的时候,一定要避免无意义的拖延。领导在开会时要避免长时间的漫谈,尤其是不要让自己在侃侃而谈中迷失方向,忽略了会议的实质性内容。如果会议的主题是技术讨论,就不应频繁跳跃到无关的管理话题;如果是工作汇报,就应该确保每个人按照事先约定的时间完成汇报,避免一个人过度讲解,而导致其他人无法参与,反而浪费了所有人的时间。时间管理非常关键,一场有效的会议应该精准高效,避免拖沓和无效的讨论。

在开会的时候,领导一定要控场,并且让员工聚焦关键问题,避免会议跑题。在会议进行过程中,如果领导发现讨论开始偏离主题,应该及时干预,提醒大家回到正题上。领导的引导作用至关重要,能够有效控制会议的方向,避免讨论陷入无关紧要的琐事。对于那些没有价值的内容,领导应该果断切断,确保会议围绕关键问题展开,达成具体的工作成果。

会议的关键是要有决策,避免毫无意义的开会和讨论。总结会议内容,并明确后续行动。会议的结束不应只是草草了事,而是要确保每个人都明确自己的责任和任务。没有任务的人其实不需要来开这场会议。领导应在会议结束前进行简短的总结,并明确每个成员的具体行动步骤和完成时间。这能确保每个参会人员都知道接下来的工作重点,以及他们需要采取的行动。

高效会议的背后:尊重员工的时间,提升工作质量

会议的真正意义,在于通过有效的沟通和信息交流来提升工作效率和质量。领导通过合理规划和高效执行会议,不仅能够为团队提供明确的方向和目标,还能够提高团队成员的参与感和责任感。当每一次会议都能有条不紊地进行,大家的时间得到了尊重,工作也将变得更加高效。

高效的会议,能让团队成员在短时间内达成共识,推进工作进展,而非浪费宝贵的时间和精力。对于领导来说,每一次会议的高效执行,都能让团队感到信任与尊重,从而提升整体的工作氛围和团队士气。会议不是一个形式,它是一种推动工作前进的工具;只有当我们摆脱无效会议的困扰,才能真正提升工作效率和团队凝聚力。

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

当工作的时间被无形割裂:程序员的焦虑与困境

碎片化工作:一场无声的时间劫持

每天早晨来到公司,程序员在整理好书包,冲泡好咖啡,刚刚准备好进入代码世界,整理昨天的工作内容,即将开始今天的工作。却发现公司的电子邮件、工作群聊和公司内部的管理平台早已堆满了待处理的事项。其中,有人要求你提交日报,有人催你汇总周报,还有不定时的安全检查行为规范桌面整洁程度技术考试企业文化培训产品与项目的流程考试等。

即使你坐下来开始整理技术方案和编写代码,也时常会被临时的任务打断。比如,突然有一个人在工作群聊里面找你,并告知你“这里有一个非常紧急的任务,今天下班之前必须完成”,或者领导临时要求你提交一份PPT或者文档向上汇报,或者突然间你收到一封邮件要求填写设备外出证明,接着又需要将个人周报的总结内容汇总给部门负责人,紧接着,你会突然收到领导的要求,临时要求你去几十公里之外参加一个不明目的、突如其来的会议,虽然你知道这个会议与你的工作并没有直接关系,但仍不得不去,同时花费大量的时间和精力。而当你到达现场时,会议还没有开始,或者根本没有机会参加,甚至已经结束,最终只能再次返回几十公里以外的座位上,继续处理未完成的工作。

就算你在忙碌了一天之后,在18:00准备去吃饭的时候,还有可能会收到来自工作群聊或者邮件的工作安排,要求明天早上12:00之前提交自己半年内的工作材料,包括但不限于代码、文档、会议记录、日常沟通详情等内容。在这种情况下,你只好继续加班应对这种突如其来的任务,以便明天早上能够顺利完成。如果运气不好,接到这个任务的时间恰好是周五17:30,那不好意思,你必须要在周六来义务加班完成,并提交你这半年甚至一整年的工作证明。

这些任务看似不起眼,却消耗了程序员宝贵的专注力。真正的工作时间被这种信息噪音所侵蚀。尽管程序员从早忙到晚,但真正专注编程、解决问题的时间寥寥无几,反而是在重复、冗长的报告和反馈中度过了一天。

无形中的压力:目标与任务之间的断层

更加让人头痛的是,领导传递的信息并不是完整的,中层并没有做好任务的拆解,而是只做了任务的传递,甚至还只传递了部分的信息或者错误的信息。程序员所面临的任务往往是碎片化和形式化的,缺乏有效的目标指引,也不明白为什么要那么做。许多额外的任务并不直接影响产品开发或技术创新,然而它们却成为了程序员工作的必选项。比如,必须每天填写日报,每周写周报,双周写双周报,后面还有月报、季度报、半年报、年度总结报告等一系列内容。这些报告的内容通常是机械的、汇总式的、没有价值的,但却被看作是衡量工作的标准之一,毕竟领导也不一定知道你具体做了什么样的工作。

这种情况加剧了程序员的焦虑和压力。在时间上,他们总是被紧迫的任务所包围,导致根本没有时间进行深入的学习和思考;在情绪上,他们也感到疲惫,因为这似乎永远无法填补的任务清单压得他们喘不过气来。甚至有时候,他们开始怀疑自己的工作是否真正被认可,是否在不断忙碌中失去了本应专注的核心任务——技术研发。极端情况下,程序员的主要工作会从代码撰写变成了文职一类的文档撰写工作。除此之外,加班似乎成了程序员生活中的常态,在一些公司内部,但很多加班的时间并非都用来做技术工作,反而是用来完成那些无关紧要的任务。为了不被领导质疑,程序员不得不在晚上加班整理周报、处理不必要的邮件、参加临时会议,甚至加班后还要应付突如其来的工作要求。

这种形式化的工作并不能为团队和公司带来真正的创新和提升,反而可能使程序员的技术能力停滞不前。代码写得更多,但创新却变少了;参与的会议和活动更多,但实际解决问题的机会却变少了。结果是程序员尽管加班加点,却依然没有产出优秀的成果,工作效率低下,身心疲惫。

如何打破碎片化:让程序员真正回归技术

对于程序员自身来说,时间是一切的基石。高效的开发工作需要高度的集中和深度思考,这是任何外界干扰无法替代的宝贵时间。当这些被外部杂事和信息化管理掩盖时,程序员的工作节奏被打乱,他们不得不在碎片化的工作模式中挣扎,难以找到真正的创造空间。程序员的核心价值在于技术和创新,而这种碎片化的工作环境,却极大地限制了他们的成长空间。没有长时间的深度思考和技术挑战,程序员的能力和创造力往往停留在表面,缺乏突破和提升。碎片化的任务无形中削弱了他们解决问题时的专注力,使他们的技术深度逐渐变浅,最终陷入“技术疲劳”的怪圈。

许多技术问题和创新性任务需要程序员在长时间的深度工作中积累和解决,而这些工作往往没有外部干扰。只有在“无任务”的环境下,程序员才能有时间深入研究某个具体的问题,提出创新的解决方案。然而,现实却是,程序员在忙碌的会议和报告中反复切换角色,无法有效地进入“技术流”的状态。

要改变这一现状,企业必须从根本上审视当前的管理模式。技术型岗位的特殊性要求企业必须为技术工作提供一个安静、专注的环境。企业不能忽视开发时间的价值,它是每个程序员突破瓶颈、解决难题、创造创新产品的关键。企业应考虑减少无关紧要的例行工作和会议,将更多的时间和精力集中在真正有意义的工作上。以下是几个简单的建议:

1. 合理分配任务,避免过多的行政工作:企业应减少过多的会议和报告要求,合理分配工作任务,给程序员更多的时间集中于核心技术工作。报告和总结类任务可以通过自动化工具或团队协作来减少工作负担。尤其是不应该让程序员去承担过多的产品设计、项目沟通等工作,更不应该让程序员去承担文员一类的工作

2. 减少不必要的干扰,鼓励“深度工作”:在项目开发的关键阶段,企业应鼓励程序员“关掉手机”或“关闭不必要的应用”,并在时间上设置专注区,帮助他们进入深度工作状态。必要的时候减少日报、周报、月报的撰写工作,企业不要随时随地检查程序员是否在工作,也不要让程序员自己证明自己在工作。

3. 优化会议管理,避免无效时间浪费:减少频繁的临时会议,尤其是无关工作内容的会议。会议时间应根据实际需求严格控制,确保每次会议都是有效的、有目的的。推动线上线下会议的有机结合,不要随随便便就让程序员去几十公里之外参加一个无关紧要的会议。

4. 建立合理的绩效评估机制:不要通过日报、周报等形式化任务来衡量程序员的工作成果。评估程序员的工作绩效应当基于他们在技术开发、创新解决方案和项目推进方面的贡献。更不要用代码行数、文档个数、模型个数等指标来衡量程序员的产出。

5. 尊重技术人员的成长空间:为程序员提供更多培训和深度学习的机会,鼓励他们进行技术积累和知识更新,而不是把他们局限在繁琐的日常任务中。鼓励他们通过在线课程、公司内部资源进行主动学习,管理者不应该把程序员困在繁琐的工作中而不去培养他们的能力。

管理者的自省:让技术员工回归创造的初心

对于管理者而言,需要认识到碎片化时间的危害,并采取切实措施帮助员工恢复专注,是推动团队长远发展的关键。高效的管理不仅仅是任务的分配和监督,更重要的是创造一个能够激发员工潜能、鼓励深度思考的工作氛围。有效的时间管理,清晰的工作目标,和明确的任务优先级,有助于确保技术人员能够在专注的工作状态中,发挥出最大效能。与此同时,管理者也要从根本上反思和调整员工任务的分配机制。应避免过度依赖额外的管理任务,而是更多地注重项目进展、技术提升和团队协作。这不仅能减少员工的负担,更能提升团队整体的工作效率和技术创新能力。

最终的目标:创造一个健康、专注的工作环境

碎片化的工作方式,给程序员带来了巨大的挑战和困境。只有通过企业和管理者的共同努力,优化管理方式,提供更多的技术空间,程序员才能真正回归到他们的核心工作——技术创新。如果企业能够认识到这些问题,并采取合理的应对措施,那么程序员将能够恢复自己的创造力和工作动力。通过有效的时间管理和任务优化,程序员可以将更多精力投入到技术研究和项目开发中,实现个人职业成长和公司整体技术水平的提升。

最终,企业和员工的共同努力将为创造一个更高效、更具创新性的工作环境奠定基础,帮助每个程序员都能在职场中找到真正属于自己的价值和成长空间。

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

形式过重,内容失焦

最近,某些企业开始要求员工制作短视频来汇报工作,包括内容剪辑、拍照、设计、配音、字幕等一系列操作。制作一份短视频,首先要经历拍摄、剪辑、配音、设计字幕等一系列繁琐的步骤。这些步骤涉及到大量的时间投入,无论是技术人员还是其他职能人员,都可能因此被拖慢工作进度。尤其是在没有任何实际需求的情况下,制作这些视频,既无法提高工作效率,也无法真正提升汇报的质量。相比之下,员工完全可以将这些时间投入到更具价值的工作当中,例如优化现有的流程、推动项目进展、解决实际问题,这才是对公司和部门更有价值的贡献。

除此之外,有些部门要求技术人员人员在忙完交付项目的同时,为自己的部门做一个部门门户网站,展示部门的集体活动、项目工作安排和其他事务。这一切看似是在提高工作效率和现代化,但实际上,却是一种过度形式化的浪费,不仅没有提升效率,反而给员工增加了不必要的负担。在组织架构频繁调整的情况下,部门门户网站的开发成本和维护成本将会居高不下。每一次组织架构的调整都意味着网站内容的修改、页面结构的重组、链接的更新,甚至是新的功能需求的增加。这些改动不仅需要技术人员投入大量时间去开发和调整,甚至还可能需要后期不断的维护和优化,导致成本居高不下。然而,这些网站所能带来的实际价值往往微乎其微——它们更多的是成为一个“虚拟的名片”,而并没有实际解决工作中的问题,也难以真正推动部门内外的有效沟通。

简单来看,PPT、Excel、Word等文件已经能够满足向上汇报的需求。信息化的办公平台,在线文档,甚至简单的邮件汇报,都能清晰、高效地传达部门的工作进展和重点。PPT本身就能将信息进行可视化,数据图表的分析和展示在 Excel 中不费吹灰之力,Word 文档和在线协作平台也能将工作内容一一列明。信息传达得足够清晰,工作情况也能得到很好的反映。那么,为什么一定要用短视频和网站去增加额外的时间和成本?或许让员工都忙起来才是领导真正的目的。

短视频的制作本质上是一种“形式上的繁琐”。我们必须知道,汇报的目的不是为了制作一部短片,而是为了向上级简洁地展示工作进展。让员工们花费大量的时间去制作视频,进行剪辑、拍摄、设计、配音,不仅让员工的工作效率降低,还使得他们的精力被这些无意义的形式主义所消耗。最令人困惑的是,这种形式化的内容输出并没有实际的价值,最终得到的汇报内容也可能只是为了给领导展示而已,而非为工作提供实际的帮助。

再来看门户网站的要求,似乎是为了让部门展示得更加专业,但实际上,这种做法带来了更多的复杂性和维护成本。开发人员本应该专注于自己的项目开发工作,而不是被迫去做展示的工作。做一个网站,意味着要设计页面、开发功能、测试调试,甚至后期的维护和更新也将耗费大量人力。这与工作汇报的初衷背道而驰:汇报的核心是传递工作信息,而不是通过网站来展示部门的形象。如果为了门户网站投入了大量精力,难道不应该思考一下,这个网站究竟能够为部门的实际工作带来多少实质性的提升呢?

最重要的是,这种过度形式化的汇报方式,往往会造成资源的浪费。对于一个部门来说,员工的时间和精力是最宝贵的资源。如果将本该用于实际工作的时间消耗在无意义的形式制作上,最终得到的汇报效果可能远不如那些使用传统手段(如PPT、文档等)做出的汇报。反而,如果每个人都可以专注于自己的工作,使用传统的、有效的汇报方式,不仅能够节省大量的时间,还能保证工作的质量和进度。另外,信息化平台本身已经能够满足绝大多数向上汇报的需求。如今,我们有越来越多高效的在线平台,能够让部门之间的信息传递更加流畅。如果我们不再被这种“形式主义”所束缚,反而能让工作回归到高效与实用的轨道

过度形式化的汇报工作只会让员工的时间和精力浪费在无关紧要的事情上,而非专注于工作的实际内容。这种做法看似现代化,实则徒增负担。作为企业的领导就应当摒弃这些毫无必要的汇报方式,让员工们回归工作的本质,尊重员工们的创造力和工作效率。真正的工作汇报,应该是简洁高效的,而不是过度复杂的装饰品

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

不算加班的加班:如何将私人时间变成团队资源

这周某个大团队举行了一场超级盛大聚会,定在了周六下午12:30-19:00。从时间上看领导们都觉得不算加班,但对于员工而言不是加班却胜过加班,至少加班会有加班工资或者调休。这场超级盛大聚会的活动内容包括开场、节目表演、团队业绩汇报、领导的长篇大论和一个默默的散场。为了避免不必要的麻烦,这场活动显然是“自愿参加”,但从组织安排到活动内容,怎么看怎么像是把员工的私人时间当成了团队的一项资源。

让我们来看看时间安排——周六下午12点到19点,员工为了提前到场和提前吃午饭,11:00就要准备出门。周六下午这个时间段本该是员工休息、放松、与家人相处的黄金时光,却被团队精心安排成了活动时间。虽然领导强调活动不算加班,但实际上,这并不意味着员工的时间不被浪费。为了表彰极少数优秀的员工,整个团队的私人时间被毫不犹豫地占用,这种安排真的让人觉得,领导的资源分配机制似乎只考虑了团队利益,却忽略了员工的基本需求。

再来说说没有聚餐的安排——本以为表彰大会应该有一些激励性的元素,像是聚餐、团队互动等环节,可惜,这场大会没有任何聚餐环节,整个活动简直就是一个没有味道的盛宴。节目表演?业绩汇报?领导的讲话?这些看似充实的内容,实则空洞无物,完全缺乏和员工实际需求的对接。领导讲话的时间甚至比员工等待的时间还要长,大家只能盯着舞台,勉强等待着会议的结束,仿佛整场活动的唯一意义就是完成一个合格的表彰环节。

而在活动前的周三,大家还回答了一个神奇的问题:“你是否愿意来参加周末的盛大聚会?”虽然这场活动不算加班,但这一问,却像是对员工心理的微妙测试。这并非一个简单的问询,而是带有潜在压力的提示:“你若不参加,是否就显得不够团队精神了?你不参加,是不是不愿意接受这一份团队的荣誉了?并不是所有员工都有机会参加的,给你这一份荣耀你要积极参与呀!”即使这种加班没有明确的强制性,这种提前询问也让员工在选择上感到左右为难,不禁让人怀疑,背后是否隐藏着一种“潜规则”?

然后,来谈谈这场大会的内容:虽然表彰大会的初衷是为了激励员工,但最终的效果却可能事与愿违。奖金微乎其微,没有额外的福利,抽奖环节的奖品少之又少。看到这里,许多员工的内心反而会充满失落。能让员工真正感到价值和激励的,不是空洞的表扬,而是切实的奖励和对员工辛勤工作的认可。否则,所有的表彰和奖励,都变成了表面功夫。业绩的提高、领导的讲话,似乎是为了让大家觉得:团队很重视你们,但实际操作起来,却和员工的需求南辕北辙。

盛大宴会的意义应该在于让员工感受到关心与尊重,但如果它成为了侵占员工时间的借口,并没有真正的激励和回报,甚至还让员工感到压力,那它的真正价值就值得怀疑了。让员工放弃周末时间来参加盛大宴会,现场却没有给出任何实际的激励,这种安排不禁让人觉得,团队似乎在占用员工的时间和精力,却没有给员工带来任何实质性回报

我们应该深刻思考的是,这种看似无害的活动安排,背后到底隐藏了多少公司对员工私人时间和需求的忽视?员工不是无条件地为团队工作和奉献,他们同样需要时间、空间以及真正的激励和认可。只有当领导真正从员工的角度出发,考虑到他们的生活和工作平衡,才能让这些表彰大会真正具有意义。而不是像这次活动一样,沦为一场“空洞”的时间占用,充斥着形式化的“庆祝”和空泛的表扬。

这场盛大聚会更像是一次被安排的体验,员工在其中扮演的不过是合格的观众,而不是参与者。如果领导真心希望增强团队的凝聚力,激励员工的工作热情,或许应该从根本上改变这种形式化的活动安排。真正的激励,不应该仅仅体现在一个活动的安排上,而是通过实际的奖励、福利、甚至是合理安排员工时间的尊重,来激发员工的积极性和忠诚度。本质上是公司对员工私人时间的轻描淡写的剥夺。

在这种安排下,员工的工作热情和归属感并不会因此得到提升,反而会产生一种无形的压力:即便是公司举办的活动,你依然要为参加而付出时间和精力,而收获的只有一些形式化的表彰。真正值得反思的是,未来的活动是否能更加人性化,考虑员工的需求,不仅仅是通过表扬来表现团队精神,而是通过实际的奖励和对员工时间的尊重,来推动更好的团队氛围。

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

Ollama简介:让大模型走进每个开发者的工具箱

Ollama的介绍

Ollama 是一款强大的人工智能语言大模型(LLM)平台,专注于为开发者和企业提供高效、可定制的文本生成和自然语言处理能力。通过集成先进的深度学习技术,Ollama 能够在本地帮助用户生成高质量的文章、解答复杂问题、提供自动化客服支持等。无论是内容创作、数据分析,还是智能客服系统,Ollama 都能提供灵活的解决方案,并支持跨平台应用。凭借其易用的接口、快速的响应速度和强大的定制化功能,Ollama 已成为越来越多开发者和企业的首选工具,为他们在复杂任务中提供智能化的辅助和支持。


不仅如此,Ollama还提供了一些非常简单的方式来下载、运行、加载和使用各种预训练的开源大语言模型,支持文本生成、知识问答等常见的自然语言处理功能。在Ollama的加持下,NLP不再是只有深度学习背景的开发者才能够接触的领域。

Ollama的入门

在GitHub的官网上,可以找到Ollama的链接是:https://github.com/ollama/ollama。同时,它可以支持MAC、Windows、Linux的使用,并且Linux的下载和安装命令如下:

curl -fsSL https://ollama.com/install.sh | sh

除此之外,Ollama还支持通过Docker的方式进行部署。在使用Ollama的之前,需要将其安装在电脑上,根据不同的操作系统,可以选择不同的安装方式。

下载与安装

Windows系统

打开浏览器,访问 Ollama 官方网站:https://ollama.com/download,下载适用于 Windows 的安装程序。下载地址为:https://ollama.com/download/OllamaSetup.exe。下载完成后,双击安装程序并按照提示完成安装。打开命令提示符或 PowerShell,输入以下命令验证安装是否成功:

ollama --version

如果上述命令显示版本号,则表示安装成功。

Mac系统

打开浏览器,访问 Ollama 官方网站:https://ollama.com/download,下载适用于 macOS 的安装程序。下载地址为:https://ollama.com/download/Ollama-darwin.zip。下载完成后,双击安装包并按照提示完成安装。安装完成后,通过以下命令验证:

ollama --version

如果上述命令显示版本号,例如ollama version is 0.6.5,则表示安装成功。如果显示zsh: command not found: ollama,则表示没有安装成功。

Linux系统

在Linux系统上,可以一键安装ollama,输入以下命令即可:

curl -fsSL https://ollama.com/install.sh | bash

安装完成后,通过以下命令验证:

ollama --version

如果上述命令显示版本号,则表示安装成功。

部分模型

在GitHub的官网上,我们可以看到Ollama可以支持和下载的模型种类是非常多的,包括Gemma、DeepSeek、Llama、LLaVA等,并且不同的大小也可以通过参数来进行选择。通常来说,模型的参数越多,模型的大小也就越大。更全的模型库可以参考链接:https://ollama.com/library

模型参数大小下载并运行
Gemma 31B815MBollama run gemma3:1b
Gemma 34B3.3GBollama run gemma3
Gemma 312B8.1GBollama run gemma3:12b
Gemma 327B17GBollama run gemma3:27b
QwQ32B20GBollama run qwq
DeepSeek-R17B4.7GBollama run deepseek-r1
DeepSeek-R1671B404GBollama run deepseek-r1:671b
Llama 3.370B43GBollama run llama3.3
Llama 3.23B2.0GBollama run llama3.2
Llama 3.21B1.3GBollama run llama3.2:1b
Llama 3.2 Vision11B7.9GBollama run llama3.2-vision
Llama 3.2 Vision90B55GBollama run llama3.2-vision:90b
Llama 3.18B4.7GBollama run llama3.1
Llama 3.1405B231GBollama run llama3.1:405b
Phi 414B9.1GBollama run phi4
Phi 4 Mini3.8B2.5GBollama run phi4-mini
Mistral7B4.1GBollama run mistral
Moondream 21.4B829MBollama run moondream
Neural Chat7B4.1GBollama run neural-chat
Starling7B4.1GBollama run starling-lm
Code Llama7B3.8GBollama run codellama
Llama 2 Uncensored7B3.8GBollama run llama2-uncensored
LLaVA7B4.5GBollama run llava
Granite-3.28B4.9GBollama run granite3.2

DeepSeek-r1会有不同的模型参数和大小,最少的模型参数是1.5b,最大的模型参数是671b。这些可以在Ollama的官网上找到,并且可以基于本地电脑的配置下载到本地电脑进行运行。在运行模型的时候,请注意mac的内存情况,以及参考Ollama官方提供的建议:You should have at least 8 GB of RAM available to run the 7B models, 16 GB to run the 13B models, and 32 GB to run the 33B models.

Ollama的使用

模型下载

使用帮助命令可以查到ollama的常见命令如下:

ollama -h

目前以操作deepseek-r1:7b模型为例,当你只需要下载模型的时候,需要使用命令:

ollama pull deepseek-r1:7b

当你需要下载模型并且运行的时候,需要使用命令,同时就会进入对话功能,正常的使用即可。退出的时候可以使用ctrl+d或者/bye即可。

ollama run deepseek-r1:7b

如果想查看该模型的细节,可以用show命令进行展示。

ollama show deepseek-r1:7b

当你想查看Ollama安装了多少大模型的时候,可以使用命令:

ollama list

在mac上执行ollama serve,会出现Error: listen tcp 127.0.0.1:11434: bind: address already in use的错误。原因是:Mac安装Ollama后,启动Ollama后会本地监听本地TCP的11434端口,但这个监听仅仅是本地层面的监听,无法被本地以外的主机访问,也就是无法被同网段的主机访问。如果其他主机需要访问的话,需要采用docker部署的方式,重新修改一个新的端口即可,同时对外开放相应的端口。

模型交互

命令行交互

在mac上启动命令行,可以将模型直接启动起来,进入对话模式。

ollama run deepseek-r1:7b

在交互模式下,输入/bye或按下Ctrl+d退出即可。

单次命令交互

通过管道将输入传递给相应的模型,模型进行输出,例如输入“什么是数学?”就可以用以下命令:

echo "什么是数学?" | ollama run deepseek-r1:7b

使用命令行参数

甚至还可以直接在命令行中传递输入以下内容,直接获得结果。

ollama run deepseek-r1:7b "撰写一份周报的模板"

使用文件交互,例如有一个文件是input_text_1.txt,内容是“什么是化学?”,那么通过这个符号<以及路径和文件就可以输入给模型,并且得到输出的结果。

ollama run deepseek-r1:7b </Users/zr9558/Documents/Datasets/text/input_text_1.txt 

自定义提示词

通过 Modelfile 定义自定义提示词或系统指令,使模型在交互中遵循特定规则。创建自定义模型,编写一个 Modelfile:

FROM deepseek-r1:7b SYSTEM "你是一个编程助手,专门帮助用户编写代码。"

创建自定义模型:

ollama create runoob-model -f ./Modelfile

运行自定义模型:

ollama run runoob-model

发送请求交互

通过curl命令可以看到当前端口启动的模型:

curl http://localhost:11434/api/tags

通过curl命令和相应的参数配置,可以实现发送请求给本地mac启动的模型。

curl http://localhost:11434/api/generate -d '{
  "model": "deepseek-r1:7b",
  "prompt": "什么是生物学?主要研究哪些方向?",
  "stream": false
}'

还可以增加更为复杂的参数进行curl请求,其中options里面就是模型的参数选择。

curl http://localhost:11434/api/generate -d '{
  "model": "deepseek-r1:7b",
  "prompt": "什么是生物学?主要研究哪些方向?",
  "stream": false,
  "options": {
    "temperature": 0.7,
    "max_tokens": 100
  }
}'

如果选择stream是true,则用流式进行输出,那么则是逐行输出,每一行的输出是就是词语或者汉字字符,把每一行的response汇总到一起就是最终的输出。

curl http://localhost:11434/api/generate -d '{
  "model": "gemma3:27b",
  "prompt": "用一句话介绍数学是什么?",
  "stream": true
}'

Python 交互

ollama提供了多种方式与Python代码进行交互,包括request,ollama SDK等。

requests 交互

可以直接使用Python的requests模块发送请求,并获得相应的结果。

import requests

# 生成文本
response = requests.post(
    "http://localhost:11434/api/generate",
    json={
        "model": "gemma3:27b",
        "prompt": "用一句话介绍什么是线性代数",
        "stream": False
    }
)
print(response.json())

另外,还可以这样去写代码:

import requests
response = requests.post(
    "http://localhost:11434/api/chat",
    json={
        "model": "gemma3:27b",
        "messages": [
            {
                "role": "user",
                "content": "用一句话描述什么是实变函数"
            }
        ],
        "stream": False
    }
)
print(response.json())

Ollama 交互

Ollama有python的SDK,可以使用python的版本,其GitHub源码链接是https://github.com/ollama/ollama-python。使用pip就可以完成安装:

pip install ollama

然后在Mac的PyCharm中使用以下代码,就可以发送请求给模型,进行结果的一次性返回:

from ollama import chat
from ollama import ChatResponse

response: ChatResponse = chat(model='gemma3:27b', messages=[
  {
    'role': 'user',
    'content': '用一句话介绍什么是泛函分析',
  },
])
# 打印响应内容
print(response['message']['content'])

print('-'*40)

# 或者直接访问响应对象的字段
print(response.message.content)

如果要做流式输出,则可以采用以下方法:

from ollama import chat

stream = chat(
    model='deepseek-r1:32b',
    messages=[{'role': 'user', 'content': '什么是数学分析?'}],
    stream=True,
)

# 逐块打印响应内容
for chunk in stream:
    print(chunk['message']['content'], end='', flush=True)


ollama的chat 方法可以与模型进行对话生成,发送用户消息并获取模型响应:

import ollama

print(ollama.chat(model='gemma3:27b', messages=[{'role': 'user', 'content': '用一句话介绍:数学中的动力系统是什么?'}]))

输出以下内容:

model=’gemma3:27b’ created_at=’2025-04-15T02:56:36.041842Z’ done=True done_reason=’stop’ total_duration=3464291750 load_duration=48093500 prompt_eval_count=20 prompt_eval_duration=433924792 eval_count=22 eval_duration=2981754125 message=Message(role=’assistant’, content=’数学中的动力系统研究的是随时间变化的系统,尤其是系统状态如何随时间演变。\n’, images=None, tool_calls=None)

如果只需要输出message中content 的部分,则可以这样修改代码:

import ollama

print(ollama.chat(model='gemma3:27b', messages=[{'role': 'user', 'content': '用一句话介绍:数学中的动力系统是什么?'}]).message.content)

ollama的generate方法用于文本生成任务。与chat方法类似,但是它只需要一个prompt参数。同时,如果只需要查看response的时候,就可以参考以下代码:

import ollama

print(ollama.generate(model='gemma3:27b', prompt='用一句话介绍:数学中的常微分方程是什么?'))

print(ollama.generate(model='gemma3:27b', prompt='用一句话介绍:数学中的常微分方程是什么?').response)

ollama的list方法可以列出所有可用的模型:

import ollama print(ollama.list())

ollama的show方法可以显示指定模型的详细信息:

import ollama print(ollama.show('deepseek-r1:32b'))

ollama的embed方法可以输出文本嵌入:

import ollama

print(ollama.embed(model='deepseek-r1:32b', input='The sky is blue because of rayleigh scattering'))

print(ollama.embed(model='deepseek-r1:32b', input='The sky is blue because of rayleigh scattering').embeddings)

另外,ollama还有create(创建新模型)、copy(复制)、delete(删除)、pull(拉取)、push(推送到远端)等常用的方法。另外,还可以使用ps命令查看运行的模型:

import ollama
print(ollama.ps())

客户端

还可以创建自定义客户端,来进一步控制请求配置,比如设置自定义的 headers 或指定本地服务的 URL。通过 Client,用户可以自定义请求的设置(如请求头、URL 等),并发送请求。

from ollama import Client

client = Client(
    host='http://localhost:11434',
    headers={'x-some-header': 'some-value'}
)

response = client.chat(model='gemma3:27b', messages=[
    {
        'role': 'user',
        'content': '什么是生物学',
    },
])
print(response['message']['content'])

如果用户希望异步执行请求,可以使用AsyncClient类,适用于需要并发的场景。异步客户端支持与传统的同步请求一样的功能,唯一的区别是请求是异步执行的,可以提高性能,尤其是在高并发场景下。

import asyncio
from ollama import AsyncClient

async def chat():
    message = {'role': 'user', 'content': '用简单的语句描述工作中的日报有哪些内容?'}
    response = await AsyncClient().chat(model='gemma3:27b', messages=[message])
    print(response['message']['content'])

asyncio.run(chat())

如果用户需要异步地处理流式响应,可以通过将stream=True设置为异步生成器来实现。

import asyncio
from ollama import AsyncClient

async def chat():
    message = {'role': 'user', 'content': '用简单的语句描述工作中的日报有哪些内容?'}
    async for part in await AsyncClient().chat(model='gemma3:27b', messages=[message], stream=True):
        print(part['message']['content'], end='', flush=True)

asyncio.run(chat())

文章总结

Ollama 是一个本地大模型运行框架,致力于让开发者在个人设备上快速部署和使用各类开源大语言模型(如 LLaMA、Mistral、Gemma、DeepSeek等)。它通过极简的 CLI 命令(如 ollama run llama3),帮助用户在无需复杂环境配置的情况下,一键拉起本地模型。Ollama 提供了统一的模型管理、会话API和内存管理机制,是开发者测试、原型开发、本地私有化部署的理想工具,也适合作为RAG、Agent框架中的模型后端接入点。

参考资料

  1. 官网链接:https://ollama.comhttps://ollama.org.cn
  2. GitHub地址:https://github.com/ollama/ollama
  3. Ollama中文文档:https://ollama.readthedocs.io/quickstart/
  4. Ollama教程:https://www.runoob.com/ollama/ollama-tutorial.html
  5. Ollama中文文档:https://ollama.readthedocs.io
  6. LlamaFactory:https://www.llamafactory.cn

比996更可怕的学习禁令:知识获取量下降的真相

当主动学习成为禁忌,企业便沦为领导的精神封建庄园。
但真正的技术人从不下跪。
我们收藏知识,如同战乱年代的学者守护典籍;
我们破解封锁,如同骑士突破坚固的城堡;
我们终将证明:那些用管理制度筑起的层层封锁,永远挡不住渴望进化的自由灵魂。

在深夜的办公室里,小 A 揉了揉发酸的眼睛,屏幕上的 PPT 标题《XXX 技术赋能业务增长》在黑暗中格外刺眼。这已是她今年的第 N 个周末被强制要求参加团队的技术分享,而就在昨天,领导刚驳回了她在工作日组织培训的申请,理由是:“你有这时间不如多改两个 BUG。”她想起上周分享到工作群里的公司培训链接,被领导当众批评“小 A 的工作不饱和,工作量不够大。”,也想到自己工作日组织同事学习计算机技术的时候,被领导在部门群里提醒“工作的时间不要做与工作无关的事情。”,甚至还想起自己过去熬夜准备的周末技术分享内容,最终成了领导述职报告里的团队建设成果。

“员工主动想学习知识,却被领导层惩罚和批评”——这荒诞的职场潜规则,正在以管理之名,悄然扼杀无数人的未来。

当 996 的加班争议尚未平息,一种更隐蔽的时间掠夺术正在蔓延。小 A 的遭遇绝非孤例:领导们在工作日的工作时间禁止一切技术培训,周末却强制全员充电学习和来公司开会,甚至还不能申请周末加班,毕竟没有处理公司的事情。领导们用双标逻辑编织出一张精密的大网——员工的私人时间被默认为团队的资产,导致员工的成长路径必须由他们独家授权。

小 A 所在的技术团队存在非常明显的学习时间错配。员工在工作日忙碌工作的同时,还要被迫在周末的时候来公司参与活动,被要求在疲惫状态下吸收知识。在人疲劳的时候,知识在员工心中的留存远远不如工作日所学到的知识。更荒诞的是,这些周末的技术狂欢往往没有后续落地计划,但是却成为领导汇报中团队文化建设的勋章。一位程序员甚至在匿名社区写道:“我们像被按头喝水的驴——领导指挥往哪儿走,我们就得喝哪片水洼,哪怕水里有毒。

比占用时间更可怕的,是对认知渠道的封锁。公司提供的官方培训链接被斥为“不务正业”,而领导安排的周末分享却成了“技术圣经”。这种信息管控的套路,正在制造现代职场的认知荒漠。某金融公司的案例令人心惊:风控团队被要求所有的模型必须基于领导 15 年前的论文框架修改,年轻工程师偷偷研究的强化学习算法一旦被发现,立即被标注为“与团队技术路线不兼容”。当学习这件事被异化为忠诚度测试,创新就成了领导权威的祭品。一位离职员工在最后苦笑:“我们不是工程师,是领导学术遗产的守墓人。”

领导们的心照不宣,藏在那些看似矛盾的禁令里。他们恐惧的从来不是员工“学不会”,而是“学得太快”——当团队技术水平停滞在领导可控的范围内,那把象征权力的椅子才能坐得安稳。某领导曾私下透露:“对于员工,只需要让他们完成任务,做好执行的工具人就可以了。不需要把这些知识传授给他们,他们一旦学会了新的技术,就会主动离开团队了,会引起团队的动荡。”

这种为了领导们安全区管理的代价是血淋淋的。某制造业工厂拆除技术图书馆,宣称“手工流水线是最好的商学院”,最终被智能生产线淘汰时,连操作手册都无人能看懂。当企业把员工驯化成认知绵羊,员工们的技术死亡早已进入倒计时。面对领导们全方位的围剿,真正的技术人学会了一套职场生存暗器。有人用自动化工具生成代码,从领导手中偷回加班的时间,在工作之余还能保持积极上进的心态;还有人主动建立和加入外部的学习社群,主动学习新的技术并于好友们积极沟通,如同地下工作者传递情报。

历史总是惊人相似。当中世纪的教会垄断《圣经》解释权,勇敢者把真理藏在民间歌谣里传播;当数字时代的领导们筑起认知高墙,真正的技术人正在用代码写就新的反抗诗篇。小 A 的电脑里依然存着那份未完成的 PPT,但在某一页的角落,多了一行小字:“所有技术演进史,都是破壁者与守门人的战争。”她不知道领导是否会看到这句话,但她终于明白——那些用加班时长丈量出的权力,永远压不垮渴望破土的生命。

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

当现代公司长了一颗作坊心

定义

现代化公司是一种以系统性管理、流程标准化、数据驱动、人才发展为核心特征的组织形态。它强调组织能力的可复制性集体成果的归属感个体成长的制度保障。在这种公司中:

  • 知识与经验属于组织,通过文档化、工具化沉淀 
  • 人才的成长路径明确,有培训、辅导与反馈机制 
  • 管理依赖流程、机制,而非“谁说了算” 
  • 协作是常态,分工清晰、透明、可追溯 
  • 成果归属于团队,激励机制偏向共享与长期价值 

反之,手工作坊起源于农业社会,是一种以“传帮带”、“一人多能”、“经验为王”为基础的生产模式。它依赖于师徒制、个体经验、非标准化操作。在这种模式下的组织表现为:

  • 知识掌握在个体手中,不愿公开或缺乏沉淀机制 
  • 新人培养靠“拜师学艺”,成长随缘 
  • 管理方式依赖资历、情感、家长制权威 
  • 分工模糊,谁会谁做,靠人撑场面 
  • 老员工享有“知识特权”,抵触流程化与协作 

简单说,现代化公司以组织系统支撑人的成功,而非靠“谁带你”“跟谁混”来决定命运。手工作坊是“靠人运转”的单位,而非“靠制度和体系自转”的组织。

工坊模式混进现代企业管理

在不少企业特别是传统行业或发展初期的团队中,我们常常能看到一种错位的管理模式。企业长着一副现代化的外壳,办公室有着高级感的开放工位、Scrum墙、ERP系统,但管理却保留着农业社会工坊的“传帮带+师徒制”内核。令人感到讽刺的是,这种看似“有经验”的管理,其实严重依赖人治、不具备可复制性。只要核心人物变动,整个小组的运作就会陷入混乱。而且,老员工以稳定为名抵触标准化流程,不愿意放权、不鼓励知识公开,导致新员工始终处在“你还不够格知道”、“信息传递只有一部分”的边缘地带。

一、手工作坊的影子:从传帮带到留一手

农业社会中,作坊式的手工生产靠的是“口口相传、手把手教”,而不是标准化流程和培训体系。这种“手工作坊式”的文化有几个鲜明的特征。首先是知识传承依赖个体。老员工像工坊里的“师傅”,不通过体系化培训,而是凭心情带人,甚至习惯性地留一手,把信息和诀窍当成自己的职场资产牢牢捂住。这不仅阻碍了知识的传递,也造成了岗位交接困难、业务断层的风险。企业的知识沉淀被个人化,组织对新人的培养仿佛变成了靠运气配对,甚至新人的成长非常缓慢。这就是所谓的:

  • 技能传授靠个人意愿,师傅愿不愿教、教多少,全凭“人情”与“信任”
  • 知识是“私有资产”,而不是“组织资产”
  • 信息透明度极低,掌握=控制,留一手=稳定地位

这种模式一旦迁移到现代企业,便出现了这些奇怪的现象:

> 📌 新员工没有完整的入职路径,而是“跟着谁就学谁的习惯”

> 📌 知识文档形同虚设,最核心的东西都藏在老员工脑子里  

> 📌 新人被视为“劳动力补充”,不被期待成长,也不允许挑战旧经验  

> 📌 老员工把项目成果视作“个人资产”,抵触合作、排斥透明

说白了,这不是组织在培养人才,而是老员工在复制徒弟。在协作机制上,成果也应被重新定义。一个项目的成功,不属于谁带出来的徒弟,而属于整个团队流程与分工的胜利。与其守着谁负责什么,不如强化跨岗位协同和知识共享。协作的前提,是对透明和信任的信仰,而不是旧式地盘文化。当传授经验变成对员工控制,知识也就死了

二、为什么老员工会产生工具人思维?

在某些企业中,很多老员工会从内心真的以为自己“白手起家、创下江山、劳苦功高”,却忽略了:

  • 真正让业绩增长的,是时代风口行业需求集体协作资金补贴,而非一己之力。
  • 团队中的任务分配、资源调配,本就是组织的作用,而非“谁带谁”。
  • 如果团队的知识无法沉淀、老员工的经验无法传承,再多的技术元老也架不住代谢,更何况某些老员工的技术在外面看来真的是不值一提。

但在“作坊化团队”中,老员工往往:

> ❌ 把自己当功勋,把新人当耗材 

> ❌ 不愿标准化流程,因为那会削弱“经验权力” 

> ❌ 反感培训体系,因为新人“变强”等于自己地位变弱 

> ❌ 对新人提意见,却不给资源与路径,只要求“干就完了”

老员工会将新员工(无论是社招还是校招)当做工具人使用,而非作为人才发展的一部分。在这种文化中,新人常常被默认“只负责干活,不必成长”,一切围绕输出展开,而非围绕个人的提升来开展工作。新人们没有明确的成长路径,也很少获得战略视角上的指导,也不明白自己未来究竟会走向什么样的岗位,更不知道自己未来会获得什么样的成就。在公司里面的老员工则往往把现有的成果视为自己亲手打下的江山,却忽略了其实大部分成果是行业红利、市场趋势、集体协作甚至资金补贴共同作用的结果。这种认知偏差让他们对新人的期待停留在“听话、好使”,而不是“成长、接棒”。

三、现代化管理该如何破局?

如果企业想打破工坊式依赖,那么就必须回归系统性管理的初心

✅ 1. 建立组织知识资产体系 

  • 所有经验必须转化为文档、流程、制度,而非靠人情口耳
  • 核心项目必须有交接计划、透明记录、鼓励员工主动进行文档建设

✅ 2. 新员工成长应制度化,而非“看人脸色” 

  • 入职培训路径明确、阶段反馈可量化、能够有明确的成长道路
  • 定期一对一指导、辅导机制正式化,而不是靠师傅心情

✅ 3. 明确“团队成果”的归属与协作机制 

  • 项目成果应属于团队,而非个体
  • 鼓励协作和交叉能力,打破谁的地盘谁做主的江湖习气

✅ 4. 老员工的价值不是独占经验,而是复制能力 

  • 成为经验教练,而不是信息壳子
  • 激励制度向带人成果倾斜,避免只做不教的激励误区

企业现代化,从来不只是工具和表格的升级,更是一场思维方式的转型。管理者要意识到,真正的高手不是自己做得多牛,而是能把别人带得很牛。企业能不能走远,不取决于你有没有几个资深老员工,而在于有没有一套机制,让他们的经验变成组织的能力。传帮带可以有,但不应该成为压榨和封闭的借口。新老共存的真正前提,是把人当作独立的个体来对待,而不是接力赛里的“下一棒劳动力”。真正的高手,是能教出高手的人。

维度现代化公司手工作坊
知识管理制度化、工具化、组织资产私有化、口口相传
人才培养路径清晰、机制支持拜师随机、自生自灭
管理方式流程+机制情感+资历
协作模式分工透明、集体归因模糊重复、谁熟谁上
成果归属团队结果、组织认可老员工主导、排斥新人
成长逻辑复制能力、放权教人留一手、控制话语权

如果你也在一个看似公司、实则作坊的环境里工作,那么也许你已经感受到了那种“表面现代化、骨子里落后”的割裂感。而破除这种“作坊心”,也许正是我们对职业尊严的第一场真正抗争。

四、总结:从“农业式组织”走向“工业化系统”

传帮带,不等于压榨;资历深,不等于控制权。 

当企业试图奔向数字化、智能化的未来时,更该先问一句:

我们的管理模式,是否还停留在刀耕火种?

当你的成长路径全靠运气,那就说明你身处的是作坊,不是组织。

真正的现代管理,不是你比别人牛,而是你能让别人也牛。

老带新,不是看新人的运气,而应是一种制度保障。

组织的现代化,不是换一套软件系统、更换一种汇报模式就能实现的。而是从每一位老员工开始,卸下作坊思维,建立真正面向未来的现代企业的成长型文化

万能螺丝钉的陷阱:做了很多,却没有留下什么

📚 十本手账,记录了两年的工作轨迹。

会议纪要、周报月报季度报年报、KPI奖惩方案、PPT整理、产品设计对接、校招与社招面试记录、短视频运营策划与编辑、设计与开发文档……翻开这些厚厚的本子,60%以上的内容竟都不是代码,也不是技术资料。

更让我唏嘘的是,虽然在这两年时间内涉猎了客户端、前端、后端、数据库、数据分析、算法各个技术方向,但真正能沉淀为技术资产的部分,却少得可怜。回顾之前的工作,能够整理出技术文档和知识的几乎没有。

> 📖 手账可以记录工作,但不能替代成长。 

📉 广度有了,深度缺失;做了很多,留下很少。

🧩 做“万能螺丝钉”的代价

在团队中,我像一个随叫随到的修补工,一个随处可以使用的螺丝钉:

  • UI改需求?上 
  • 前端开发?上
  • 数据库的数据不对?上 
  • 线上服务挂了?上 
  • 招聘没人面试?上
  • 短视频没人做?我也上
  • 周报、月报、季度报没人进行汇总?我依旧上

在过去的一段时间里面,我以为这是一种能力:我能适应任何位置,我是不可或缺的多面手。但时间久了,我逐步发现一个令人警醒的几个现象:

每个项目我都参与了,但没有一个领域真正“属于我”。  

> 在公司里面我做了很多的事情,也尝试了很多的新方向,但却没有一个方向上做到“很深、很强、很值钱”。

尤其作为一名人工智能算法开发工程师,这是一件危险的事情,因为这与过去的工作模式截然不同。因此,

> 🔧 万能螺丝钉不是万能药,而是焦虑症的缓释剂。 

> 🧠 真正让人不可替代的,是“你在某件事上比别人更懂”。

🚨 技术人深陷“全能陷阱”的三重危机

1️⃣ 沉没成本陷阱:累积的是“经验”,而不是“能力”

会议协调、流程整合、文档撰写看起来在产出,但没有形成系统性的、可迁移的技术成长。你写了很多,却没法在下一个岗位直接用上。各种周报、月报的汇总和整理更是耗费了大量的时间和精力,以至于在技术上没有很深的沉淀和积累。即使在技术上有投入,那也是均分在客户端、前端、后端、数据库、数据分析、算法等技术领域中,没有办法深入人工智能这个领域专注地做算法研究与开发工作。

2️⃣ 稀释注意力陷阱:广撒网,却钓不到鱼

涉及的技术领域太多,每一个都只停留在工具调通、逻辑理解的阶段,无法对核心算法深入挖掘或重构优化,不能成为某个领域的专家。所谓的客户端、前端等方向,更多的是使用ChatGPT等工具进行开发,浅尝则之,对于有一定技术深度的问题就无法解决。技术能力不会比ChatGPT更高明。而对于人工智能这个方向,由于数据平台的限制,也没有办法在原有公司的基础上更进一步,更多的则是在开源项目上修修补补,拿来即用而已。

3️⃣ 价值识别陷阱:外人看不出你真正“擅长什么”

你解决了很多问题,但简历上写不出来;你做了很多项目,却没有能代表个人标签的关键成果。用人部门也难以对你定位和信任。每一个人的精力都是有限的,一个号称能够从事客户端、前端、后端、数据库、数据分析、算法的人,他肯定是什么都做,但是什么都不精通,所开发的工具和平台也仅仅是能够做到能用而已,有技术难度的事情依旧做不了。在面试的时候,外人也很难看出你更加擅长什么方向,只能把你看成一个万金油的工程师,但是在求职的时候,其方向匹配会显得尤为重要。尤其是高级别的员工,别人更加关注的是你的技术深度,而不是技术广度。

🚪 如何破局?给“算法工程师”的几点建议

✅ 1. 设定一个“技术锚点”,先深挖一个方向

从你现在的工作内容中挑一个主攻方向,比如:

  • 推荐系统
  • 计算机视觉
  • NLP与大模型调优
  • 机器学习与数据分析
  • 多模态学习

为这个方向定一个半年目标,从底层原理、主流框架、调参技巧、线上应用、性能优化都走一遍。构建“深度认知+实战成果”体系。

📌 建议:  

建立个人的主题技术文档,将每次的学习/阅读/调试/复现都记录在案,便于后续其他项目的复用与分享。

✅ 2. 打造一个“沉淀型项目”而非“消耗型项目”

这两个项目的最重要区别就在于:

  • 消耗型项目:你完成它,它就结束了。
  • 沉淀型项目:你做完了,它还可以复用、分享、维护、传播。

比如:

  • 一个可开源的数据处理 pipeline
  • 一个小规模但结构完整的推荐系统 Demo
  • 一份行业内冷启动策略的白皮书
  • 或者一个完整的模型调优实践案例

📌 建议:  

在信息安全以及符合公司规范的前提下,通过写博客、发知乎、发arxiv、发论文等方式,让你的项目“被看见”,这对提升个人的技术影响力和个人品牌至关重要。判断领导是否培养你也可以用类似的评价方法,如果领导把你当做消耗型人才,那么就不会关心你的个人成长,会阻碍你参加培训等事情,只会关心你是否完成了工作;如果领导把你当做培养型人才,那么在完成了工作的同时,还会告诉你要花点时间提升自己。回想起来,之前在第一家公司的时候,领导和导师都非常关注员工的成长,会让员工自己留一定的时间进行自学或者参加培训,甚至会告诉员工不要把所有的时间都投入到业务中。但是在过去的两年里面,领导则是把员工当成一次性的消耗品,只需要完成工作就可以,在工作时间组织和参与技术培训是万万不行的,领导会想尽办法阻止员工在工作时间参加技术培训。

✅ 3. 为自己建立“技术护城河”而非“忙碌记录”

如果手账是你的“战斗日记”,那你也该为自己建立:

  • 📚 技术知识库(如云文档、云笔记、GitHub的Readme)
  • 📊 技术沉淀列表(写过哪些模型、调优过哪些参数、踩过哪些坑)
  • 🗣️ 技术输出矩阵(博客、分享、内训、答疑)

📌 建议:  

让自己的每一段探索都有“痕迹”,哪怕是思维图、配置模板、复盘文档,都比“会议记录”更值得保留。会议记录由于信息安全等因素,无法做到对外传播。但是在其过程中的思维方式、技术成长,却能够有效地形成自己的技术护城河。

✅ 4. 将自己“产品化”:建立可传递的价值链

技术人可以也应该具备“产品化思维”:你不仅要能完成任务,还要能提炼价值优化体验延续影响力。在工作之余,请你认真的想一想,你能否:

  • 让自己的某段算法调优经验写成“内部小册子”;
  • 将你在模型上线过程中的流程沉淀为“复用模板”;
  • 把一次模型性能突破变成“团队能力的提升”;

📌 建议:  

定期复盘:我最近做的哪些工作“留下了东西”?哪些只是“完成了任务”?长期来看,这两个区别会非常大。每个人在工作中,除了赚到钱,更重要的是让自己更加值钱

💡 写在最后:不是拒绝广度,而是拒绝无效广度

“什么都能做”很好,但更重要的是—— 

你有没有一个明确的标签,一个可以对外被识别、被依赖、被信任的核心方向。

万能螺丝钉不是错,但你必须先是“标准件”,才能扩展为“万用件”。

“在成为一个通才之前,先成为一个专家。”

祝你我都能从“手账记录者”走向“技术建设者”,做出真正属于自己的技术资产与个人品牌

职场管理与员工关怀:职场中的双向平衡之道

在很多传统行业中,会产生一群从基层一步步走上来的领导者,他们凭借多年的行业经验和扎实的技术背景,逐渐承担起了企业团队的管理职责。这些管理者的年龄一般都在40岁以上。这种从底层到高层的职业轨迹,虽然充满了奋斗和拼搏的故事,却也潜藏着一些职场问题,或许会影响着团队的工作氛围和新员工的自我发展。

这类管理者通常对工作要求非常高,认为通过自身的艰苦努力和不懈奋斗,尤其是与人斗争,只要解决人就能够解决一切问题。在这种工作氛围下,管理者常常促使他们对团队成员也提出类似的期望。他们希望员工像自己一样投入工作,导致员工常常没有明确的工作与生活边界,工作日和周末加班成了常态。如果这些管理者的家庭生活一般的话,通常就会在工作上投入更多的精力,以至于会持续对员工们会提出越来越高的要求,例如在工作期间常常会提到“xx连续三个月工作到凌晨”、“yy凌晨四点还会去敲供应商的家门”、“zz团队最近走得太早了,需要在下班之后增加培训和会议增加工作时长”。这样的工作氛围一定会使员工感到疲惫和不满,久而久之,员工的工作积极性和满意度会逐渐下降,导致离职率也开始上升。

这类管理者的管理风格也往往忽视了团队成员的情感需求和心理健康。管理者会给员工非常大的压力,并且员工没有自我疏导的渠道。在长时间的工作压力下,员工们都缺乏足够的休息时间和心理调节空间,而管理层的关注点更多集中在如何提高完成任务的质量和数量上。员工的个人需求和情感关怀常常被忽略,导致团队的工作氛围的紧张,团队的凝聚力逐渐削弱。在领导层与员工的沟通中,领导层会想办法打听员工的家庭条件、住宿情况、贷款情况等一系列事情,当然这并不是在关心员工,而是在看员工是否存在所谓的软肋,以至于可以被领导层利用。因此,员工学会保护自己的隐私也是一件工作大事。在领导层与员工的互动中,这类领导通常只会关注自己的想法,导致普通员工的意见往往难以得到重视,领导层更多关注的是任务的达成,而非团队的情感认同和创造力的激发。久而久之,员工们会感到被冷落,甚至产生工作被机器化的情绪,工作热情和创造力都会逐渐下降。

在现代职场中,有的管理者甚至会说出“这种培训让员工学会了,他们就跑了。作为员工只需要完成工作就可以了,不需要学那么多东西”、“我根本不在乎员工走不走,他走之前把东西做完然后留下就好了”、“工作时间参加培训就是工作量不饱和”、“开会要使用下班时间,不要耽误上班的时间”这样的话语。用现代管理的理论来看,这种逻辑是完全不通的。管理者必须意识到,员工不仅仅是完成任务的工具,他们是团队持续发展和创新的核心驱动力。若只是单纯地将员工视为消耗品,忽略他们的成长与发展,团队最终会陷入低效与创新不足的困境。相反,通过培养员工,帮助他们不断提升技能,才能确保团队始终保持竞争力,推动企业迈向更高的目标。领导层甚至可以用以前员工的过往成功经历来持续激励后来的员工,培养出高级别的选手远比简单的任务分配更为重要。在培养的过程中,员工不仅能完成工作任务,更能在成长过程中为团队带来更多的价值。通过有针对性的培训和职业发展规划,领导者可以激发员工的潜力,让他们在工作中不断突破自我,为公司创造更多的创新机会和业务成果。这种投资并不会导致员工流失,而是能帮助企业建立起更强的内在竞争力,提升员工的忠诚度和归属感。

这类管理者的决策通常基于多年积累的经验,固守传统的管理模式,例如通过高压力的方式对员工进行管理,并且筛选出一批忠诚度高、身体好的、能力强、能够抗压的员工。在行业发展的浪潮中,他们会一直坚持原有的做事方法和沟通策略。虽然这种经验在一定程度上帮助他们解决了许多现实工作问题,但也容易陷入对创新的抵触和对新技术的怀疑,总觉得原有的技术是必须要做的,新的技术也只是锦上添花而已。这种保守的管理态度,会导致管理层和新员工的理念脱节,并且新员工也后续的工作中不再提出任何创新和改善的意见。

这种管理模式虽然可以让管理层在短期内完成既定目标,但长期来看,企业和团队的活力和创新性将受到制约。如果没有及时调整管理思路、优化工作方式,团队将面临员工流失、凝聚力下降、创新能力不足等一系列问题。职场中,如何在追求效率的同时,给予员工足够的关怀与支持,如何在坚持经验的同时,拥抱创新和变革,已经成为很多团队面临的难题。通过平衡高要求与员工需求,调整工作节奏和管理风格,才能在保证业绩的同时,维持团队的活力和稳定,推动团队走向更长远的发展。

如果整理成表格的话,那可以整理出领导和员工的诉求,并且提供相对折中的解决方案。

领导的诉求员工的诉求解决方案
工作产出和任务完成工作与生活平衡,避免过度加班制定合理的工作时间表,避免长时间过度加班,设立清晰的工作与生活边界。尽量能够保证员工能够双休,而不是在周末还持续让员工处理工作、进行团建、组织开会等一系列事情。不要过度宣传高强度工作,不要强调周末加班、凌晨三点还在进行工作等一系列事情。
员工全身心投入工作,保持高度的自律和执行力合理的工作压力,更多的心理支持和情感关怀提供心理健康支持、在工作日(非周末)定期举行团队建设活动,增强员工的归属感和情感认同。
团队成员遵循传统的工作模式,按既定流程执行工作参与决策和创新的机会,能够表达个人意见建立开放的沟通渠道,鼓励员工提出创新意见并参与到决策过程中,帮助员工解决问题,并将合理的意见融入到团队的管理中。
强调高要求和高标准,期望员工能像自己一样投入工作合理的工作负荷和多样的职业发展机会管理者需要设立明确的职业发展路径,提供必要的职业培训,并且允许员工在工作时间进行自我能力的提升,鼓励员工通过自学和使用公司资源提升自我能力,需要帮助员工管理压力。
快速完成任务,确保生产效率感受到被领导和团队支持与认可定期进行绩效反馈,注重正面激励,适当减少负面刺激,同时认可员工的努力和贡献,提供必要的物质或者非物质的奖励机制。
传统经验的延续与工作方式的坚持更现代化的工作环境和技术支持,期望与时俱进管理层需要引入新技术和现代化管理方法,推动团队内部的创新文化,定期进行技术培训和管理理念更新。
解决问题时依赖于自身经验需要更好的沟通与合作,期望被尊重和理解加强与员工的沟通,定期召开团队会议,鼓励团队合作与跨部门协作,尊重员工的建议和意见,并且在员工提出意见之后不会打压员工。
重视工作任务完成感受到工作的多样性和挑战性,期望获得更多成长机会提供更多的跨部门沟通和项目管理机会,丰富员工的工作内容,提升员工的技术实力,激励员工不断学习和提升自我。而不只是把员工当做完成工作的工具,需要让员工觉得在工作期间就能够得到能力的提升。
高压管理,重视任务执行力更加宽松的工作环境和团队支持在高压工作中增加休息与放松时间,提供心理疏导和情感支持,同时减少不必要的工作压力,不需要时时刻刻都让员工们处于紧绷的状态
通过传统管理方式维持组织运作更多的自主性和创新空间鼓励员工提出新的想法并参与到公司改革中,推行更灵活的管理模式,在合适的范围内赋予员工更多的自主决策权。

在人性化的员工管理中,企业需要把员工放在企业发展的核心位置,而非仅仅作为完成任务的工具。真正以员工为本的管理,是把员工当做根本,而不是把员工当做资本。不仅关注员工的工作表现,更注重他们的成长和心理需求。通过提供职业发展的机会、培养他们的技能和潜力,企业能够激发员工的创造力和忠诚度,形成更紧密的团队合作与更高的工作效率。当员工感受到被尊重、被重视,他们会更加积极主动地为企业贡献力量,而不仅仅是完成工作任务。这种人性化的管理方式能够帮助企业打造一个更加稳固且有活力的团队,推动公司持续健康地发展,走得更远,走得更稳。

星辰大海,同心同行:从员工的敬业度谈起

近几天笔者在参加培训,第一次听到员工敬业度(Employee Engagement) 这个词语,它是指员工对工作、团队、公司以及其文化的情感投入和积极态度。在培训课堂上,老师说敬业度衡量的是员工对公司目标、价值观的认同感,是否愿意在工作中付出额外努力,是否对工作充满热情,是否感到自己在组织中的贡献被重视,以及是否有动力帮助公司实现长期成功。

在一个公司里面,高度敬业的员工通常会表现出以下特征:

  1. 主动投入:他们不仅完成基本工作,甚至还愿意为公司额外付出和承担更多的责任。
  2. 情感承诺:他们与公司的价值观和使命高度契合,感到自己是公司的一部分。
  3. 积极参与:他们在日常工作中积极参与、提供建议,并努力提升团队和公司的表现。
  4. 忠诚度高:他们更愿意长期在公司工作,且通常会推荐公司给外部人才或将公司的产品推荐给消费者。

但是,在如今竞争激烈的职场中,职场人士通常会感受到多种完全不同的职场文化和企业文化。在消费市场中,作为消费者的我们也常常会遇到多种截然不同的公司文化和品牌形象。作为消费者和员工,我们的感受往往是最真实的反馈。当笔者思考自己为何总是乐于向亲朋好友推荐T公司,而对B公司却总是持保留态度时,心中涌现出许多不同的思考。这不仅仅是公司产品的优劣,更是公司文化、员工敬业度的直接反映。

T公司:我愿意主动宣传,因为我真的认可

从我个人的经验来看,T公司给我的第一印象就是充满活力和创新,一切以保障用户的价值为基础。作为一名普通的消费者,我自然而然地从一开始就会使用T公司的一系列产品,并且在试用后,会毫不犹豫地购买了会员,甚至开始充值和支持更多的周边产品。这个过程并非出于打广告或推销,而是因为我真心喜欢并认可T公司所提供的价值和产品服务。

T公司不仅让我在使用产品时感受到便捷和高效,还让我在日常生活中逐渐形成了对其品牌的情感认同。每当朋友向我询问某个产品推荐时,我总是第一时间推荐T公司,而不仅仅是因为它是我用过的最好产品之一,更因为T公司背后传递出来的企业文化深深打动了我——一种注重创新、追求卓越、关心员工、尊重普通消费者和用户的企业文化。作为一名员工,我也能感受到这种文化的传递,无论是工作中的支持与尊重,还是团队间的协作与信任,都让我愿意为T公司贡献更多的力量。

在T公司,即使离职的员工,也很少会说出任何负面的言论。因为离开并非出于对公司企业文化的怨恨,而是个人发展的选择或者团队的被动调整。T公司为员工提供了足够的成长空间和尊重,内部经常戏称为“T大学”。这样的企业文化和氛围,让每个曾经为其效力的人都能带着美好的回忆离开,甚至成为T公司未来的忠实用户和支持者。尤其是在其他公司工作过之后,会发现T公司的企业文化真的是行业天花板

B公司:我选择避雷,甚至劝朋友远离

相比之下,B公司给我的体验则截然不同。虽然我在初次接触时也有过短暂的尝试,但很快就发现,这家公司在员工关怀、用工福利和企业文化等方面都远远不如T公司。员工只是被当做耗材而被使用,在人才培养方面几乎等于零。后续当有亲朋好友问我相关产品的时候,我不仅没有主动使用B公司的产品,甚至在朋友要购买其产品时,我会出于好意劝他们避开这家公司。

B公司产品普普通通,内部工作流程和同事素质也经常让人抓狂,甩锅推活等事情非常常见。而更让我无法接受的,是其背后令人沮丧的企业文化。B公司似乎并不注重员工的成长和幸福,也缺乏员工关怀,同时缺乏有效的激励机制,导致员工的敬业度和忠诚度普遍较低。很多离职员工在离开后纷纷开始吐槽公司,甚至对公司有着极大的不满,许多人都在社交平台上发表过他们的负面情绪。他们不仅吐槽公司的企业文化,还会吐槽公司的福利制度,就属于那种能扣就扣的类型,任何福利制度(工资发放日、公积金、社保、医保、育儿假等)都是按照最低标准来支付的。这样的福利制度氛围无形中让我对这家公司产生了深深的不信任感。

在B公司工作的日子里,我很难感受到自己作为员工的价值,常常觉得自己像是一个领导们被利用的工具,而不是一个被尊重的伙伴。领导经常说的话就是“扣工资”,仿佛只会用扣员工工资这件事情来管理团队和员工。领导对社招和校招的同事没有足够的关怀,只会让新同事来做很多重复且没有提升的事情,或者做一些很简单的事情且没有让人成长的事情。一旦出现问题,领导除了给员工压力之外,并没有任何有效的意见或者改进方案,一切只会让员工来自行解决。员工也无法从公司学到新的技术和技能。

而且,按照B公司的企业文化和做事风格,如果让B公司来调查员工的敬业度,大概就会这样调查并且考核员工:

1. 主动投入:考核员工的加班时长以及是否在周末主动义务加班在B公司,敬业的员工不仅仅要在工作时间内完成任务,还需要在没有加班费的情况下,把周末奉献给公司。毕竟,真正的敬业就是永不离开办公桌,哪怕周六周日也要主动来义务加班。调查问卷中会问你:“你是否自愿在周末加班,且能忍受没有任何奖励的加班文化?”如果你的回答是“当然”,那你就是公司最敬业的员工!

2. 情感承诺:考核员工周末团建、是否购买公司产品等;即使是去KTV喊麦,去野外露营,哪怕是看似毫无意义的活动,也要拼尽全力参与。至于是否购买公司产品,显然,做一个“忠实客户”是对公司最深的情感承诺——你买了,说明你爱公司;你不买,可能就“不够敬业”了。甚至,他们还会问你:“你是否已经购买了公司周边产品,并在社交平台上积极展示?”

3. 积极参与:考核员工的会议次数、代码行数、提意见次数等工作指标;B公司认为,工作就是要让员工不断出力。无论是参加会议,还是写代码,亦或是提交意见,他们都有详细的“量化标准”。“你是否参加了本月的所有会议?”“你每月提交的代码行数达到多少?”“你在团队讨论中提过多少次建设性意见?”如果你能回答“无数次”,那你就是公司中的“积极分子”。至于实际贡献如何,没人关心,数字才是王道。

4. 忠诚度高:考核员工是否在朋友圈、微博等社交媒体上转发公司的宣传稿,转发次数和转发天数等。真正的忠诚度在B公司不仅仅是体现在工作上,更重要的是你在朋友圈、微博、抖音等社交平台上的宣传表现。调查问卷上这样问:“你是否转发了公司的宣传稿?转发次数达到多少次?转发的天数是多少?”如果你能保持每日转发公司的活动信息,哪怕是最无聊的产品更新,你就是公司最忠诚的社交大使。毕竟,离职后不在社交媒体上发牢骚,也算是对公司最大的忠诚了。

在B公司,很多离职的员工都没有美好的回忆,反而带着一种被消耗的疲惫感和厌倦感。在这样的公司,给人的感觉就是哪里都不好,所以自然我也不会愿意主动去宣传它,反而在身边的朋友询问的时候,我会立刻劝他们避开B公司的产品。

员工敬业度:从工作到生活,态度至关重要

员工的敬业度,直接影响到我们对公司的认同感、忠诚度以及对其产品和服务的支持程度。对于T公司,我之所以乐于推荐其产品,不仅仅是因为它的产品质量优秀,更因为它的员工敬业度极高,大家都充满了对公司使命的认同感和对未来的信心。员工能够感到公司对员工所做出的努力,同时员工也在为公司的成长付出,而这种心态深深感染了作为消费者和员工的我。

而B公司,员工的敬业度普遍较低,在日常的工作中大家只是机械地完成任务,对于创新一类的事情并不敢兴趣,毕竟做好了也没有任何收益,做坏了反而有处罚。大家都缺乏对公司文化和未来的认同,有的员工也想离开,只是因为自身能力不够无法离开而已。能力强的员工流失严重,并且很多人在离职都带着负面情绪离开,事后甚至吐槽公司管理层的无能与冷漠。

结语:选择与认同,源自内心的敬业度

当一个公司的员工都能自豪地为其代言,并且在离开时依然怀有对公司的美好记忆时,这家公司一定是拥有强大内力的。T公司让我感受到了这种正能量,作为员工我感到自豪,作为消费者我愿意为其买单。反观B公司,缺乏真正的文化底蕴和员工的敬业精神,即使它的产品销量再高,作为离职员工也不会主动去为其代言。我劝朋友避雷,只是因为不想他们走上我曾经走过的弯路——这家公司的企业文化和员工敬业度,注定了它无法获得长期的成功,或许只能够做到昙花一现。

公司文化不仅仅影响着员工的敬业度,也深深影响着消费者的认同感。在选择公司时,我们不仅看重产品,更看重的是它背后的理念、价值观、企业文化和员工的敬业度。真正的企业,能够通过员工的忠诚与敬业,赢得消费者的认可与支持,最终实现双赢。正所谓,星辰大海,同心同行。