( 教学 )Agent 构建 Prompt(提示词)5. PandasDataFrameOutPutParser

30 阅读4分钟

( 教学 )Agent 构建 Prompt(提示词)5. PandasDataFrameOutPutParser

LLM 的输出以 pd.DataFrame 格式进行控制。

“Pandas”是一个软件包,以表格(即表格数据)的形式存在,深受数据科学家的青睐。它能帮助您进行数据的探索、清理和处理。 若想进一步了解 pd.DataFrame 及其功能,请访问 Pandas 官方教程之一,即 10 分钟学会 Pandas

  • 这既可以作为将结构化输出转换为 LLM 查询的字符串形式,也可以作为将结构化输入提供给 LLM 查询的形式

  • 作为输入,可以使用 pd.DataFrame 数据集,使 LLM 与数据进行交互。 “本教程的目标” 了解 PandasDataFrameOutputParser 是如何用于与 pd.DataFrame 进行交互的。 数据采集

  • 可访问figshare.com网站,可以在该网站上找到各类学术研究的成果,包括从 CSV 格式到 PDF 格式的文件。

定义大模型

from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
from dotenv import load_dotenv
import os

load_dotenv()

Qwen2_5_7B_Instruct_llm = ChatOpenAI(
    temperature=0.1,  # 控制输出的随机性和创造性,值越低输出越稳定可预测,值越高输出越有创意但可能偏离预期 (范围: 0.0 ~ 2.0)
    model_name="Qwen/Qwen2.5-7B-Instruct",  # 硅基流动支持的模型名称
    openai_api_key=os.getenv("SILICONFLOW_API_KEY"),  # 从环境变量获取API密钥
    openai_api_base="https://api.siliconflow.cn/v1"  # 硅基流动API的基础URL
)

定义输出模型

import pandas as pd
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI

class DataFrameResponse(BaseModel):
    """期望 LLM 返回表格数据"""
    dataframe: list[dict] = Field(..., description="表格数据,每行是一个字典")

model = Qwen2_5_7B_Instruct_llm.with_structured_output(DataFrameResponse)

response = model.invoke("列出前5个最大哺乳动物及其特征")
df = pd.DataFrame(response.dataframe)

不适用模型的情况

  • format_parser_output函数用于将解析器输出转换为字典格式并格式化输出。
  • 当输入为pd.DataFrame或文件时。
def format_parser_output(parser_output: Dict[str, Any]) -> None:
    length_val = len(list(parser_output.values()))
    if length_val == 1 and isinstance(parser_output.values, (int, float)):
        return {"result": parser_output}
        # 遍历解析器输出(字典)的"键"
    else:
        for key in parser_output.keys():
            parser_output[key] = parser_output[key].to_dict()
            # 美化打印
            return pprint.PrettyPrinter(width=4, compact=True).pprint(parser_output)

我们使用模拟数据来演示:

df = pd.read_csv("./data/Air-Traffic-Passenger-Statistics-csv.csv")
df.head()

输出结构

  • 数据框的前五行
    • 包含所有列的前五行数据
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
Activity Period Activity Period Start Date Operating Airline Operating Airline IATA Code Published Airline Published Airline IATA Code GEO Summary GEO Region Activity Type Code Price Category Code Terminal Boarding Area Passenger Count data_as_of data_loaded_at
0 199907 1999/07/01 ATA Airlines TZ ATA Airlines TZ Domestic US Deplaned Low Fare Terminal 1 B 31432 2023/11/20 07:01:34 AM 2023/11/20 07:02:25 AM
1 199907 1999/07/01 ATA Airlines TZ ATA Airlines TZ Domestic US Enplaned Low Fare Terminal 1 B 31353 2023/11/20 07:01:34 AM 2023/11/20 07:02:25 AM
2 199907 1999/07/01 ATA Airlines TZ ATA Airlines TZ Domestic US Thru / Transit Low Fare Terminal 1 B 2518 2023/11/20 07:01:34 AM 2023/11/20 07:02:25 AM
3 199907 1999/07/01 Aeroflot Russian International Airlines NaN Aeroflot Russian International Airlines NaN International Europe Deplaned Other Terminal 2 D 1324 2023/11/20 07:01:34 AM 2023/11/20 07:02:25 AM
4 199907 1999/07/01 Aeroflot Russian International Airlines NaN Aeroflot Russian International Airlines NaN International Europe Enplaned Other Terminal 2 D 1198 2023/11/20 07:01:34 AM 2023/11/20 07:02:25 AM
import pandas as pd
from typing import Dict, Any
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

class CSVAnalyzer:
    def __init__(self, model_name="Qwen2.5-7B-Instruct"):
        self.model = Qwen2_5_7B_Instruct_llm
    
    def analyze_csv(self, csv_data: str, question: str) -> Dict[str, Any]:
        """完整CSV分析器"""
        df = pd.read_csv(pd.compat.StringIO(csv_data))
        
        prompt = ChatPromptTemplate.from_template("""
                                            CSV数据概览:
                                            - 行数:{row_count}
                                            - 列数:{col_count} 
                                            - 列名:{columns}
                                            - 数据预览:
                                            {preview}

                                            完整数据:
                                            {csv_data}

                                            问题:{question}

                                            请提供:
                                            1. 分析结果
                                            2. 可视化建议
                                            3. 业务洞察
                                            """)
        
        result = prompt | self.model | StrOutputParser()
        response = result.invoke({
            "row_count": len(df),
            "col_count": len(df.columns),
            "columns": ", ".join(df.columns),
            "preview": df.head(3).to_string(),
            "csv_data": csv_data,
            "question": question
        })
        
        return {
            "dataframe": df,
            "analysis": response,
            "summary_stats": df.describe()
        }

# 使用
analyzer = CSVAnalyzer()
csv_data = df.to_csv(index=False)

result = analyzer.analyze_csv(csv_data, "分析薪资分布和城市关系")
print(result["analysis"])