随着人工智能技术的快速发展,如何高效管理和利用企业内部知识资产成为企业数字化转型的关键挑战。本文介绍的企业知识助手系统,基于先进的LlamaIndex框架和智谱AI大模型,通过集成本地向量数据库和多种实用工具,实现了自然语言交互、文档检索、数据分析和信息查询等核心功能。系统采用FastAPI作为后端服务框架,提供稳定高效的API接口。
这里我们的大模型选择的是glm-4-flash,这是一个轻量级的glm模型,缺点是生成能力不如glm-pro等模型,由于是演示项目所以主打一个免费实用就够用。
由于Llamaindex将市面上常用的大模型都整合到了一个库调用,所以这里不管是切换为ChatGPT还是LLama等其他大模型,效果都是一样的,甚至本地模型也可。
关键参数说明:
# 1. 配置API密钥
ZHIPU_API_KEY = "Your_Key"
os.environ["ZHIPU_API_KEY"] = ZHIPU_API_KEY
# 2. 初始化ZhipuAI大模型
llm = ZhipuAI(model="glm-4-flash", temperature=0.5, api_key=ZHIPU_API_KEY)
Settings.llm = llm
系统采用FAISS作为本地向量数据库存储企业文档知识库:
def load_vector_db(db_path, model_path):
# 初始化嵌入模型
embedding_model = SentenceTransformerEmbeddings(
model_name=model_path,
model_kwargs={'device': 'cpu'},
encode_kwargs={'normalize_embeddings': False}
)
# 加载向量库
vector_db = FAISS.load_local(
folder_path=db_path,
embeddings=embedding_model,
allow_dangerous_deserialization=True
)
return vector_db
# 加载FAISS向量数据库
faiss_vector_db = load_vector_db("./faiss_index", "./local_models/all-mpnet-base-v2")
关键技术要点:
关于如何生成本地向量库详见我之前的博客
Langchain+FAISS+sentence_transformer使用本地模型创建向量知识库的方法
代码如下
class FAISSQueryEngine:
def __init__(self, vector_db, top_k=3):
self.vector_db = vector_db
self.top_k = top_k
def query(self, query_str: str) -> str:
"""使用FAISS执行查询并返回结果"""
try:
# 执行相似性搜索
results = self.vector_db.similarity_search_with_score(query_str, k=self.top_k)
# 格式化结果
response = []
for i, (doc, score) in enumerate(results):
response.append(
f"文档 {i+1} - (相似度: {1-score:.2f})\n"
f"内容: {doc.page_content[:200]}..."
)
return "\n\n".join(response)
except Exception as e:
return f"查询错误: {str(e)}"
代码如下
def calculator_tool(expression: str) -> str:
"""执行数学计算(带输入过滤)"""
# 过滤不安全字符
sanitized_expr = re.sub(r'[()$$$${};"\'\`<>]', '', expression)
try:
# 尝试替换中文运算符
sanitized_expr = sanitized_expr.replace('×', '*').replace('÷', '/')
result = eval(sanitized_expr)
return f"计算结果: {expression} = {result}"
except Exception as e:
return f"计算错误: {str(e)}"
代码如下
def web_search(query: str) -> str:
"""使用DuckDuckGo进行网络搜索"""
try:
response = requests.get(
"https://api.duckduckgo.com/",
params={
"q": query,
"format": "json",
"no_html": "1",
"no_redirect": "1",
"t": "MyApp"
},
timeout=10
)
data = response.json()
# 整理结果
results = []
if data.get("AbstractText"):
results.append(f"摘要: {data['AbstractText']}")
for topic in data.get("RelatedTopics", []):
if "FirstURL" in topic and "Text" in topic:
results.append(f"{topic['Text']} ({topic['FirstURL']})")
return "\n".join(results[:3]) if results else "未找到相关信息"
except Exception as e:
return f"搜索错误: {str(e)}"
万变不离其宗,网络搜索工具可以更换为任意其他的搜索引擎
这是一个典型的通过API来作为工具扩展智能体功能的方法,这里的API可以更换为企业内部的各种API,只要写好方法信息和提示词模板,Agent就可以智能调用。
def get_phone_location(phone_number: str) -> str:
"""
获取手机号码归属地信息
参数:
phone_number (str): 需要查询的手机号码
返回:
str: 格式化后的归属地信息或错误消息
"""
# API配置
api_url = "http://apis.juhe.cn/mobile/get"
api_key = "" # 请替换为您的实际API密钥
# 构建请求参数
params = {
"phone": phone_number,
"key": api_key
}
try:
# 发送GET请求
response = requests.get(api_url, params=params, timeout=10)
# 检查HTTP状态码
response.raise_for_status()
# 解析JSON响应
data = response.json()
# 检查API返回状态
if data.get("error_code") != 0:
error_msg = data.get("reason", "未知错误")
return f"API错误: {error_msg} (错误码: {data.get('error_code')})"
# 提取并格式化结果
result = data.get("result", {})
province = result.get("province", "未知省份")
city = result.get("city", "未知城市")
operator = result.get("company", "未知运营商")
return f"手机号码: {phone_number}\n归属地: {province}{city}\n运营商: {operator}"
except requests.exceptions.RequestException as e:
return f"网络请求失败: {str(e)}"
except json.JSONDecodeError:
return "API响应解析失败"
except Exception as e:
return f"处理过程中发生错误: {str(e)}"
FunctionTool 是 LlamaIndex(现更名为 LlamaIndexTS)框架中的一个核心组件,主要用于将自定义函数封装成可供大语言模型(LLM)调用的工具。它在构建智能代理(Agent)、插件系统或需要外部工具扩展LLM能力的场景中扮演关键角色。以下是具体代码:
将任何 Python 函数(如数据库查询、API调用、计算逻辑等)转化为LLM可识别的标准化工具接口,使LLM能按需调用这些外部能力。
LLM 通过 FunctionTool 突破纯文本生成的限制,实时获取外部数据(如天气、股票)、执行计算(如数学公式)或操作外部系统(如发送邮件)。
在 ReAct、OpenAIAgent 等代理架构中,FunctionTool 定义代理可用的工具集,代理根据用户问题动态选择并执行工具。
通过函数签名和参数文档(docstring)自动生成工具的描述信息(如功能说明、参数格式),帮助LLM理解何时调用该工具。
支持通过 pydantic 或 JSON Schema 定义参数规范,自动校验LLM传入的参数类型和结构,避免运行时错误。
工具可直接注入 OpenAIAgent、ReActAgent 等代理:
生成符合 OpenAI Function Calling 或 ReAct 格式的工具描述,适配主流LLM(如 GPT-4, Claude, Llama 等)。
# ============================
# 4. 创建统一格式的工具集合
# ============================
# 创建文档查询工具(使用FunctionTool包装)
document_tool = FunctionTool.from_defaults(
fn=lambda query: document_query_engine.query(query),
name="document_search",
description="查询公司内部文档和知识库",
)
# 创建计算器工具
calculator_tool = FunctionTool.from_defaults(
fn=calculator_tool,
name="calculator",
description="执行数学计算"
)
# 创建网络搜索工具
web_search_tool = FunctionTool.from_defaults(
fn=web_search,
name="web_search",
description="使用DuckDuckGo搜索引擎获取最新的网络信息"
)
get_phone_location_tool = FunctionTool.from_defaults(
fn=get_phone_location,
name="get_phone_location",
description="获取手机号码归属地信息"
)
# 创建工具集合(所有工具使用相同的FunctionTool格式)
tools = [
document_tool,
web_search_tool,
get_phone_location_tool,
calculator_tool
]
这里我们选择构建一个简单的智能体,由于使用了LlamaIndex的FunctionTool进行管理,智能体的扩展性大大增强。
具体代码如下:
# ============================
# 5. 创建智能代理
# ============================
def create_agent():
"""创建新的会话代理"""
return ReActAgent.from_tools(
tools=tools,
llm=llm,
verbose=True,
system_prompt=f"""
当前日期: {datetime.now().strftime('%Y-%m-%d')}
你是一个专业的知识助手,能访问文档库、网络搜索和计算工具。
遵守以下规则:
1. 文档问题优先使用document_search工具
2. 时效性问题使用web_search工具
3. 数学计算使用calculator工具
4. 查询号码归属地使用get_phone_location工具
5. 对引用内容注明来源
6. 思考过程保持简洁
"""
)
# 会话管理类
class ChatAgent:
def __init__(self):
self.session_history = {}
def get_agent(self, session_id):
"""获取或创建特定会话的代理"""
if session_id not in self.session_history:
self.session_history[session_id] = create_agent()
return self.session_history[session_id]
def chat(self, message, session_id="default"):
"""处理用户消息"""
agent = self.get_agent(session_id)
return agent.chat(message)
# 创建聊天代理管理器
chat_agent = ChatAgent()
使用FastAPI构建简单的智能体服务,系统通过FastAPI提供标准化API服务:
# ============================
# 7. FastAPI服务
# ============================
app = FastAPI(title="企业知识助手API")
class ChatRequest(BaseModel):
message: str
session_id: str = "default"
def sanitize_input(text: str) -> str:
"""过滤潜在危险字符"""
return re.sub(r'[<>\"\';%&\\]', '', text)[:500]
@app.post("/chat")
async def chat_endpoint(request: ChatRequest):
try:
# 清理输入
clean_message = sanitize_input(request.message)
session_id = sanitize_input(request.session_id)[:64]
# 处理聊天
agent = chat_agent.get_agent(session_id)
response = agent.chat(clean_message)
return {"response": str(response)}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# ============================
# 主程序入口
# ============================
if __name__ == "__main__":
print("=" * 60)
print("企业知识助手系统 - LlamaIndex + ZhipuAI")
print(f"模型: {llm.model} | API密钥: {ZHIPU_API_KEY[:12]}...")
print(f"FAISS向量库文档数量: {faiss_vector_db.index.ntotal}")
print("=" * 60)
# 启动API服务
print("\n启动API服务: http://localhost:8000")
print("使用CTRL+C停止服务")
try:
uvicorn.run(app, host="0.0.0.0", port=8000, log_level="info")
except Exception as e:
print(f"服务启动失败: {e}")
本文实现的企业知识助手系统具有以下核心优势:
通过将LlamaIndex框架与智谱AI大模型深度集成,系统实现了: