ZeroOne AI
← 返回文章列表

LlamaIndex 系列(四):入门案例(阿里云百炼适配)

👁 39
分类:工业AI

本文以阿里云百炼为模型底座,演示 LlamaIndex 入门案例:OpenAILike 接入通义千问、FunctionAgent 工具调用智能体、Context 多轮对话记忆、RAG 文档检索与索引持久化,并给出完整可运行代码。

一、项目背景

大模型落地应用时,仅靠模型自身的通用能力远远不够:企业私有数据(设备手册、工艺文件、生产记录)如何被模型理解并正确引用,才是工程化的核心问题。LlamaIndex 正是为解决这一问题而生的数据框架,它把文档解析、分块、向量化、检索、提示词组装等繁琐环节封装成标准组件,让开发者专注于业务逻辑本身。

在国内生产环境中,直接调用海外模型服务存在网络与合规成本。阿里云百炼平台提供 OpenAI 兼容接口与免费额度,配合通义千问系列模型,是国产化适配的主流选择。本系列文章以 LlamaIndex 为骨架、阿里云百炼为模型底座,从零演示一个可运行的入门案例,覆盖:工具调用智能体、多轮对话记忆、RAG 检索与索引持久化。

二、技术方案

很多开发者把 LlamaIndex 简单等同于 RAG 框架,但官方将数据增强型大模型应用归纳为五大核心形态:

理解这五大形态,才能跳出 Demo,设计出可落地的生产级应用。本案例的技术选型如下:

环境要求:Python >= 3.10 且 < 4.0。安装有三种方式:

  1. Pip 快速安装:pip install llama-index(基础包含 core、llms-openai、embeddings-openai、readers-file)
  2. 自定义按需安装:如 Ollama 本地模型 + HuggingFace Embedding,只装 llama-index-core 等必要包
  3. 源码编译安装:clone 仓库后以 poetry 安装核心库与各集成包

三、系统架构

整体分为三层:

数据流转:用户提问 → 智能体判断意图并选择动作(工具调用或文档检索)→ 执行结果回填提示词 → LLM 生成最终答案返回。

四、实施过程

4.1 环境配置

获取百炼 API Key 后写入 .env 文件(比 export 更稳定,不受终端与启动方式影响),并安装 python-dotenv:

pip install python-dotenv
DASHSCOPE_API_KEY=sk-xxx

4.2 基础智能体:工具调用

创建 starter.py,实现一个具备乘法计算工具的智能体:

import asyncio
import os

from dotenv import load_dotenv
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.openai_like import OpenAILike

load_dotenv()
api_key = os.environ["DASHSCOPE_API_KEY"]

llm = OpenAILike(
    model="qwen-plus",
    api_key=api_key,
    api_base="https://dashscope.aliyuncs.com/compatible-mode/v1",
    is_chat_model=True,
    is_function_calling_model=True,
)

def multiply(a: float, b: float) -> float:
    """两个数字相乘"""
    return a * b

agent = FunctionAgent(
    tools=[multiply],
    llm=llm,
    system_prompt="你是助手,可以完成两个数字相乘计算。",
)

async def main():
    response = await agent.run("1234 * 4567 等于多少?")
    print(str(response))

if __name__ == "__main__":
    asyncio.run(main())

运行输出:1234 × 4567 = 5,635,678。

执行流程:用户问题 + 工具描述传入 LLM → 模型选择工具并填充参数 → 执行函数 → 整合结果生成回答。框架推荐异步写法,可提升应用并发性能。

4.3 增加多轮对话记忆

依靠 Context 对象持久化会话上下文:同一个 ctx 上的多次 run() 共享对话记忆;不传 ctx 则每次都是全新会话。

import asyncio
import os

from dotenv import load_dotenv
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.core.workflow import Context
from llama_index.llms.openai_like import OpenAILike

load_dotenv()
llm = OpenAILike(
    model="qwen-plus",
    api_key=os.environ["DASHSCOPE_API_KEY"],
    api_base="https://dashscope.aliyuncs.com/compatible-mode/v1",
    is_chat_model=True,
    is_function_calling_model=True,
)

def multiply(a: float, b: float) -> float:
    """两个数字相乘"""
    return a * b

agent = FunctionAgent(
    tools=[multiply],
    llm=llm,
    system_prompt="你是助手,可以完成两个数字相乘计算。",
)

async def main():
    ctx = Context(agent)

    response = await agent.run("我叫Logan", ctx=ctx)
    print("第1轮:", str(response))

    response = await agent.run("我的名字是什么?", ctx=ctx)
    print("第2轮:", str(response))

    response = await agent.run("我叫Logan,12乘以12等于多少?", ctx=ctx)
    print("第3轮:", str(response))

    response = await agent.run("我的名字是什么?")
    print("无ctx对照:", str(response))

if __name__ == "__main__":
    asyncio.run(main())

执行效果:第 1 轮打招呼;第 2 轮能答出名字(记忆生效);第 3 轮记忆与工具调用共存;无 ctx 对照轮完全不记得之前对话。Context 内部维护会话的 memory(对话历史)与 state,跨 run() 保留,多智能体场景下还可作为共享黑板传递结构化状态。

4.4 为智能体接入 RAG 检索能力

准备测试文档:将任意 .txt 文件放入 data/ 目录即可(示例使用官方 Paul Graham 随笔)。注意:RAG 依赖 embedding 模型,若不配置框架会默认回退到 OpenAI 并报错,必须把 LLM 与 embedding 同时切到百炼。

import asyncio
import os

from dotenv import load_dotenv
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.embeddings.openai_like import OpenAILikeEmbedding
from llama_index.llms.openai_like import OpenAILike

load_dotenv()
API_KEY = os.environ["DASHSCOPE_API_KEY"]
API_BASE = "https://dashscope.aliyuncs.com/compatible-mode/v1"

Settings.llm = OpenAILike(
    model="qwen-plus",
    api_key=API_KEY,
    api_base=API_BASE,
    is_chat_model=True,
    is_function_calling_model=True,
)
Settings.embed_model = OpenAILikeEmbedding(
    model_name="text-embedding-v3",
    api_key=API_KEY,
    api_base=API_BASE,
)

documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(documents, show_progress=True)
query_engine = index.as_query_engine()

def multiply(a: float, b: float) -> float:
    """两个数字相乘"""
    return a * b

async def search_documents(query: str) -> str:
    """检索本地文档"""
    response = await query_engine.aquery(query)
    return str(response)

agent = FunctionAgent(
    tools=[multiply, search_documents],
    llm=Settings.llm,
    system_prompt="你可以进行数学计算,也可以检索文档回答问题。",
)

async def main():
    response = await agent.run("作者大学时期做了什么?7乘以8等于多少?")
    print(response)

if __name__ == "__main__":
    asyncio.run(main())

智能体会自动判断何时调用计算工具、何时检索文档,一次提问同时完成"文档问答 + 数学计算"两类任务。

4.5 RAG 索引持久化

避免每次启动重复解析文档,推荐"有缓存则加载、无则构建并保存"的模式:

import asyncio
import os
from pathlib import Path

from dotenv import load_dotenv
from llama_index.core import (
    Settings, SimpleDirectoryReader, StorageContext,
    VectorStoreIndex, load_index_from_storage,
)
from llama_index.embeddings.openai_like import OpenAILikeEmbedding
from llama_index.llms.openai_like import OpenAILike

load_dotenv()
API_KEY = os.environ["DASHSCOPE_API_KEY"]
API_BASE = "https://dashscope.aliyuncs.com/compatible-mode/v1"

Settings.llm = OpenAILike(
    model="qwen-plus", api_key=API_KEY, api_base=API_BASE,
    is_chat_model=True, is_function_calling_model=True,
)
Settings.embed_model = OpenAILikeEmbedding(
    model_name="text-embedding-v3", api_key=API_KEY, api_base=API_BASE,
)

PERSIST_DIR = "./storage"

if Path(PERSIST_DIR).exists() and any(Path(PERSIST_DIR).iterdir()):
    print(">> 检测到已持久化的索引,直接加载(跳过文档解析)...")
    storage_context = StorageContext.from_defaults(persist_dir=PERSIST_DIR)
    index = load_index_from_storage(storage_context)
else:
    print(">> 首次运行:解析文档并构建索引...")
    documents = SimpleDirectoryReader("data").load_data()
    index = VectorStoreIndex.from_documents(documents, show_progress=True)
    index.storage_context.persist(persist_dir=PERSIST_DIR)
    print(f">> 索引已保存到 {PERSIST_DIR}")

query_engine = index.as_query_engine()

async def main():
    response = await query_engine.aquery("作者大学时期做了什么?")
    print(response)

if __name__ == "__main__":
    asyncio.run(main())

以 75KB 文档实测,storage/ 目录共五个文件:

文件大小内容
docstore.json137KB文档库:分块文本、节点元数据、分块与源文档的溯源关系
index_store.json2KB索引结构:节点与索引、节点与向量的映射
default__vector_store.json501KB向量数据(体积最大):文本向量、向量到源文档映射
graph_store.json18B知识图谱存储(本例未建图索引,为空壳)
image__vector_store.json72B图像向量存储(本例无图像,为空壳)

两点提醒:

文档越大,解析与 embedding 成本越高,持久化的收益越明显。

4.6 拓展方向

五、应用价值

六、SEO关键词

LlamaIndex、阿里云百炼、RAG、FunctionAgent、智能体、通义千问、OpenAILike、text-embedding-v3、向量检索、多轮对话记忆

推荐阅读

更多工业 AI、智能制造与技术实践文章

AI视觉

YOLO目标检测模型调参入门:从训练参数到检测效果优化

YOLO目标检测模型调参入门指南:详解 epochs、imgsz、batch、模型大小、conf、IoU 等核心参数的作用与调节方法,给出工业视觉、疲劳驾驶、缺陷检测等 AI 项目的调参顺序与实验对比思路,帮助初学者在精度、速度与显存之间找到平衡。

工业互联网

Linux系统篇(二十二)——文件(六):目标文件与 ELF 深度解析:从编译到加载的全景揭秘

从目标文件出发,逐层解剖ELF头部、节头表与程序头表,讲透静态链接重定位、动态链接GOT/PLT以及程序从编译到加载的完整过程。

AI视觉

陶瓷浮雕盘印刷视觉定位方案:8K线扫相机 + 暗场光源 + 旋转平台

针对最大Φ320mm带浮雕、釉面反光的陶瓷盘自动印刷定位难题,提出8K线扫相机 + 低角度暗场光源 + 旋转平台 + 编码器同步 + 模板匹配的完整视觉定位方案,输出X/Y/θ坐标,可与Trio运动控制器联动实现闭环印刷。

工业互联网

局域网服务器如何实现外网访问:Ubuntu 22.04 搭建 FRP 内网穿透服务器

工业现场、企业局域网和工厂 MES 系统中,服务器没有公网 IP 时如何实现外网远程访问?本文以 Ubuntu 22.04 为例,完整演示 FRP 内网穿透方案:frps 服务端配置、frpc 客户端配置、Systemd 开机自启、多工厂统一接入、HTTPS 安全架构以及完整的故障排查与安全建议。

数码印刷

RIP软件底层逻辑全解析:从CMYK墨量控制到PRN灰度网点数据

本文深入数码印刷RIP软件的底层逻辑:CMYK曲线与单通道/总墨量限制如何控制物理边界,打印机线性化与ICC特性文件如何实现精准色彩复制,灰度PRN数据与位深度(1/2/3位)如何驱动可变网点喷头,以及半色调方法、PPI/DPI匹配和常见印刷故障的排查指南。

工业互联网

Linux系统篇(五)——工具篇(一):搞懂 Linux 包管理,玩转 Vim 编辑器

从软件安装底层逻辑讲透 yum/apt 包管理器工作原理,再深入 Vim 多模式操作与高效快捷键,为 Linux 开发打下坚实基础。

评论(0)