从模块到系统,打造真正可用的企业级AI应用
开篇回顾与本期聚焦
经过前面四篇的深入学习,我们已经系统掌握了LangChain的完整技术栈:
-
Model I/O:与模型对话的"正确姿势" (直达飞机)
-
Retrieval:为模型注入外部知识(直达飞机)
-
Agents:让模型自主使用工具解决问题(直达飞机)
-
Memory & Chains:实现有记忆的协作工作流(直达飞机)
现在,是时候将这些技术融会贯通,构建一个真正可用于生产环境的企业级AI应用系统了!
在本篇中,我们将完整开发一个企业智能知识管理系统,它不仅能处理各种格式的文档,还能理解复杂查询、维护对话上下文,并通过智能工具调用解决实际问题。
一、系统架构设计
1. 系统核心功能
我们的企业知识管理系统将包含以下核心模块:
-
多格式文档处理:支持PDF、Word、Excel、TXT等格式
-
智能检索问答:基于RAG的精准知识查询
-
对话记忆系统:维护用户偏好和对话历史
-
工具协作平台:集成搜索、计算、分析等工具
-
权限与安全:基础的访问控制和数据保护
-
监控与日志:系统运行状态的可观测性
2. 技术架构图
用户界面
↓
API网关
↓
核心处理层 → 记忆系统 → 向量数据库
↓
工具协作层 → 外部API
↓
模型服务层
二、完整系统实现
下面是我们企业知识管理系统的完整代码实现:
1. 定义配置和日志系统
# ==================== 全局配置 ====================
# 聚合平台 http://www.ufunai.cn 配置
BASE_URL = "https://api.ufunai.cn/v1"
API_KEY = "sk-xxxxx" # 替换为你的API密钥
MODEL_NAME = "gpt-4" # 指定要测试的模型名称
# 1. 配置和日志系统
class Config:
"""系统配置"""
def __init__(self):
self.api_base_url = BASE_URL
self.api_key = API_KEY
self.model_name = MODEL_NAME
self.embedding_model = "text-embedding-ada-002"
self.chunk_size = 1000
self.chunk_overlap = 200
self.max_conversation_history = 10
self.supported_file_types = ['.pdf', '.txt', '.docx', '.doc', '.xlsx']
# 设置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('knowledge_system.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger("KnowledgeSystem")
2. 核心模型服务
class ModelService:
"""统一的模型服务"""
def __init__(self, config: Config):
self.config = config
self.chat_model = self._create_chat_model()
self.embedding_model = self._create_embedding_model()
def _create_chat_model(self):
"""创建聊天模型"""
return HTTPChatModel(
base_url=self.config.api_base_url,
api_key=self.config.api_key,
model=self.config.model_name
)
def _create_embedding_model(self):
"""创建嵌入模型"""
return HTTPEmbeddingModel(
base_url=self.config.api_base_url,
api_key=self.config.api_key
)
def chat_completion(self, messages: List[Dict]) -> str:
"""聊天补全"""
try:
return self.chat_model.invoke(messages)
except Exception as e:
logger.error(f"聊天模型调用失败: {e}")
raise
def get_embeddings(self, texts: List[str]) -> List[List[float]]:
"""获取文本嵌入"""
try:
return self.embedding_model.embed_documents(texts)
except Exception as e:
logger.error(f"嵌入模型调用失败: {e}")
raise
3. 文档处理引擎
class DocumentProcessor:
"""文档处理引擎"""
def __init__(self, config: Config, embedding_model):
self.config = config
self.embedding_model = embedding_model
self.text_splitter = RecursiveCharacterTextSplitter(
chunk_size=config.chunk_size,
chunk_overlap=config.chunk_overlap,
length_function=len
)
def load_document(self, file_path: str) -> List[Dict]:
"""加载文档"""
file_ext = os.path.splitext(file_path)[1].lower()
try:
if file_ext == '.pdf':
loader = PyPDFLoader(file_path)
elif file_ext in ['.docx', '.doc']:
loader = Docx2txtLoader(file_path)
elif file_ext in ['.xlsx', '.xls']:
loader = UnstructuredExcelLoader(file_path)
else:
loader = TextLoader(file_path, encoding='utf-8')
documents = loader.load()
logger.info(f"成功加载文档: {file_path}, 共 {len(documents)} 页")
return documents
except Exception as e:
logger.error(f"文档加载失败 {file_path}: {e}")
raise
def process_document(self, file_path: str) -> List[Dict]:
"""处理文档:加载、分割、生成嵌入"""
# 加载文档
documents = self.load_document(file_path)
# 分割文本
chunks = self.text_splitter.split_documents(documents)
chunk_texts = [chunk.page_content for chunk in chunks]
# 生成嵌入
logger.info("正在生成文档嵌入...")
embeddings = self.embedding_model.embed_documents(chunk_texts)
# 构建文档块信息
processed_chunks = []
for i, (chunk, embedding) in enumerate(zip(chunks, embeddings)):
processed_chunks.append({
"id": f"{os.path.basename(file_path)}_{i}",
"content": chunk.page_content,
"metadata": chunk.metadata,
"embedding": embedding,
"file_path": file_path,
"processed_time": datetime.now().isoformat()
})
logger.info(f"文档处理完成: {len(processed_chunks)} 个块")
return processed_chunks
4. 向量存储系统
class VectorStore:
"""向量存储系统"""
def __init__(self):
self.documents = {}
self.embeddings = {}
self.document_index = {} # 文件到文档块的映射
def add_documents(self, processed_chunks: List[Dict]):
"""添加文档到向量存储"""
for chunk in processed_chunks:
doc_id = chunk["id"]
self.documents[doc_id] = chunk
self.embeddings[doc_id] = chunk["embedding"]
# 更新文件索引
file_path = chunk["file_path"]
if file_path not in self.document_index:

最低0.47元/天 解锁文章
908

被折叠的 条评论
为什么被折叠?



