写在前面
- 博文内容为基于 LangChain 数据增强 和 Ollams 本地部署 DeepSeek-R1
- 实现 K8s运维文档检索与问答系统 Demo
- 通过 Demo 对
LEDVR 工作流
,语义检索
有基本认知 - 理解不足小伙伴帮忙指正 😃,生活加油
我看远山,远山悲悯
持续分享技术干货,感兴趣小伙伴可以关注下 _
Ollama 部署 DeepSeek-R1
过 Ollama
在本地部署 DeepSeek-R1
蒸馏模型,通过 langChain
调用,下载模型,启动 Ollama
服务
PS C:\Users\Administrator> ollama list
NAME ID SIZE MODIFIED
deepseek-r1:latest 0a8c26691023 4.7 GB 3 seconds ago
deepseek-r1:32b 38056bbcbb2d 19 GB 2 weeks ago
deepseek-r1:14b ea35dfe18182 9.0 GB 2 weeks ago
deepseek-r1:8b 28f8fd6cdc67 4.9 GB 2 weeks ago
bge-m3:latest 790764642607 1.2 GB 2 weeks ago
PS C:\Users\Administrator> ollama serve
Error: listen tcp 127.0.0.1:11434: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.
PS C:\Users\Administrator> ollama serve
2025/03/09 01:22:39 routes.go:1187: INFO server config env="map[CUDA_VISIBLE_DEVICES: GPU_DEVICE_ORDINAL: HIP_VISIBLE_DEVICES: HSA_OVERRIDE_GFX_VERSION: HTTPS_PROXY: HTTP_PROXY: NO_PROXY: OLLAMA_DEBUG:false OLLAMA_FLASH_ATTENTION:false OLLAMA_GPU_OVERHEAD:0 OLLAMA_HOST:http://127.0.0.1:11434 OLLAMA_INTEL_GPU:false OLLAMA_KEEP_ALIVE:5m0s OLLAMA_KV_CACHE_TYPE: OLLAMA_LLM_LIBRARY: OLLAMA_LOAD_TIMEOUT:5m0s OLLAMA_MAX_LOADED_MODELS:0 OLLAMA_MAX_QUEUE:512 OLLAMA_MODELS:C:\\Users\\Administrator\\.ollama\\models OLLAMA_MULTIUSER_CACHE:false OLLAMA_NOHISTORY:false OLLAMA_NOPRUNE:false OLLAMA_NUM_PARALLEL:0 OLLAMA_ORIGINS:[http://localhost https://localhost http://localhost:* https://localhost:* http://127.0.0.1 https://127.0.0.1 http://127.0.0.1:* https://127.0.0.1:* http://0.0.0.0 https://0.0.0.0 http://0.0.0.0:* https://0.0.0.0:* app://* file://* tauri://* vscode-webview://*] OLLAMA_SCHED_SPREAD:false ROCR_VISIBLE_DEVICES:]"
time=2025-03-09T01:22:39.303+08:00 level=INFO source=images.go:432 msg="total blobs: 14"
。。。。。。。。。。。。。。。。。。。。。。。。。。。。
time=2025-03-09T01:22:39.448+08:00 level=INFO source=types.go:131 msg="inference compute" id=GPU-e65029a6-c2f9-44b1-bd76-c12e4083fa4c library=cuda variant=v12 compute=8.6 driver=12.8 name="NVIDIA GeForce RTX 3060" total="12.0 GiB" available="11.0 GiB"
LangChain 数据增强模块
LangChain 的数据增强模块是构建大语言模型(LLM)应用的核心组件,专注于整合、优化外部数据
以提升模型输入的精准度与效率。
该模块通过文档加载器(Document Loaders)
从多源数据(如PDF、数据库、网页)
中提取内容
并标准化为结构化文档
。针对长文本或复杂格式问题,内置的文档转换器(Document Transformers)支持切割、合并、过滤
等操作。
同时,模块还通过向量存储(Vector Stores)和检索器(Retrievers)
实现数据的高效管理
,利用嵌入模型
将文本转换为向量
,构建语义检索能力
,从而在用户提问时快速定位相关片段作为上下文注入提示词模板
。
与LLM
的协作流程形成检索增强生成(RAG)
范式:外部数据经加载、转换、存储后,结合用户问题生成动态提示词
,通过模型包装器调用底层API并解析输出。其典型应用包括长文本摘要(如法律条款分析)、知识库问答(精准召回专业内容)以及实时数据更新(定期抓取网页信息并同步向量库)
。通过模块化设计,LangChain
大幅简化了异构数据处理复杂度,为开发者提供灵活、可扩展的LLM应用支持。
LEDVR 工作流
数据增强模块是一个多功能的数据增强集成工具,一般称作 LEDVR
其中:
L
代表加载器(Loader)
E
代表嵌人模型包装器(Text EmbeddingModcl)
D
代表文档转换器( Document Transformers)
V
代表向量存储库( VectorStore )
R
代表检索器(Retriever)
加载器
负责从各种来源加载数据作为文档,其中文档是由文本和相关元数据组成的。无论是简单的.txt 文件,还是任何网页文本内容,加载器都可以将它们加载为文档。
嵌人模型包装器
一个专为与各种文本嵌人模型(如 OpenAI、Coherc、HuggingFace
等)交互而设计的类。它的作用与模型 I/O 模块
的 LLM 模型包装器
和聊天模型包装器
一样,用于通过嵌入模型生成向量
文档转换器
主要用来对文档进行切割、组合、过滤等各种转换
。文本切割器(RecursiveCharacterTcxtSplitter)
是最常见的文档转换工具。文档转换器的目的是将加载的文档转换为可被嵌入模型包装器操作的文档数据格式
。
向量存储库
是用于存储和检索嵌入向量
的工具,处理的数据是通过模型平台的文本嵌人模型(Text Embedding Mode1)转换的向量数据
,这是处理非结构化数据的-种常见方法。向量存储库负责存储嵌入数据并执行向量检索
。在检索时,可以嵌入非结构化查询,以检索与嵌入数据“最相似”的嵌入向量。
检索器
是一个接口,返回非结构化查询
的文档。它比向量存储库更通用。检索器
无须存储文档,只需要返回(或检索)文档
。
K8s运维文档检索与问答系统 Demo
下面为一个基于 LEDVR 工作流(Loader → Embedding → Document Transformers → VectorStore → Retriever)与本地部署 Ollama 的完整代码示例
Demo
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@File : demo_LEDVR.py
@Time : 2025/03/15 04:30:36
@Author : Li Ruilong
@Version : 1.0
@Contact : liruilonger@gmail.com
@Desc : None
"""# here put the import lib
#pip install langchain langchain-community ollama -i https://pypi.tuna.tsinghua.edu.cn/simple
#pip install faiss-cpu
#pip install pypdf
#pip install "unstructured[md]"import nltk
#nltk.download('averaged_perceptron_tagger')from langchain.prompts import PromptTemplate
from langchain_community.document_loaders import UnstructuredMarkdownLoader
from langchain_text_splitters import TokenTextSplitter
from langchain_community.embeddings import OllamaEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_community.llms import Ollama
from langchain.chains import RetrievalQA
import warningswarnings.filterwarnings("ignore") # 忽略嵌入模型警告#### 1. 加载md文档 L 加载器
print("=============开始加载md文档")
loader = UnstructuredMarkdownLoader("K8s面试系列:K8s常用API资源总结速记 .md")
documents = loader.load()print(len(documents))#### 2. 文档转换器 (Document Transformers)
# 2. 按token分块
print("=============按token分块")
text_splitter = TokenTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = text_splitter.split_documents(documents)
print(f"有效分块数: {len(chunks)}") # 应大于0if not chunks:raise ValueError("文档分块失败!请检查原始文件内容和分块参数。")print(len(chunks)) #### 3. 嵌入模型 (Embedding)
print("=============嵌入模型")
embeddings = OllamaEmbeddings(model="bge-m3", # 支持的模型包括bge-m3base_url="http://localhost:11434" # 默认端口11434
)#### 4. 向量存储库 (VectorStore)
# 构建本地 FAISS 向量数据库
vector_db = FAISS.from_documents(chunks, embeddings)#### 5. 检索器 (Retriever)
# 配置 Top-3 相似度检索
retriever = vector_db.as_retriever(search_kwargs={"k": 3})### **集成 Ollama 本地模型**
# 配置本地 DeepSeek R1 模型(需提前通过 Ollama 下载)
llm = Ollama(base_url='http://localhost:11434',model="deepseek-r1:latest"
)prompt_template = """基于以下上下文回答问题:
{context}
问题:{question}
答案(不超过4句话):"""# 构建问答链
qa_chain = RetrievalQA.from_chain_type(llm=llm,chain_type="stuff",retriever=retriever,chain_type_kwargs={"prompt": PromptTemplate.from_template(prompt_template)},return_source_documents=True
)# 执行查询
question = "K8s 中准入控制器资源有哪些?"
response = qa_chain.invoke({"query": question})# 输出结果
print("回答:", response["result"])
print("参考来源:")
for doc in response["source_documents"]:print(f"- {doc.page_content[:80]}...")
下面为实际的输出示例
PS C:\Users\Administrator\Documents\GitHub\LangChainDemo> & C:/Users/Administrator/AppData/Local/Programs/Python/Python310/python.exe c:/Users/Administrator/Documents/GitHub/LangChainDemo/demo/demo_LEDVR.py
[nltk_data] Downloading package averaged_perceptron_tagger to
[nltk_data] C:\Users\Administrator\AppData\Roaming\nltk_data...
[nltk_data] Package averaged_perceptron_tagger is already up-to-
[nltk_data] date!
=============开始加载md文档
1
=============按token分块
有效分块数: 86
86
=============嵌入模型
回答: <think>
嗯,我现在要回答关于K8s中准入控制器资源的问题。根据提供的上下文,我看到有几种不同的准入控制器,比如ValidatingAdmissionPolicy、ValidatingWebhookConfiguration和NetworkPolicy。
首先,ValidatingAdmissionPolicy是在K8s 1.30版本中发布的,用于在资源被创建、更新或删除时执行验证逻辑。它应用到apps/v1组中的deployment资源,并且拒绝请求如果副本数超过5。
然后是ValidatingWebhookConfiguration,这个结构包含一个配置和一个认证,允许从服务或其他地方发送钩子调用到容器注册表中。这意味着当服务发布到K8s的时候,会自动触发这些钩子,这在扩展性方面很有帮助。
接下来是NetworkPolicy,这是一组策略,可以定义网络的白名单规则。比如,允许特定IP范围和端口下的流量通过。虽然Flannel不支持它,但其他插件如Calico、Cilium等支持,并且这些插件可以集成到K8s中使用。
还有ResourceQuota,用于限制命名空间中的资源使用。这是一种策略,可以在集群级别限制CPU、内存等资源的使用,有助于确保资源分配公平。
总结一下,准入控制器资源包括ValidatingAdmissionPolicy、ValidatingWebhookConfiguration和NetworkPolicy,这些都是用来控制和管理K8s资源的工 具。
</think>在K8s中,准入控制器资源主要用于控制和验证API请求。以下是一些常见的准入控制器资源及其用途:1. **ValidatingAdmissionPolicy**:- **版本信息**:发布于K8s 1.30。- **用途**:应用于特定的资源类型(如Deployments),在资源被创建、更新或删除时执行验证逻辑。- **示例策略**:限制部署的副本数不超过5个。2. **ValidatingWebhookConfiguration**:- **结构**:包含一个配置和一个认证,用于允许从服务或其他位置发送钩子调用到容器注册表中。- **用途**:简化服务发布流程,自动触发钩子调用。3. **NetworkPolicy**:- **支持的工具**:Calico、Cilium、Weave Net等插件支持,并可集成到K8s中。- **用途**:定义网络的白名单规则,允许特定IP范围和端口下的流量通过。4. **ResourceQuota**:- **功能**:限制命名空间中的资源使用,如CPU和内存,确保资源分配公平。这些资源共同作用,帮助实施集群级别的安全和管理策略。参考来源:
- 个新的准入控制器,定义自定义的验证逻辑,在资源被创建、更新或删除时执行。K8s 1.30 发布正式版本yaml apiVersion: admissionr...
- .1.0/24 - namespaceSelector: #命名空间限制 matchLabels: project: myproject - podSelect...
- title: K8s面试系列:K8s常用 API 资源总结速记 tags: - Kubernetes categories: - Kubernetes toc:...
PS C:\Users\Administrator\Documents\GitHub\LangChainDemo>
可以看到答案对于这本地运行的蒸馏模型,并且只有几十行代码来实现的功能来说以及很不错了。
下面部分为加载的文档中的内容的简单摘要,这是我之前写的一篇博文,可以看到通过一个简单的Demo检索的答案很接近
…
–#### ValidatingAdmissionPolicy
一种类似 Admission Webhook
的声明式配置方式。ValidatingAdmissionPolicy
是 K8s 1.26
版本引入的一个新的准入控制器
,定义自定义的验证逻辑,在资源被创建、更新或删除时执行。K8s 1.30
发布正式版本
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:name: "demo-policy.example.com"
spec:failurePolicy: Fail # Fail表示如果验证失败,则拒绝请求。matchConstraints: #定义哪些API请求应该被此策略验证。resourceRules:- apiGroups: ["apps"]apiVersions: ["v1"]operations: ["CREATE", "UPDATE"]resources: ["deployments"]validations: # 具体的验证规则- expression: "object.spec.replicas <= 5" # 验证部署(Deployment)对象的副本数(replicas)是否小于或等于5。
这个策略将应用于所有对apps/v1组中deployments资源的CREATE和UPDATE操作,并且会拒绝任何副本数超过5的部署请求。
前面讲到的 ValidatingWebhookConfiguration
和 ValidatingAdmissionPolicy
都是 Kubernetes 中的准入控制机制,但它们在设计和使用方式上有一些重要区别:
…
…
关于上面的关键组件做说明
模块 | 技术实现 | 优势说明 |
---|---|---|
Loader | UnstructuredMarkdownLoader md 格式文档加载 | 统一处理 md 格式 |
Document Transformers | 递归字符分块法保留上下文语义 | 解决长文本 token 限制问题 |
Embedding | bge-m3 轻量化模型 | 本地部署无需 API 密钥 |
VectorStore | FAISS 高效向量检索 | 支持毫秒级相似度匹配 |
Ollama | DeepSeek R1 7B 量化版 | 消费级 GPU 即可运行 |
这里我们在看一个有报错信息的 Demo
.............................
loader = UnstructuredMarkdownLoader("Kubernetes 触发 OOMKilled(内存杀手)如何排除故障.md")
...................
# 执行查询
question = """```bash
┌──[root@vms100.liruilongs.github.io]-[~/ansible/oomkiller]
└─$kubectl apply -f oom-killer-pod.yaml
pod/oom-killer-pod created
┌──[root@vms100.liruilongs.github.io]-[~/ansible/oomkiller]
└─$kubectl get pods oom-killer-pod -w
NAME READY STATUS RESTARTS AGE
oom-killer-pod 0/1 ContainerCreating 0 7s
oom-killer-pod 1/1 Running 0 25s
oom-killer-pod 0/1 OOMKilled 0 28s
oom-killer-pod 0/1 OOMKilled 1 (18s ago) 45s
oom-killer-pod 0/1 CrashLoopBackOff 1 (13s ago) 57s
oom-killer-pod 0/1 OOMKilled 2 (29s ago) 73s
/```
上面的报错是什么原因?如何解决?
"""
response = qa_chain.invoke({"query": question})# 输出结果
print("回答:", response["result"])
print("参考来源:")
for doc in response["source_documents"]:print(f"- {doc.page_content[:180]}...")
PS C:\Users\Administrator\Documents\GitHub\LangChainDemo> c:; cd 'c:\Users\Administrator\Documents\GitHub\LangChainDemo'; & 'c:\Users\Administrator\AppData\Local\Programs\Python\Python310\python.exe' 'c:\Users\Administrator\.vscode\extensions\ms-python.debugpy-2025.4.1-win32-x64\bundled\libs\debugpy\launcher' '55098' '--' 'C:\Users\Administrator\Documents\GitHub\LangChainDemo\demo\demo_LEDVR.py'
[nltk_data] Downloading package averaged_perceptron_tagger to
[nltk_data] C:\Users\Administrator\AppData\Roaming\nltk_data...
[nltk_data] Package averaged_perceptron_tagger is already up-to-
[nltk_data] date!
=============开始加载md文档
1
=============按token分块
有效分块数: 21
21
=============嵌入模型
回答: <think>
好吧,我现在要解决这个Kubernetes中的OOMKilled错误问题。让我先理清楚发生了什么。首先,用户运行了一个Pod,里面装有一个叫bigmem的应用程序,这通常会模拟内存不回收的情况。当他们运行这个Pod时,发现出现了oom-killer-pod的Pod状态,其中有两个OOMKilled日志。根据提供的上下文,这可能是因为内存不足导致系统调用内核中的OOMKiller来终止进程。
我看到用户提到他们使用了_ansible任务,并且在yaml文件中装了一个 bigmem 包。这个包通常会让容器保持大段内存,导致内存泄漏。当Pod的内存消耗超过限制时,Kubernetes会通 过CrashLoopBackOff机制调用OOMKiller来终止进程。
问题是如何解决这个问题。首先,我需要理解为什么会触发OOM错误。这可能是因为内存管理不善,或者Pod的资源设置不当。例如,没有正确设置 pod resource limits 或 container resources limit。
接下来,我应该检查用户生成的 YAML 文件,看看是否正确限制了pod或容器的内存。确保 bigmem 包被正确卸载,并且资源限制足够。
此外,调整容器和pod的资源限制也是一个好方法。比如,为每个容器添加一个适当的 resource Limits,或者将 pod 的资源限制提高到足以运行所有容器,但又不超出系统处理能力。
如果资源限制不足以应对内存泄漏的问题,可能需要重新审视 bigmem 包的配置,看看是否可以适当卸载或优化其内存使用情况。
最后,如果调整资源限制后问题仍然存在,可能需要进一步检查是否有其他进程占用过多内存,或者系统中的内存分配策略是否有问题。此外,确保容器调度器(如Podman)已经正确设置,并且没有其他潜在的内存消耗因素。
总之,解决这个问题的关键在于识别导致OOM错误的根本原因,可能是资源限制不当或内存泄漏,然后相应地调整配置以避免这种情况。
</think>
上面的情况是由于容器内存不回收(bigmem 包的存在)导致系统调用 Kubernetes 的 OOMKiller 功能。OOMKiller 通过终止进程来释放内存。解决方法:
1. 在 pod.yaml 中卸载 bigmem 包:/```yamlresources:bigmem-7.0-1.r29766.x86_64.rpm: null/```
2. 调整 container resource limits,限制每个容器的内存使用:/```yamlcontainers:- image=bigmem-7.0-1.r29766.x86_64.rpmresources:memory: '512MiB'/```
3. 确保 pod resource limits 足够大,以支持所有容器同时运行。通过这些调整,可以避免因内存泄漏导致的 OOMKilled 错误。参考来源:
- ms100.liruilongs.github.io]-[~/ansible/oomkiller] └─$kubectl get pods oom-killer-pod -w NAME READY STATUS RESTARTS AGE oom-killer-pod 0/1 ContainerCreating 0 7s oom-killer-pod 1/1 ...
- /ansible/oomkiller] └─$
对于在生产环境的 Pod ,OOMKilled 常常 伴随这 CrashLoopBackOff,触发 OOM 之后,被 Kill 掉,之后由于 Pod 重启机制,会陷入 CrashLoopBackOff
什么是 OOMKilled K8s 错误
当 Kubernetes 集群中的容器超出其内存限制时,Ku...
- o wide No resources found in resources namespace. ┌──[root@vms81.liruilongs.github.io]-[~/ansible/resources] └─$vim pod-demo.yaml ┌──[root@vms81.liruilongs.github.io]-[~/ansible/re...
PS C:\Users\Administrator\Documents\GitHub\LangChainDemo>
博文部分内容参考
© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知 😃
《LangChain 入门指南构建高可复用、可扩展的 LLM 应用程序》
书籍获取有条件小伙伴可以支持一下原书作者,pdf 版本获取:https://pan.quark.cn/s/2bf8697bf0d2
© 2018-至今 liruilonger@gmail.com, 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)