llamaindex实战-Agent-在Agent中和数据库对话(本地部署)

server/2024/11/17 16:56:34/

概述

本文实现了一个简单的智能Agent,该Agent先从数据库中查询出数据,然后再通过工具函数来对数据进行处理。这是一个非常常见的场景。从这个场景可以扩展到多个实际的场景。

同样,本文的实验都是在本地一台:16C32G的linux机器(CPU)上完成。

数据准备

在mysql数据库中创建一张表:

CREATE TABLE `city_stats` (`city_name` varchar(100) DEFAULT NULL,`population` int(11) DEFAULT NULL,`country` varchar(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

在数据表中插入几条数据:

city_namepopulationcountry
Toronto2930000Canada
Tokyo13929286Japan
Berlin600000Germany

实现逻辑

  1. 定义本地嵌入模型,并把本地嵌入模型的对象赋值给Settings.embed_model变量。这个是llamaindex的一个设置项。

    注意:这个一定要用本地嵌入模型来进行重置,否则会默认使用openai的接口,这样就达不到本地部署的目的了。

  2. 构建数据库查询引擎。这个主要是通过创建NLSQLTableQueryEngine对象来实现的。通过这个对象,就可以使用自然语言和数据库对话。

  3. 构建一系列的工具函数,通过这些工具函数来实现额外的一些功能。

  4. 把数据库查询引擎通过QueryEngineTool对象封装成工具链中的一个对象,这样Agent就可以把查询引擎当成工具链中的一个工具来选择和使用了。

  5. 最后就是要写好提示词,给Agent一个明确的指令。我这里的指令是:先查询出两个城市的人口数,然后再调用add函数把这两个城市的人口数相加。

注意:该实验只是一个例子,演示了数据库查询引擎和Agent工具函数结合使用。这种组合实际上还可以实现更多的场景的功能。

实现代码

from llama_index.core.agent import ReActAgent
from llama_index.llms.openai import OpenAI
from llama_index.core.tools import FunctionTool
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex, Settings
from llama_index.core.tools import QueryEngineTool
from llama_index.llms.ollama import Ollama
​
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.ollama import Ollama
from llama_index.core import SQLDatabase
from llama_index.llms.ollama import Ollama
from ollama import Client
​
from llama_index.core.query_engine import NLSQLTableQueryEngine
​
from sqlalchemy import (create_engine,select,
)
from sqlalchemy import insert
​
# 构建本地嵌入模型
local_model = "/opt/models/BAAI/bge-base-en-v1.5"
# bge-base embedding model
Settings.embed_model = HuggingFaceEmbedding(model_name=local_model)
​
# 创建本地大模型
#Settings.llm = Ollama(model="llama3.2", request_timeout=360)
Settings.llm = Ollama(model="gemma2", request_timeout=360)
​
## 创建数据库查询引擎
engine = create_engine("mysql+pymysql://admin:admin123@192.168.1.54/llmdb")
# prepare data
sql_database = SQLDatabase(engine, include_tables=["city_stats"])
query_engine = NLSQLTableQueryEngine(sql_database=sql_database, tables=["city_stats"], llm=Settings.llm
)
​
# 创建工具函数
def multiply(a: float, b: float) -> float:"""Multiply two numbers and returns the product"""return a * b
​
multiply_tool = FunctionTool.from_defaults(fn=multiply)
​
def add(a: float, b: float) -> float:"""Add two numbers and returns the sum"""return a + b
​
add_tool = FunctionTool.from_defaults(fn=add)
​
# 把数据库查询引擎封装到工具函数对象中
population_tool = QueryEngineTool.from_defaults(query_engine, name="city_population",description="A SQLTable query engine about population of the city and country."
)
​
# 构建RAG查询引擎
agent = ReActAgent.from_tools([multiply_tool, add_tool, population_tool], verbose=True)
# 通过agent给出指令
response = agent.chat("Please get the populations of Toronto city and Tokyo city from database table, and the add the population!")
​
print(response)

代码给出的指令是:查出Toronto和Tokyo城市的人口,然后把这两个城市的人口数量加起来,最终得到输出结果。这只是一个简单的例子,可以根据实际业务场景来修改例子进行测试。

结果输出

python agent_rag_db.py 
> Running step 1a514ec3-de70-440d-a58d-0304ff0a02e5. Step input: Please get the populations of Toronto city and Tokyo city from database table, and the add the population!
Thought: The current language of the user is: English. I need to use a tool to help me answer the question.
Action: city_population
Action Input: {'input': 'Toronto'}
Observation: Toronto has a population of 2,930,000.  
​
> Running step 84aa20cf-31c6-402e-95d5-8b265b8ddef8. Step input: None
Thought: The current language of the user is: English. I need to use a tool to help me answer the question.
Action: city_population
Action Input: {'input': 'Tokyo'}
Observation: The population of Tokyo is 13,929,286. 
​
Let me know if you have any other questions about Tokyo or cities around the world!
> Running step 1f40acfb-1b80-4962-80e6-cbe5395182a6. Step input: None
Thought: I can answer without using any more tools. I'll use the user's language to answer
Answer: The population of Toronto is  2,930,000 and the population of Tokyo is 13,929,286. Their combined population is 16,859,286.
The population of Toronto is  2,930,000 and the population of Tokyo is 13,929,286. Their combined population is 16,859,286.

从以上输出可以看出,Agent把我的指令规划成了3个步骤(这个是不是最优的?),先分两步进行查询结果,然后再把两步得结果相加得到最终结果。

要注意:Agent有planning能力,但这个能力也有好有不好,规划得好,那么可能实现的效率就高。从以上输出来看,我们的Agent的规划步骤并不一定是最优的(其实我们可以一步查询出两个城市的人口,而不是分成两步),这个取决于大模型的能力,也和提示词的写法有很大的关系。

小结

最终,我们给Agent的指令,Agent通过自动规划,计算出了我们想要的结果。但这个过程有很多可以去优化的点。一是通过自然语言和数据库的数据表对话的能力。二是Agent的规划能力。规划的好,效率就高,规划的不好就会浪费资源。这里我们可以通过优化我们的提示词来更好的让Agent给出好的规划。


http://www.ppmy.cn/server/142693.html

相关文章

D3的竞品有哪些,D3的优势,D3和echarts的对比

D3 的竞品 ECharts: 简介: ECharts 是由百度公司开发的一款开源的 JavaScript 图表库,提供了丰富的图表类型和高度定制化的配置选项。特点: 易于使用,文档详尽,社区活跃,支持多种图表类型(如折线图、柱状图、饼图、散点…

ISUP协议视频平台EasyCVR视频设备轨迹回放平台智慧农业视频远程监控管理方案

在当今快速发展的农业领域,智慧农业已成为推动农业现代化、助力乡村全面振兴的新手段和新动能。随着信息技术的持续进步和城市化进程的加快,智慧农业对于监控安全和智能管理的需求日益增长。 视频设备轨迹回放平台EasyCVR作为智慧农业视频远程监控管理方…

【C#】C#编程入门指南:构建你的.NET开发基础

文章目录 前言:1. C# 开发环境 VS的基本熟悉2. 解决方案与项目的关系3. 编辑、编译、链接、运行4. 托管代码和CLR4.1 CLR:4.2 C# 代码第编译过程(两次编译的) 5. 命名空间6. 类的组成与分析7. C# 的数据类型7.1 值类型7.2 引用类型…

循环神经网络(GRU)全面解析

1. 引言 什么是GRU? GRU(Gated Recurrent Unit,门控循环单元)是一种循环神经网络(Recurrent Neural Network, RNN)变体,旨在处理序列数据。GRU在LSTM(Long Short-Term Memory&…

超子物联网HAL库笔记:定时器[外部模式]篇

超子物联网 HAL库学习 汇总入口: 超子物联网HAL库笔记:[汇总] 写作不易,如果您觉得写的不错,欢迎给博主来一波点赞、收藏~让博主更有动力吧! 一、资源介绍:STM32F103C8T6定时器资源介绍 高级定时器&#x…

PGSQL记录

1.每句后面需要加 ; 2.获取时间 当前时间 : GETDATE() now() LOCALTIMESTAMP 提前几天时间: now()::DATE -3 now()::TIME 推迟几天时间:now()1 获取第几周: date_part(week,Today) day month 设定每周的第一天为周一 SET datestyle TO IS…

github和Visual Studio

1、代码下载和提交 GitHubDesktopSetup-x64.exe 使用很简单,自己稍微琢磨下就明白了。 2、Visual Studio 2022 2.1 安装组件及学习内容 Visual Studio 中的 CMake 项目 | Microsoft Learn 2.2 打开 CMakeLists.txt 文件 定位并选择 CMakeLists.txt 文件 …

如何基于Tesseract实现图片的文本识别

在前一篇文章基础上,如何将报告图片中的文本解析出来,最近研究了基于Tesseract的OCR方案,Tesseract OCR是一个开源的OCR引擎,主要结合开源的tesseract和pytesseract,实现了jpg/png等格式图片文本识别,供大家…