Spaces:
Running
Running
File size: 7,977 Bytes
342e4c4 495d32d 342e4c4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | import re
import streamlit as st
from typing import IO, List
from prompt_engineer.call_llm import LLMClient
class DataLoadingAgent(LLMClient):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.file_name = []
self.user_input = None
self.par_content = ""
self.dfs = None
self.abstract=None
self.full = None
self.finish_auto_task = False
def finish_auto(self):
self.finish_auto_task = True
def save_file_name(self, file_name):
self.file_name.append(file_name)
def load_file_name(self):
return self.file_name
def save_dfs(self, dfs):
self.dfs = (dfs)
def load_dfs(self):
return self.dfs
def clear_file_name(self):
self.file_name = []
def read_names_from_file(self, uploaded_names_file, df_head):
"""
从上传的 .names/.arff 文件中提取属性名。
优先使用 LLM 识别 @attribute 行中的属性名;如果 LLM 调用失败,退回到正则解析。
"""
raw = uploaded_names_file.read().decode('utf-8', errors='ignore')
try:
uploaded_names_file.seek(0)
except Exception:
pass
prompt = (
"下面是上传的 names 和 df_head 文件内容,请仅以 Python 列表格式返回与df_head一一对应的所有属性(attribute)名称,"
"并保持顺序,不要添加多余文字,请注意,你只需要返回一个列表,不要出现任何markdown语法:\n```\n"
f"name文件:{raw}\n```"
f"df_head:{df_head}\n```"
)
try:
response = self.call(prompt)
names_list = eval(response.strip())
if isinstance(names_list, list) and all(isinstance(n, str) for n in names_list):
col_names = names_list
else:
raise ValueError("LLM 输出格式不正确")
except Exception:
col_names = []
attr_re = re.compile(
r"""^@attribute\s+
['"]?([^'"\s]+)['"]?
\s+.+
""",
re.IGNORECASE | re.VERBOSE
)
for line in raw.splitlines():
line = line.strip()
if not line:
continue
if line.lower().startswith('@data'):
break
m = attr_re.match(line)
if m:
col_names.append(m.group(1))
counts: dict[str, int] = {}
unique_names: List[str] = []
for name in col_names:
if name in counts:
counts[name] += 1
unique_names.append(f"{name}_{counts[name]}")
else:
counts[name] = 0
unique_names.append(name)
return unique_names
def do_data_description(self, df, user_input=None, memory_limit=6):
recent_memory = self.memory[-memory_limit:] if self.memory else []
if recent_memory:
formatted_memory = "\n".join(
f"{m['role']}: {m['content']}" for m in recent_memory
)
memory_block = f"{formatted_memory}"
else:
memory_block = ""
prompt = (
"你是一名专业的数据分析助手,负责解释数据结构与业务含义。\n"
f"- 数据维度:{df.shape[0]} 行 × {df.shape[1]} 列\n"
f"- 列名和数据类型:{dict(zip(df.columns.tolist(), df.dtypes.astype(str).tolist()))}\n"
f"- 前 5 行样本:\n{df.head().to_dict(orient='list')}\n\n"
f"""- 数据解释聊天对话:
--- 开始聊天记录 ---
{memory_block}
--- 结束聊天记录 ---"""
)
if user_input is not None:
prompt += f"""
请严格依据用户需求“{user_input}”,对当前数据进行深入、系统的分析。
要求:
1. 分析内容必须与该需求完全对应,不能添加无关推断。
2. 结论要具体、清晰,可直接支持后续报告撰写或建模步骤。
3. 分析语言应专业、简洁,不使用模糊或情绪化表述。
"""
else:
prompt += """
以下是一个数据集的基本概览。请帮助我分析它的性质和结构,并回答以下问题:
1. 该数据集可能来源于什么业务或研究场景?
2. 各主要字段分别代表什么含义?若能判断,请说明其单位或数值含义。
3. 数据中是否存在明显异常、异常分布或需要注意的特征?
输出要求:
- 使用自然、流畅的中文描述;
- 采用清晰的分条结构(1、2、3);
- 语言客观简洁,不使用“可能”“也许”“似乎”等模糊词;
- 重点突出数据结构、含义与潜在问题。
"""
if st.session_state.preference_select:
prompt += f"以下是用户的分析偏好设置:{st.session_state.preference_select}”。\n\n"
if st.session_state.additional_preference:
prompt += f"用户提供了以下建模目的与特殊需求:{st.session_state.additional_preference}”。\n\n"
desc = self.call(prompt)
return desc
def summary_html(self):
df = self.load_df()
df_head = df.head()
dtype_info = df.dtypes.astype(str)
prompt = f"""
你正在撰写一份数据分析报告的第一章——《数据概览与数据含义分析》。
请根据以下输入内容,整理关键信息并进行分析说明:
数据格式:
{dtype_info}
前五行数据:
{df_head}
数据解释聊天对话:
--- 开始聊天记录 ---
{self.memory}
--- 结束聊天记录 ---
额外要求:
1. 要用流畅的自然语言
2. 不要滥用形容词和副词,尽量用简单的动词和名词表达意思
3. 不用"可能""也许""似乎""微妙"等模糊表述
""".strip()
desc = self.call(prompt)
summary = {
"title": "数据导入",
"df": df_head,
"desc": desc,
}
return summary
def summary_word(self):
return self.summary_html()
def check_abstract(self):
if self.abstract is None:
df = self.load_df()
df_head = df.head()
dtype_info = df.dtypes.astype(str)
prompt = f"""
这是数据分析的数据导入阶段
数据格式:
{dtype_info}
前五行数据:
{df_head}
数据解释聊天对话:
--- 开始聊天记录 ---
{self.memory}
--- 结束聊天记录 ---
要求:
请基于上述数据与对话内容,生成一段简洁、准确的综合摘要。
摘要需完整呈现核心信息,便于后续自动判断该内容在报告撰写中是否需要被引用。
""".strip()
desc = self.call(prompt)
self.abstract = desc
return self.abstract
def check_full(self):
if self.full is None:
df = self.load_df()
df_head = df.head()
dtype_info = df.dtypes.astype(str)
self.full = (
f"【阶段说明】这是数据分析流程中的数据导入阶段。\n"
f"【数据格式】{dtype_info}\n"
f"【样本预览】\n{df_head}\n"
f"【分析对话记录】\n{self.memory}"
)
return self.full
|