LlamaIndex-Agent查询数据库
安装
pip install llama-index
pip install peewee
创建数据库
创建用户表
CREATE TABLE users (
user_id INT PRIMARY KEY, -- 用户唯一标识,自动递增
name VARCHAR(255) NOT NULL, -- 用户名称,不允许为空
address VARCHAR(255), -- 用户地址,允许为空
email VARCHAR(255), -- 用户邮箱,允许为空
phone_number VARCHAR(20), -- 用户手机号,允许为空
birthday DATE -- 用户生日,允许为空
);
测试数据
INSERT INTO users (id,name, address, email, phone_number, birthday) VALUES
(1,'Alice', '北京市朝阳区', 'alice@example.com', '13800138000', '1990-05-15'),
(2,'Bob', '上海市浦东新区', 'bob@example.com', '13900139000', '1985-08-20'),
(3,'Charlie', '广州市天河区', 'charlie@example.com', '13700137000', '1995-12-10'),
(4,'David', '深圳市南山区', 'david@example.com', '13600136000', '1988-03-25'),
(5,'Eve', '杭州市西湖区', 'eve@example.com', '13500135000', '1992-07-30');
创建工具函数
from peewee import *
db = SqliteDatabase('test.db')
db.connect()
class BaseModel(Model):
class Meta:
database = db
class UserInfo(BaseModel):
user_id = IntegerField()
name = CharField()
address = CharField()
email = CharField()
phone_number = CharField()
birthday = DateField()
class Meta:
table_name = "users"
# 具体的工具函数,此处需要定义字段,模型将根据用户提供的信息自动匹配字段(受用户输入影响很大)
def getuserinfo(name: str = None, email: str = None, address: str = None, birthday: str = None,
phone_number: str = None) -> dict:
"""根据用户姓名、邮箱、地址查询用户信息"""
query = UserInfo.select(UserInfo.user_id, UserInfo.name, UserInfo.address, UserInfo.email, UserInfo.phone_number,
UserInfo.birthday)
if name:
query = query.where(UserInfo.name == name)
if birthday:
query = query.where(UserInfo.birthday == birthday)
if phone_number:
query = query.where(UserInfo.phone_number == phone_number)
if address:
query = query.where(UserInfo.address == address)
if email:
query = query.where(UserInfo.email == email)
# rs = query.dicts()
query_result = [user.__data__ for user in query]
if query_result:
query_result[0]["birthday"] = str(query_result[0]["birthday"])
print(query_result)
return {"result": query_result}
自定义LLM
from typing import Any, Generator
from llama_index.core.llms import (
CustomLLM,
CompletionResponse,
LLMMetadata,
)
from llama_index.core.llms.callbacks import llm_completion_callback
from openai import OpenAI
from pydantic import Field
# 定义新的LLM类,继承自CustomLLM基类
class LLM(CustomLLM):
api_key: str = Field(default="api_key")
base_url: str = Field(default="http://127.0.0.1:8000/v1")
model_name: str = Field(default="glm-4-flash")
client: OpenAI = Field(default=None, exclude=True) # 显式声明 client 字段
def __init__(self, api_key: str, base_url: str, model_name: str = model_name, **data: Any):
super().__init__(**data)
self.api_key = api_key
self.base_url = base_url
self.model_name = model_name
self.client = OpenAI(api_key=self.api_key, base_url=self.base_url) # 使用传入的api_key和base_url初始化 client 实例
@property
def metadata(self) -> LLMMetadata:
"""Get LLM metadata."""
return LLMMetadata(
model_name=self.model_name,
)
@llm_completion_callback()
def complete(self, prompt: str, **kwargs: Any) -> CompletionResponse:
response = self.client.chat.completions.create(model=self.model_name,
messages=[{"role": "user", "content": prompt}])
if hasattr(response, 'choices') and len(response.choices) > 0:
response_text = response.choices[0].message.content
return CompletionResponse(text=response_text)
else:
raise Exception(f"Unexpected response format: {response}")
@llm_completion_callback()
def stream_complete(
self, prompt: str, **kwargs: Any
) -> Generator[CompletionResponse, None, None]:
response = self.client.chat.completions.create(
model=self.model_name,
messages=[{"role": "user", "content": prompt}],
stream=True
)
try:
for chunk in response:
chunk_message = chunk.choices[0].delta
if not chunk_message.content:
continue
content = chunk_message.content
yield CompletionResponse(text=content, delta=content)
except Exception as e:
raise Exception(f"Unexpected response format: {e}")
主函数
这里用的是硅基流动,新用户注册送14元的额度,这是邀请连接:https://cloud.siliconflow.cn/i/Fvcyk52x 通过邀请链接注册我也可以获得14元额度,也可以使用其他厂商的
# encoding:utf8
from llama_index.core.agent import ReActAgent
from llama_index.core.tools import FunctionTool
from agent_tools.getUserInfo import getuserinfo
from llms_class import LLM
class UserInfoAgent:
def __init__(self):
# model_name 模型名称
# base_url 接口地址
# api_key 自己的api_key
self.llm = LLM(model_name="deepseek-ai/DeepSeek-R1-Distill-Qwen-14B", base_url="https://api.siliconflow.cn/v1",
api_key="sk-xxxx")
self.tools = []
def add_tool(self, tool):
self.tools.append(tool)
def chat(self, query):
# 添加自定义工具,这里的getuserinfo函数是自定义的函数,需要添加到工具列表中
userinfo_tool = FunctionTool.from_defaults(fn=getuserinfo)
self.tools.append(userinfo_tool)
# 创建ReActAgent实例
agent = ReActAgent.from_tools(self.tools, llm=self.llm, verbose=True)
return agent.chat(query)
# 调用
if __name__ == '__main__':
userinfo_agent = UserInfoAgent()
# 查询用户Eve的所有信息,如果要查询表数据总数,需要自定义新的工具函数用于获取表数据总数
userinfo_agent.chat("查询用户Eve的所有信息")
效果
> Running step 71672083-3e6e-4928-9386-4357d913c675. Step input: 查询用户Eve的所有信息
Thought: The current language of the user is: 中文. I need to use a tool to help me answer the question.
Action: getuserinfo
Action Input: {'name': 'Eve'}
Observation: {'result': [{'user_id': 5, 'name': 'Eve', 'address': '杭州市西湖区', 'email': 'eve@example.com', 'phone_number': '13500135000', 'birthday': '1992-07-30'}]}
> Running step f326ef97-d301-4172-a74a-b7ef89e25875. Step input: None
Thought: (Implicit) I can answer without any more tools!
Answer: Answer: Eve的用户信息如下:
- 用户ID:5
- 姓名:Eve
- 地址:杭州市西湖区
- 邮箱:eve@example.com
- 电话号码:13500135000
- 生日:1992年7月30日