当前位置: 首页 > article >正文

工业级大模型学习之路021:LangChain零基础入门教程(第四篇):文档加载与文本分块技术

一、文档处理是 RAG 系统的基石1.1 为什么文档处理决定了 RAG 系统的上限RAG 系统的核心逻辑是 **检索相关文档片段 → 喂给大模型生成回答**整个流程的质量完全依赖于文档处理环节如果文档解析失败再好的检索和生成模型也无法获取有效信息如果分块不合理要么检索到的片段上下文不完整要么包含太多无关信息工业级统计显示文档处理环节的优化能带来 30%-50% 的 RAG 回答准确率提升是投入产出比最高的优化点1.2 文档处理的完整流水线一个工业级文档处理流水线包含以下 5 个步骤原始文档 → 文档加载 → 文本清洗 → 文本分块 → 元数据增强 → 分块存储文档加载将不同格式的文件PDF、Word、Markdown 等转换为纯文本文本清洗去除乱码、多余空格、页眉页脚、重复内容等噪声文本分块将长文本切割成适合大模型上下文窗口和检索的小块元数据增强为每个分块添加来源、页码、章节、作者等元信息分块存储将分块和元数据保存到文件或向量数据库1.3 文档加载的核心挑战不同格式的文档有不同的解析难点没有万能的解析工具文档格式主要挑战常见问题PDF扫描件识别、表格提取、页眉页脚去除、跨页断句乱码、表格变成纯文本乱序、图片无法提取Word格式解析、嵌入式对象、修订痕迹格式丢失、批注被当成正文Markdown标题层级解析、代码块处理、链接提取标题层级混乱、代码块被拆分Excel/CSV表格结构解析、多 sheet 处理表格行被拆分、数值格式丢失PPT幻灯片顺序、备注提取、图片文字备注丢失、文本框顺序混乱1.4 文本分块的核心原则分块不是简单的按长度切割必须遵循以下三大原则原则 1语义完整性一个分块应该包含一个完整的语义单元如一个段落、一个知识点避免将一句话或一个概念拆分到两个分块中。错误分块分块1RAG技术的核心思想是将外部知识库检索与大模型生成相结合它可以有效解决大模型的 分块2知识过时和幻觉问题。正确分块分块1RAG技术的核心思想是将外部知识库检索与大模型生成相结合它可以有效解决大模型的知识过时和幻觉问题。原则 2上下文相关性分块大小要与检索粒度和大模型上下文窗口匹配太小丢失上下文信息检索精度下降太大包含太多无关信息稀释核心内容增加大模型处理成本工业级推荐分块大小场景推荐分块大小重叠大小通用问答512-1024 字符50-100 字符技术文档1024-2048 字符100-200 字符法律合同2048-4096 字符200-400 字符小说 / 长文本4096-8192 字符400-800 字符原则 3可追溯性每个分块必须保留完整的元数据能够追溯到原始文档的具体位置如页码、章节、行号这是实现引用标注和答案溯源的基础。1.5 主流分块策略对比分块策略原理优点缺点适用场景固定长度分块按字符数或 Token 数切割实现简单、速度快容易破坏语义完整性快速原型、简单文本递归字符分块按分隔符优先级递归切割段落→句子→单词尽量保留语义完整性仍可能破坏长句子通用场景最常用语义分块基于嵌入向量的相似度切割完美保留语义完整性速度慢、依赖嵌入模型高质量 RAG 系统句子窗口分块以句子为单位分块检索时扩展上下文检索精度高、上下文完整分块数量多、检索慢精准问答场景父子分块小分块用于检索大分块用于生成兼顾检索精度和上下文完整性实现复杂工业级 RAG 系统二、LangChain 文档处理核心 API 详解2.1 文档对象DocumentLangChain 中所有文档都表示为Document对象包含两个核心字段page_content文档的文本内容metadata字典类型存储文档的元数据来源、页码、作者等from langchain_core.documents import Document # 创建一个文档对象 doc Document( page_content这是文档的内容, metadata{ source: test.pdf, page: 1, author: 张三 } ) print(doc.page_content) print(doc.metadata)2.2 文档加载器DocumentLoaderLangChain 提供了 100 种文档加载器支持几乎所有常见的文档格式。所有加载器都实现了统一的接口load()同步加载所有文档返回list[Document]lazy_load()惰性加载逐个返回文档适合大文件2.2.1 纯文本加载器TextLoaderfrom langchain_community.document_loaders import TextLoader # 加载纯文本文件 loader TextLoader( file_pathdata/test.txt, encodingutf-8, autodetect_encodingTrue # 自动检测编码 ) documents loader.load() print(f加载了{len(documents)}个文档) print(documents[0].page_content[:100])2.2.2 Markdown 加载器MarkdownLoader支持解析 Markdown 的标题层级、代码块、列表等结构from langchain_community.document_loaders import MarkdownLoader # 加载Markdown文件 loader MarkdownLoader( file_pathdata/test.md, modeelements # 按元素解析返回标题、段落、代码块等不同类型的文档 ) documents loader.load() for doc in documents: print(f类型{doc.metadata[type]}内容{doc.page_content[:50]})2.2.3 PDF 加载器PyPDFLoader最常用的 PDF 加载器基于 PyPDF2 实现支持页码提取from langchain_community.document_loaders import PyPDFLoader # 加载PDF文件 loader PyPDFLoader(file_pathdata/test.pdf) # 每页返回一个Document对象 documents loader.load() for doc in documents: print(f页码{doc.metadata[page]}内容{doc.page_content[:100]})2.2.5 通用加载器UnstructuredLoader支持所有常见格式的万能加载器基于 Unstructured.IO 库是工业级首选from langchain_community.document_loaders import UnstructuredLoader # 自动识别文件格式 loader UnstructuredLoader( file_pathdata/test.pdf, strategyfast, # 解析策略fast快速/ hi_res高精度支持OCR include_page_breaksTrue, # 包含分页符 extract_images_in_pdfFalse # 是否提取PDF中的图片 ) documents loader.load() print(f加载了{len(documents)}个文档)2.3 文本分块器TextSplitterLangChain 提供了多种文本分块器所有分块器都实现了统一的接口split_documents(documents: list[Document])将文档列表切割成分块列表split_text(text: str)将纯文本切割成字符串列表2.3.1 递归字符分块器RecursiveCharacterTextSplitter工业级最常用的分块器按以下分隔符优先级递归切割[\n\n, \n, , ]优先按段落切割段落太长按行切割行太长按空格切割最后按字符切割。from langchain_text_splitters import RecursiveCharacterTextSplitter # 创建分块器 text_splitter RecursiveCharacterTextSplitter( chunk_size1000, # 分块大小字符数 chunk_overlap100, # 分块重叠大小 separators[\n\n, \n, 。, , , , ], # 中文优化的分隔符 length_functionlen, # 长度计算函数 is_separator_regexFalse # 是否使用正则表达式作为分隔符 ) # 切割文档 documents loader.load() chunks text_splitter.split_documents(documents) print(f原始文档数{len(documents)}) print(f分块数{len(chunks)}) print(f第一个分块{chunks[0].page_content}) print(f第一个分块元数据{chunks[0].metadata})2.3.2 语义分块器SemanticChunker基于嵌入向量的相似度将语义相关的内容分到同一个块中from langchain_text_splitters import SemanticChunker from langchain_openai import OpenAIEmbeddings # 创建语义分块器 semantic_splitter SemanticChunker( embeddingsOpenAIEmbeddings(), # 嵌入模型 breakpoint_threshold_typepercentile, # 断点阈值类型 breakpoint_threshold_amount95, # 阈值百分比 chunk_size1000 # 目标分块大小 ) # 切割文档 chunks semantic_splitter.split_documents(documents)2.3.3 句子分块器SentenceSplitter按句子切割文本适合句子窗口检索from langchain_text_splitters import SentenceSplitter sentence_splitter SentenceSplitter( chunk_size100, chunk_overlap20, languagezh # 中文支持 ) chunks sentence_splitter.split_documents(documents)三、工业级文档处理最佳实践3.1 文档预处理清洗与标准化原始文档中存在大量噪声必须进行预处理才能用于 RAG 系统import re from langchain_core.documents import Document def clean_text(text: str) - str: 文本清洗函数 # 去除多余的空行和空格 text re.sub(r\n{3,}, \n\n, text) text re.sub(r , , text) text re.sub(r\t, , text) # 去除页眉页脚示例匹配第X页 共Y页格式 text re.sub(r第\d页\s*共\d页, , text) # 去除特殊字符 text re.sub(r[\x00-\x1f\x7f-\x9f], , text) # 去除首尾空白 text text.strip() return text def clean_documents(documents: list[Document]) - list[Document]: 清洗文档列表 cleaned_docs [] for doc in documents: cleaned_content clean_text(doc.page_content) # 跳过空文档 if len(cleaned_content) 10: cleaned_doc Document( page_contentcleaned_content, metadatadoc.metadata ) cleaned_docs.append(cleaned_doc) return cleaned_docs3.2 元数据增强为分块添加丰富的元数据提升检索精度和可追溯性def enhance_metadata(documents: list[Document], source: str) - list[Document]: 增强文档元数据 enhanced_docs [] for i, doc in enumerate(documents): metadata { **doc.metadata, source: source, chunk_id: f{source}_{i}, chunk_index: i, total_chunks: len(documents), upload_time: time.time() } enhanced_doc Document( page_contentdoc.page_content, metadatametadata ) enhanced_docs.append(enhanced_doc) return enhanced_docs3.3 批量处理与异常容错工业级系统需要支持批量处理大量文档并能处理单个文档解析失败的情况from pathlib import Path from utils.logger import logger from utils.exceptions import DocumentParseError def batch_load_documents(dir_path: str | Path) - list[Document]: 批量加载目录下的所有文档 dir_path Path(dir_path) all_documents [] # 支持的文件格式 supported_formats [.txt, .md, .pdf, .docx, .doc] for file_path in dir_path.iterdir(): if file_path.is_file() and file_path.suffix.lower() in supported_formats: try: logger.info(f正在加载文档{file_path.name}) documents load_single_document(file_path) all_documents.extend(documents) logger.info(f✅ 文档加载成功{file_path.name}共{len(documents)}页) except Exception as e: logger.error(f❌ 文档加载失败{file_path.name}错误{str(e)}) # 跳过失败的文档继续处理其他文档 continue logger.info(f批量加载完成共加载{len(all_documents)}个文档) return all_documents3.4 分块参数调优指南分块参数没有万能值需要根据你的文档类型和业务场景进行调优先从默认值开始chunk_size1000chunk_overlap100测试不同的分块大小512、1024、2048对比检索准确率调整重叠大小通常为分块大小的 10%-20%优化分隔符针对中文添加。、、等句子结束符使用语义分块如果对质量要求高且能接受较慢的速度四、项目整合实现工业级文档处理模块现在我们将今天所学的内容整合到前两天搭建的 LangChain 2026 框架中实现一个完整的文档处理流水线。4.1 第一步新增依赖在requirements.txt中添加文档处理相关依赖# 文档处理依赖langchain-communitypypdfpython-docxunstructuredmarkdownpython-magic-bin; sys_platform win324.2 第二步新增自定义异常在utils/exceptions.py中添加文档处理相关异常# 在现有异常类后面添加 class DocumentParseError(FrameworkBaseException): 文档解析失败异常 def __init__(self, file_path: str, details: str ): message f文档解析失败{file_path} if details: message f详细信息{details} super().__init__(message, error_code1003) class ChunkError(FrameworkBaseException): 文本分块失败异常 def __init__(self, details: str ): message 文本分块失败 if details: message f详细信息{details} super().__init__(message, error_code1004)4.3 第三步实现文档处理核心模块在core/目录下创建document_processor.pyimport time import re from pathlib import Path from typing import List from langchain_core.documents import Document from langchain_community.document_loaders import ( TextLoader, PyPDFLoader, Docx2txtLoader, UnstructuredFileLoader, UnstructuredExcelLoader ) # ✅ 只导入稳定版存在的分块器 from langchain_text_splitters import ( RecursiveCharacterTextSplitter, CharacterTextSplitter ) from config.settings import settings from utils.logger import logger from utils.exceptions import DocumentParseError, ChunkError class DocumentProcessor: 工业级文档处理器最终稳定版 所有实验性功能均做自动降级处理确保无依赖也能正常运行 def __init__( self, chunk_size: int 1000, chunk_overlap: int 100, chunking_strategy: str recursive, use_semantic_chunking: bool False ): self.chunk_size chunk_size self.chunk_overlap chunk_overlap self.chunking_strategy chunking_strategy self.use_semantic_chunking use_semantic_chunking # 初始化分块器自动处理实验性功能依赖 self._init_text_splitter() logger.info( f✅ 文档处理器初始化完成 | f分块大小{chunk_size} | f重叠大小{chunk_overlap} | f分块策略{self.chunking_strategy} ) def _init_text_splitter(self): 初始化文本分块器自动降级版 if self.use_semantic_chunking: # ✅ 优先使用本地 BGE 模型 try: from langchain_experimental.text_splitter import SemanticChunker from langchain_huggingface import HuggingFaceEmbeddings logger.info(正在初始化语义分块器使用本地BGE模型...) logger.info(f正在加载本地模型{settings.embedding_model_path}) # 使用本地模型路径 embeddings HuggingFaceEmbeddings( model_namesettings.embedding_model_path, model_kwargs{device: cpu}, encode_kwargs{normalize_embeddings: True} ) self.text_splitter SemanticChunker( embeddingsembeddings, breakpoint_threshold_typepercentile, breakpoint_threshold_amount95, min_chunk_size100 ) self.chunking_strategy semantic logger.info(✅ 语义分块器初始化成功使用本地BGE模型) except ImportError as e: logger.warning(f⚠️ 缺少依赖{str(e)}自动降级为递归字符分块器) logger.warning(提示如需使用语义分块请运行pip install langchain-experimental langchain-huggingface) self.use_semantic_chunking False self.chunking_strategy recursive self._init_recursive_splitter() except Exception as e: logger.warning(f⚠️ 语义分块器初始化失败{str(e)}自动降级为递归字符分块器) self.use_semantic_chunking False self.chunking_strategy recursive self._init_recursive_splitter() else: self._init_recursive_splitter() def _init_recursive_splitter(self): 初始化工业级递归字符分块器中文深度优化 self.text_splitter RecursiveCharacterTextSplitter( chunk_sizeself.chunk_size, chunk_overlapself.chunk_overlap, separators[ \n\n## , \n\n### , \n\n#### , \n\n##### , # Markdown标题优先级最高 \n\n, \n, # 段落和行 。, , , , , # 中文句子结束符 , 、, , # 中文标点和空格 , # 最后按单个字符分割 ], length_functionlen, is_separator_regexFalse, keep_separatorTrue, # 保留分隔符保证语义完整 strip_whitespaceTrue # 自动去除首尾空白 ) self.chunking_strategy recursive def _clean_text(self, text: str) - str: 工业级文本清洗函数 if not text: return # 1. 统一换行符 text text.replace(\r\n, \n).replace(\r, \n) # 2. 去除多余空白 text re.sub(r[ \t], , text) text re.sub(r\n{3,}, \n\n, text) # 3. 去除常见噪声 text re.sub(r第\d页\s*共\d页, , text) text re.sub(r版权所有.*?保留所有权利, , text, flagsre.DOTALL) text re.sub(rhttps?://\S, , text) text re.sub(r\b[A-Za-z0-9._%-][A-Za-z0-9.-]\.[A-Z|a-z]{2,}\b, , text) text re.sub(r1[3-9]\d{9}, , text) # 4. 去除控制字符 text re.sub(r[\x00-\x1f\x7f-\x9f], , text) return text.strip() def _load_single_document(self, file_path: Path) - List[Document]: 加载单个文档国内网络优化版 移除所有需要自动下载模型的加载器全部使用原生无依赖实现 try: suffix file_path.suffix.lower() logger.debug(f加载文件{file_path.name}) # ✅ 所有加载器均使用无外部依赖的原生实现 if suffix .txt or suffix .md: # Markdown直接用TextLoader加载效果完全满足RAG需求 loader TextLoader( file_path, encodingutf-8, autodetect_encodingTrue ) elif suffix .pdf: loader PyPDFLoader(file_path) elif suffix in [.docx, .doc]: loader Docx2txtLoader(file_path) elif suffix in [.xlsx, .xls]: # Excel使用原生加载器需要openpyxl依赖 try: from langchain_community.document_loaders import OpenpyxlLoader loader OpenpyxlLoader(file_path, read_onlyTrue, data_onlyTrue) except ImportError: logger.warning(⚠️ 未安装openpyxl跳过Excel文件) return [] else: # 未知格式尝试用TextLoader加载 logger.warning(f⚠️ 不支持的格式{suffix}尝试用文本方式加载) loader TextLoader(file_path, encodingutf-8, autodetect_encodingTrue) documents loader.load() # 清洗和过滤 cleaned_docs [] for doc in documents: cleaned_content self._clean_text(doc.page_content) if len(cleaned_content) 20: # 为Markdown添加特殊元数据 if suffix .md: doc.metadata[file_type] markdown cleaned_doc Document( page_contentcleaned_content, metadatadoc.metadata ) cleaned_docs.append(cleaned_doc) return cleaned_docs except Exception as e: raise DocumentParseError(str(file_path), str(e)) from e def _enhance_metadata(self, chunks: List[Document], file_name: str) - List[Document]: 增强分块元数据 enhanced_chunks [] for i, chunk in enumerate(chunks): metadata { **chunk.metadata, source: file_name, chunk_id: f{file_name.replace(., _)}_{i}, chunk_index: i, total_chunks: len(chunks), chunk_length: len(chunk.page_content), process_time: int(time.time()), chunking_strategy: self.chunking_strategy } enhanced_chunk Document( page_contentchunk.page_content, metadatametadata ) enhanced_chunks.append(enhanced_chunk) return enhanced_chunks def process_file( self, file_path: str | Path, enhance_metadata: bool True ) - List[Document]: 处理单个文件 file_path Path(file_path) if not file_path.exists(): raise FileNotFoundError(f文件不存在{file_path}) logger.info(f开始处理{file_path.name}) # ✅ 检查 text_splitter 是否已初始化 if not hasattr(self, text_splitter) or self.text_splitter is None: logger.error(❌ text_splitter 未初始化使用默认递归分块器) self.chunking_strategy recursive self._init_recursive_splitter() try: documents self._load_single_document(file_path) if not documents: logger.warning(f文档{file_path.name}无有效内容) return [] chunks self.text_splitter.split_documents(documents) logger.info(f分块完成{len(chunks)}个分块) if enhance_metadata: chunks self._enhance_metadata(chunks, file_path.name) logger.info(f✅ 处理完成{file_path.name}) return chunks except Exception as e: logger.error(f❌ 处理失败{file_path.name}错误{str(e)}, exc_infoTrue) raise ChunkError(f处理文档{file_path.name}失败) from e def process_directory( self, dir_path: str | Path, recursive: bool False, enhance_metadata: bool True ) - List[Document]: 批量处理目录 dir_path Path(dir_path) if not dir_path.exists(): raise FileNotFoundError(f目录不存在{dir_path}) logger.info(f开始批量处理目录{dir_path}) all_chunks [] supported_formats [.txt, .md, .pdf, .docx, .doc, .xlsx, .xls] glob_pattern **/* if recursive else * for file_path in dir_path.glob(glob_pattern): if file_path.is_file() and file_path.suffix.lower() in supported_formats: try: chunks self.process_file(file_path, enhance_metadata) all_chunks.extend(chunks) except Exception: continue logger.info(f✅ 批量处理完成共生成{len(all_chunks)}个分块) return all_chunks def save_chunks_to_file(self, chunks: List[Document], output_path: str | Path): 保存分块到JSONL文件 import json output_path Path(output_path) output_path.parent.mkdir(exist_okTrue, parentsTrue) with open(output_path, w, encodingutf-8) as f: for chunk in chunks: chunk_data { page_content: chunk.page_content, metadata: chunk.metadata } f.write(json.dumps(chunk_data, ensure_asciiFalse) \n) logger.info(f分块已保存到{output_path.resolve()}) def load_chunks_from_file(self, input_path: str | Path) - List[Document]: 从JSONL文件加载分块 import json input_path Path(input_path) if not input_path.exists(): raise FileNotFoundError(f分块文件不存在{input_path}) chunks [] with open(input_path, r, encodingutf-8) as f: for line_num, line in enumerate(f, 1): try: chunk_data json.loads(line.strip()) chunk Document( page_contentchunk_data[page_content], metadatachunk_data[metadata] ) chunks.append(chunk) except json.JSONDecodeError as e: logger.warning(f第{line_num}行解析失败跳过{str(e)}) logger.info(f从{input_path}加载了{len(chunks)}个分块) return chunks

相关文章:

工业级大模型学习之路021:LangChain零基础入门教程(第四篇):文档加载与文本分块技术

一、文档处理是 RAG 系统的基石1.1 为什么文档处理决定了 RAG 系统的上限?RAG 系统的核心逻辑是 **"检索相关文档片段 → 喂给大模型生成回答"**,整个流程的质量完全依赖于文档处理环节:如果文档解析失败,再好的检索和生…...

深度学习安全帽佩戴检测系统

1 前言 今天学长向大家介绍一个机器视觉的毕设项目,深度学习安全帽佩戴检测系统 项目运行效果: 毕业设计 深度学习安全帽佩戴检测系统🧿 项目分享:见主页简介 1 课题背景 建筑工人头部伤害是造成建筑伤亡事故的重要原因。佩戴安全帽是防止…...

解决华硕灵耀X双屏Linux下扬声器不工作的问题

解决华硕灵耀X双屏Linux下扬声器不工作的问题系统信息解决方法0. 备份系统1. 修改内核启动参数,使用HDA驱动2. 测试修复方案3. 持久化修复方案系统信息 我的电脑是:华硕灵耀X双屏Pro UX5100HM 电脑声卡为:ALC294 操作系统为:Manj…...

第二周学习

学习(一)、低通滤波器1、原理(为什么方波经过低通滤波器变成了正弦波)傅里叶变换对于f(t)来说,只要f(t)是周期的,则一定可以将f(t)拆解…...

【Linux驱动开发】第12天:Linux设备树核心:树形结构+节点+属性 完整全解

目录 设备树树形结构概述节点(Node)全解:命名规范标准节点常用设备节点属性(Property)全解:类型核心属性总线专用属性标签与节点引用:设备树复用的核心常见错误与注意事项总结:驱动…...

2026年亲测AI写作辅助软件指南(高效定稿版)

为解决学术写作中效率与合规两大核心痛点,本文精选8款高适配性AI论文写作工具(按综合优先级排序),围绕中文学术规范适配、真实参考文献生成、格式标准化、高性价比四大核心维度筛选,同时配套分场景精准选型方案与学术合…...

安全打底・能力拉满:我的 OpenClaw 龙虾生态 Skill 清单

2026开年AI圈两大热词:龙虾(OpenClaw)、Skill插件。龙虾是短期流量话题,热度来得快去得快;而Skill插件可一次部署、长期复用,真正落地到日常办公、协作、社交场景。 市面多数Skill推荐内容堆砌命令、实用性…...

HTML应用指南:利用GET请求获取智己汽车门店位置信息

智己汽车作为高端智能电动汽车品牌,深度融合先锋设计美学、纯电驱动技术、高阶智能驾驶与全场景出行服务,依托L7、LS7、LS6、L6等产品矩阵,打造兼具科技感与驾控乐趣的高端出行体验。在营销推广层面,智己摒弃传统4S店模式&#xf…...

2025大厂Java后端面试:RAG高频考点【干货】

根据近期(2025-2026年)牛客网上字节、腾讯、阿里、快手、京东等大厂的Java后端面经,RAG(检索增强生成)已高频结合传统Java八股进行考察。📚 面试问题分类与总结1. 🏗️ RAG 基础概念与理解这是面…...

传统FPM项目怎么渐进式迁移到Swoole/Hyperf?

传统 FPM 项目渐进式迁移到 Swoole / Hyperf 完整方案下面是一份实战派迁移指南,不搞理想化"重写",而是一边赚钱一边换引擎。---一、先讲清楚:为啥要迁?要迁到哪?1.1 FPM 的痛点- 每个请求都要重新加载框架(Laravel 启动 30~80ms,Hyperf 启动后 0ms)- 不能保持长连…...

从Java全栈开发到云原生:一次真实的面试对话与技术剖析

从Java全栈开发到云原生:一次真实的面试对话与技术剖析 面试场景回顾 在一次真实的互联网大厂Java全栈开发岗位的面试中,面试官和应聘者展开了一场围绕技术栈、项目经验和系统设计的深入交流。面试官以专业严谨的态度,逐步引导应聘者展示其技…...

pod创建

Pod 由一个或多个紧密耦合的容器组成,它们之间共享网络、存储等资源,Pod 是 Kubernetes 中最小的工作单元,Pod 中的容器会一起启动和停止。1.创建pod一个pod只有一个业务容器kubectl logs mypod 命令用于查看名为 mypod 的 Pod 中唯一容器的标…...

第 2 篇:Agent 的三种工作模式,选错了事倍功半

系列简介:从零搭建一个多 Agent AI 助手,覆盖原理、实现、部署全链路。不讲空话,每篇都有可运行的代码。 项目地址:https://github.com/CodeMomentYY/LangGraph-Agent 本篇目标:理解 Agent 的三种工作模式,…...

为什么92%的Midjourney水效渲染失败?——解析v6.1+版本流体折射权重、noise scale与--s值的黄金三角关系

更多请点击: https://codechina.net 第一章:为什么92%的Midjourney水效渲染失败?——问题现象与根本归因 大量用户在使用 Midjourney v6 生成「水效渲染」(Water Efficiency Rendering)类提示词时遭遇高频失败——表现…...

Shutter Encoder:构建高效媒体工作流的FFmpeg图形化解决方案

Shutter Encoder:构建高效媒体工作流的FFmpeg图形化解决方案 【免费下载链接】shutter-encoder A professional video compression tool accessible to all, mostly based on FFmpeg. 项目地址: https://gitcode.com/gh_mirrors/sh/shutter-encoder 在数字媒…...

AI正在重构工程师岗位:被替代的不是“人”,而是低维度能力

过去很多人认为,AI更适合写文案、做客服、生成图片,而真正复杂的工程领域——尤其是工业、制造、自动化系统——依然离不开工程师。 但最近一个劳动仲裁案例,让越来越多工程技术人员开始重新思考这个问题: 一位从事测绘工作15年的工程师,因为企业全面导入AI自动化测绘系…...

嵌入式C语言开发中的三大致命陷阱

很多人刚开始学习C语言时,会觉得: 会指针 会结构体 会寄存器操作 能驱动外设 似乎就已经掌握了嵌入式开发。 但真正进入项目后才会发现: 嵌入式开发最难的,从来不是语法,而是“代码与硬件现实世界之间的耦合”。 同样一句代码: 在PC上可能只是运行错误; 在单片机里却可…...

Midjourney V6调色板设置失效的5大隐性原因:从--sref误用到色域压缩陷阱,一文终结色彩失真

更多请点击: https://codechina.net 第一章:Midjourney V6调色板设置失效的全局认知 Midjourney V6 引入了更严格的色彩语义解析机制,导致此前在 V5.x 中广泛使用的 --palette 参数(如 --palette vibrant 或 --palette muted&…...

SQL 数据库从免费到付费选型实战:支撑真实规模产品的能力分析与选择指南

引言:为什么 SQL 数据库选型如此重要? 在当今数据驱动的时代,数据库是任何数字产品的核心基础设施。无论是初创公司的 MVP(最小可行产品),还是日活百万的成熟应用,数据库的选择直接影响着产品的性能、成本、可扩展性和开发效率。 对于技术决策者而言,面对琳琅满目的 …...

【小白快速上手】Windows 系统 OpenClaw v2.7.5 一键部署完整教程(包含安装包)

OpenClaw 一键安装完整教程(2026 最新) 适配系统:Windows10/11 64 位当前版本:v2.7.5(虾壳云版)文件大小:约 58.7MB下载地址:https://xiake.yun/api/download/package/16?promoCod…...

SQL 能包打天下吗?多少比例的产品只需 SQL,何时需要引入其他存储?

引言 在数据驱动的时代,SQL(结构化查询语言)作为关系型数据库的标准查询语言,其地位无可撼动。它以其强大的数据操作能力、清晰的声明式语法和广泛的生态支持,成为绝大多数应用开发者的首选。然而,随着业务场景的日益复杂和数据形态的多样化,一个灵魂拷问随之而来:SQL…...

498元!某国产12代i7云终端小钢炮,仅1.7L迷你主机,可上i7-12700处理器,最大支持双M2+SATA三盘位,可惜还是准系统传家宝!

要说小主机品牌种类规格方面,最为丰富的不是个人家用消费级市场,而是云终端,痩客户机类型产品。奈何如今大环境不景气,再叠加如今处理器性能进步明显,以英特尔12代平台为例,如今依旧还是主流,所…...

实际开发中 SQL 与产品的耦合与互动实践

引言 在产品开发初期,数据库 Schema(表结构)的设计是一个绕不开的核心问题。很多开发者,尤其是新手,常常会陷入一个两难境地:“Schema 需要一开始就完全确定好吗?如果后期要改动怎么办?到底要设计多少个表(Schema 数量)才算合适?” 这些问题背后,反映的是对软件工…...

MDK Middleware网络组件的嵌入式安全防护解析

1. MDK Middleware网络组件的安全特性解析在嵌入式系统开发中,网络安全往往是最容易被忽视却又至关重要的环节。作为Keil MDK开发环境的核心组件,Middleware Network为Cortex-M系列微控制器提供了轻量级TCP/IP协议栈实现。不同于桌面级操作系统自带的网络…...

量子计算中的SWAP门原理与应用解析

1. 量子计算中的SWAP门基础原理量子计算区别于经典计算的核心在于量子比特(qubit)的叠加态和纠缠态特性。在量子线路设计中,SWAP门作为基础量子逻辑门之一,扮演着量子信息交换的关键角色。与经典计算中的位交换不同,量…...

HarmonyOS 鸿蒙PC平台三方库移植:使用 vcpkg 移植 libzen(ZenLib)

网罗开发(小红书、快手、视频号同名)大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方…...

Agent大战,赢家暗自在哪下功夫?

(一)日子都不好过OpenAI和Anthropic在release note节奏上,证明了一件事:他们有实力两周抬一次模型能力线。其威力,足以消灭掉一批创业公司。这事不展开,共识。在这一波里,别说小公司&#xff0c…...

Keil C166嵌入式开发中的宽字符实现与优化

1. 宽字符支持问题解析在嵌入式C语言开发中,Unicode支持是一个常见需求。最近我在使用Keil C166开发工具时遇到了一个关于宽字符(wchar_t)定义的有趣问题。打开标准库头文件stdlib.h时,发现其中对wchar_t的定义如下:#ifndef _WCHAR_T_DEFINED…...

原来训大模型,就像开一家小餐馆!

你是不是一直觉得,训练大语言模型是 OpenAI、百度这种大厂才能干的事?要几万张显卡,要花几个亿,普通人想都不敢想? 错了!我用自己开发机上的 8 张 H20 显卡,花了点时间,从零开始训了…...

Windows电脑自带软件全部无法使用?亲测有效的解决办法!

Windows电脑自带软件全部无法使用?亲测有效的解决办法! 最近在使用电脑的时候,我突然遇到了一个非常离谱的问题: Windows 系统自带的软件几乎全部无法正常打开! 包括但不限于: 计算器相机录音机截屏工具画图…...