LlamaIndex + 智谱大模型GLM 实现智能代理(Agent)

LlamaIndex + 智谱大模型GLM 实现智能代理(Agent)

文章目录

  • LlamaIndex + 智谱大模型GLM 实现智能代理(Agent)
  • 前言
  • 一、模型加载
  • 二、向量数据库加载
    • 1.向量库加载
    • 2.向量库生成
  • 三、方法创建
    • 1. 创建FAISS查询引擎适配器(本地外挂知识库查询)
    • 2.数学计算工具函数(计算器)
    • 3.WebSearch工具(网络搜索)
    • 4.手机号码归属地信息(号码归属地工具)
  • 四、FunctionTool
    • 1. 核心作用
    • 2. 核心特性​
    • 3. 具体代码
  • 五、智能体构建
  • 五、FastAPI调用
  • 总结


前言

随着人工智能技术的快速发展,如何高效管理和利用企业内部知识资产成为企业数字化转型的关键挑战。本文介绍的企业知识助手系统,基于先进的​​LlamaIndex框架​​和​​智谱AI大模型​​,通过集成本地向量数据库和多种实用工具,实现了自然语言交互、文档检索、数据分析和信息查询等核心功能。系统采用​​FastAPI​​作为后端服务框架,提供稳定高效的API接口。


一、模型加载

这里我们的大模型选择的是glm-4-flash,这是一个轻量级的glm模型,缺点是生成能力不如glm-pro等模型,由于是演示项目所以主打一个免费实用就够用。
由于Llamaindex将市面上常用的大模型都整合到了一个库调用,所以这里不管是切换为ChatGPT还是LLama等其他大模型,效果都是一样的,甚至本地模型也可。

关键参数说明:

  • model=“glm-4-flash”:智谱AI的高性能轻量模型
  • temperature=0.5:控制生成结果的随机性(0-1范围)
  • api_key:智谱云平台提供的API凭证
  • 系统将初始化后的大模型设置为全局默认模型(Settings.llm),确保各组件调用一致性。
# 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作为本地向量数据库存储企业文档知识库:

1.向量库加载


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")

关键技术要点:

  • 使用sentence-transformers/all-mpnet-base-v2模型生成文档嵌入向量
  • FAISS支持高效相似度搜索(Cosine Similarity)
  • allow_dangerous_deserialization=True安全加载本地序列化数据

2.向量库生成

关于如何生成本地向量库详见我之前的博客
Langchain+FAISS+sentence_transformer使用本地模型创建向量知识库的方法

三、方法创建

1. 创建FAISS查询引擎适配器(本地外挂知识库查询)

代码如下

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)}"

2.数学计算工具函数(计算器)

代码如下


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)}"

3.WebSearch工具(网络搜索)

代码如下

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)}"

万变不离其宗,网络搜索工具可以更换为任意其他的搜索引擎

4.手机号码归属地信息(号码归属地工具)

这是一个典型的通过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

FunctionTool 是 ​​LlamaIndex​​(现更名为 ​​LlamaIndexTS​​)框架中的一个核心组件,主要用于​​将自定义函数封装成可供大语言模型(LLM)调用的工具​​。它在构建智能代理(Agent)、插件系统或需要外部工具扩展LLM能力的场景中扮演关键角色。以下是具体代码:

1. 核心作用

  1. 工具封装(Tool Wrapping)​​

将任何 Python 函数(如数据库查询、API调用、计算逻辑等)转化为LLM可识别的标准化工具接口,使LLM能按需调用这些外部能力。

  1. ​​动态增强LLM功能​​

LLM 通过 FunctionTool 突破纯文本生成的限制,实时获取外部数据(如天气、股票)、执行计算(如数学公式)或操作外部系统(如发送邮件)。

  1. ​​支持智能代理工作流​​

在 ReAct、OpenAIAgent 等代理架构中,FunctionTool 定义代理可用的工具集,代理根据用户问题动态选择并执行工具。

2. 核心特性​

  1. 自动生成工具描述​​

通过函数签名和参数文档(docstring)自动生成工具的描述信息(如功能说明、参数格式),帮助LLM理解何时调用该工具。

  1. 参数校验与类型转换​

支持通过 pydantic 或 JSON Schema 定义参数规范,自动校验LLM传入的参数类型和结构,避免运行时错误。

  1. ​​无缝集成代理系统

工具可直接注入 OpenAIAgent、ReActAgent 等代理:

  1. 兼容多种LLM生态

生成符合 OpenAI Function Calling 或 ReAct 格式的工具描述,适配主流LLM(如 GPT-4, Claude, Llama 等)。

3. 具体代码

# ============================
# 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构建简单的智能体服务,系统通过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}")

总结

本文实现的企业知识助手系统具有以下核心优势:

  1. 多源知识整合​​:本地FAISS向量库 + 实时网络信息 + 工具API服务
  2. ​​安全可靠​​:输入过滤、计算过滤、API安全访问机制
  3. ​​会话管理​​:支持多用户独立会话上下文
  4. 标准化接口​​:通过FastAPI提供RESTful服务接口
  5. ​​高效推理​​:GLM-4-Flash模型提供高质量响应

通过将LlamaIndex框架与智谱AI大模型深度集成,系统实现了:

  1. 企业内部文档的高效检索
  2. 复杂数学计算能力
  3. 实时网络信息获取
  4. 结构化数据查询能力

你可能感兴趣的:(人工智能,python,langchain,faiss,自然语言处理)