大数跨境
0
0

《万物皆可LLM》008:一次不愉快的 LangChain 数据库问答和可视化分析实践

《万物皆可LLM》008:一次不愉快的 LangChain 数据库问答和可视化分析实践 数翼
2023-09-01
0
导读:数据问答和可视化分析肯定是企业管理应用的日常,今天带大家看怎么实现这个功能。先看先最终效果吧:

数据问答可视化分析肯定是企业管理应用的日常,今天带大家看怎么实现这个功能。

先看先最终效果吧:

数据问答和可视化效果

关于标题的不愉快

首先呢,我确实使用 LangChain 的 SqlAgent 实现了数据问答和可视化分析。

其次呢,LangChain 的逻辑和内置提示模板不是那么好用,偶尔会死循环。Token 用的也是飞快,如果真的这样上线,执行一次分析可能要几毛钱的价格。

下面是我开发用的 OpenAI 账号的用量,平时写写代码用量都很少。

之前的 OpenAI 用量

这两天写这篇文档的代码时候用了下 LangChain SqlAgent,流量(Token)使用飙升,虽然只有几美金,但是我这两天每天也只是调用了十几次而已(还没达到理想效果)。

调用了十几次 LangChain SqlAgent 之后

关于架构

我之前以为的架构 SqlAgent 这块的是这样:

LangChain SqlAgent 简明架构

实际上他是这样,中间会有不停的试错纠错重试:

LangChain SqlAgent 架构(含部分交互)

这也是我为什么之前建议过别人能不用就不用 LangChain,除了 Hello World 这样的 Demo 东西,后面 LangChain 还是有一些问题的。

总结下就是:

深入研究学习 LangChain 不如直接调用 OpenAI 来实现(重构)应用。

废话不说,看看这个数据问答开发过程吧。

需求

有两个小的数据分析需求。

分析邮件

第一个是咱们之前关于邮件的:

  • • 统计下有谁给我发了邮件,

  • • 邮件的主题分类都是那些,比如

饼图展示分类

分析开发任务

第二个是关于开发任务的,假设你是某个部门负责人、比如开发团队负责人,你是不是时不时的想看看团队的开发情况?

  • • 这周有多少个开发任务,

  • • 有多少任务延期了了,多少任务准时完成了,

  • • 各个部门完成的任务情况,

  • • 任务的打分、耗时等分布。

比如这样?

散点图多维度展示开发任务

或者这样:

Area 线图展示开发任务

LangChain 的 SQL 支持

首先,企业数据通常存储在 SQL 数据库中,如果要做数据分析,肯定离不开 SQL 和数据库。

LangChain 提供了 SqlChain 和 Agent 来实现基于自然语言提示构建和运行 SQL 查询。

底层实现是通过 SQLAlchemy 这个 ORM 库,SQLAlchemy 支持的主要 SQL 方言的兼容(例如 MySQL、PostgreSQL、Oracle SQL、Databricks、SQLite)。

基于这些能力,我们可以试下下面的应用:

  • • 自然语言的数据库查询

  • • 根据数据库的数据回答问题聊天机器人

  • • 自然语言的数据分析,和构建自定义仪表板

简明 LangChain SqlAgent 架构

实现

引入相关包

import sys

from langchain.agents import create_sql_agent, AgentType
from langchain.agents.agent_toolkits import SQLDatabaseToolkit
from langchain.chains import create_sql_query_chain
from langchain.chat_models import ChatOpenAI
from langchain.sql_database import SQLDatabase
from langchain.llms.openai import OpenAI
from langchain.agents import AgentExecutor

创建数据库字段

# sqlite
db = SQLDatabase.from_uri("sqlite:////Users/.../emails.db")

# postgres
db = SQLDatabase.from_uri("postgresql://user:password@localhost:5432/postgres?connect_timeout=10")

创建 Agent

llm = OpenAI(temperature=0, verbose=True)
toolkit = SQLDatabaseToolkit(db=db, llm=OpenAI(temperature=0))

agent = create_sql_agent(
    llm=llm,
    toolkit=toolkit,
    verbose=True,
    agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
)

描述表结构

response = agent.run("描述下邮件表")
print(response)

我根据日志画了一下 LangChain 的执行过程(多次调用 LLM 的过程):

描述表 Agent 执行过程

下面是打印的详细输出,可以看到 LangChain 的整个思考过程。

Entering new AgentExecutor chain...
Action: sql_db_list_tables
Action Input: 
Observation: emails
Thought: I should query the schema of the emails table
Action: sql_db_schema
Action Input: emails
Observation: 
CREATE TABLE emails (
    id BIGINT, 
    from_email VARCHAR(255), 
    from_name VARCHAR(255), 
    subject VARCHAR(1000), 
    date_beijing TIMESTAMP(0) WITHOUT TIME ZONE, 
    text TEXT
)

/*
3 rows from emails table:
id from_email from_name subject date_beijing text
8129 info@techtarget.com ComputerWeekly.com Inside Group-IB’s  playbook 2023-04-11 19:39:57 None
8156 update@grafana.com Grafana Labs Team You're invited: Grafana Terraform Provider 2023-04-12 10:01:23 None
*/
Thought: I now know the final answer
Final Answer: The emails table contains the following columns: id, from_email, from_name, subject, date_beijing, and text.

Finished chain.
The emails table contains the following columns: id, from_email, from_name, subject, date_beijing, and text.

客户端的返回时:

The emails table contains the following columns: id, from_email, from_name, subject, date_beijing, and text.

查询邮件,用 Markdown 展示

提问如下:

查看最近3个月有多少封的邮件。返回给我发送邮件最多的5个人,用 Markdown 表格展示 姓名,邮件地址,总邮件数,最后发送时间,

LangChain 执行过程如下,依然看图:

查询邮件 Agent 执行过程

看下完整的输出:

Entering new AgentExecutor chain...
Action: sql_db_list_tables
Action Input: 
Observation: emails, tasks
Thought: I should query the schema of the emails table
Action: sql_db_schema
Action Input: emails
Observation: 
CREATE TABLE emails (
    id BIGINT, 
    from_email VARCHAR(255), 
    from_name VARCHAR(255), 
    subject VARCHAR(1000), 
    date_beijing TIMESTAMP(0) WITHOUT TIME ZONE, 
    text TEXT
)
/*
3 rows from emails table:
id from_email from_name subject date_beijing text
8129 info@zmp.techtarget.com ComputerWeekly.com Inside Group-IB’s cyber security playbook 2023-04-11 19:39:57 None
8156 update@grafana.com Grafana Labs Team You're invited: Mastering the Grafana Terraform Provider 2023-04-12 10:01:23 None
*/
Thought: I should query the emails table to get the data I need
Action: sql_db_query
Action Input: SELECT from_name, from_email, COUNT(*) as total_emails, MAX(date_beijing) as last_sent_date FROM emails WHERE date_beijing > NOW() - INTERVAL '3 MONTHS' GROUP BY from_name, from_email ORDER BY total_emails DESC LIMIT 5
Observation: [('ComputerWeekly.com', 'info@zmp.techtarget.com', 20, datetime.datetime(2023, 8, 17, 18, 31, 50)), ('Grafana Labs', 'cloud-success@grafana.
Thought: I now know the final answer
Final Answer: 
| 姓名 | 邮件地址 | 总邮件数 | 最后发送时间 |
| --- | --- | --- | --- |
| ComputerWeekly.com | info@techtarget.com | 20 | 2023-08-17 18:31:50 |
| Grafana Labs | cloud@grafana.com | 13 | 2023-08-22 14:57:27 |
| Google Cloud | googlecloud@google.com | 9 | 2023-08-25 14:47:25 |
| LeanIX Connect Summit | summit@connect.com | 8 | 2023-08-24 14:05:50 |
| Grafana Labs Team | update@grafana.com | 6 | 2023-07-11 12:31:15 |
Finished chain.

谁给我发的邮件最多?

上面其实还好,当我问下下面这个问题的时候, LangChain Agent 炸了!

response = agent.run("查看最近一个月的邮件。看谁给我发的邮件最多?")
print(response)

LangChain 会告诉你:Agent stopped due to iteration limit or time limit.

没错这么简单的问题,他因为轮训次数太多超出限制停止尝试了,

输出大概是这样的:

> Entering new AgentExecutor chain...
Action: sql_db_list_tables
Action Input: 
Observation: emails
Thought: I should query the schema of the emails table

...
此处省略 100 行
...

Thought:

> Finished chain.
Agent stopped due to iteration limit or time limit.

问题的原因无非就是生成的 SQL 错误等等,然后不停修复不停重试。

这跟 LLM 有关(GPT4可能会好很多,我用的 GPT3),同样的问题有时会成功,比如一次成功的:

Finished chain.
ComputerWeekly.com 发了最多的邮件,共发了 22 封。

这个问题不纠结,我们继续(后面还会出现这种类似的死循环过程,我就不赘述了)。

可视化

下面我们来解决可视化的问题,当然可视化也有两类方案:

  • • 一个是后端 Python 生成图片返回前端, 比如 Matplotlib;

  • • 一个是返回 Json 数据给前端显示,比如 ECharts。

可视化方案:客户端 vs 服务端

我们尝试使用前端展示的方案,毕竟这样的交互性强一点。

提示

我们现在还是使用 LangChain,那么此处的关键就是编写 Prompt,能让 AI 做的都让 AI 做,比如:直接生成 ECharts 的配置。

prompt = '''
根据我的问题,执行数据查询,并选择合适的可视化方案(线图、饼图、柱状图等),生成 echarts 的配置,

问题:%s 。

数据为: %s

请按照以下格式回复我:

:::
{
  "charts":{<echarts的配置>}
}
:::
'''

可视化最近一周任务

提问:最近一周不同部门每天完成的任务数

返回的配置:

{
  "charts": {
  "option": {
    "title": {
      "text": "最近一周不同部门每天完成的任务数"  
    }
    ...
  }
}

可视化效果如下:

OpenAI生成的 ECharts 可视化配置

集成到我们的前端里面:

可视化集成到前端界面内

总结

上面是简单粗暴的 AI 数据应用实现,下一期以应用架构的四维,融合大语言模型的能力来实现一个可用的数据交互功能。



--- END ---


【声明】内容源于网络
0
0
数翼
专注 AIGC 人工智能知识传播和实践
内容 171
粉丝 0
数翼 专注 AIGC 人工智能知识传播和实践
总阅读0
粉丝0
内容171