前情提要
相信大家对RAG都不陌生,之前在本地构建了一个基于 RAG 的电力市场交易知识问答系统(MVP),能够上传 PDF/TXT 文档,并针对文档内容进行智能问答。主要用了以下技术栈:LangChain,Chroma , text2vec,Gradio,模型使用的是deepseek-v3.1。
项目结构如下
electramind-rag-project/
├── main.py # 主程序入口
├── requirements.txt # 项目依赖
├── docs/ # 知识库文档
├── vector_db/ # 向量数据库
└── project_guide.md # 开发指南
结果展示

后面发现对于开发过程对于非专业人员过于复杂,了解到各个大模型应用框架后,选择使用Dify搭建一个agent,下面将会简单介绍其过程。
Dify搭建工作流
我们的目的是搭建一个Agent,辅助电力市场交易人员了解电力市场政策,其中,Agent会调用电力市场API以便用户及时了解电价期货市场实时交易价格。
知识库构建
首先,构建知识库,这里我主要在网上下载了以下几个文档:
1、《电力现货市场基本规则(试行)》
2、全国统一电力市场发展规划蓝皮书-2024-12-16
3、新能源及储能参与电力市场交易白皮书(2024)
4、国内外电力现货市场的发展综述与展望
我们不需要手动编写代码进行文本分割和向量数据库生成,Dify平台会完成这些。
工作流编排

这里"开始"是用户的输入,"知识检索"中引入了我们前文构建的数据库,"条件检索"会对"知识检索"的输出进行判断,如果为空(或者相似度低于某个阈值),则说明数据库中没有相关信息,需要调用外部支持。我们在"HTTP请求"从 Energi Data Service API 获取电力市场的实时数据,然后"代码执行"模块会解析得到的数据包,并将解析后的数据结合用户的提问,一起输入至"LLM"模块,最终,LLM会将我们需要的回答输出。
代码执行模块代码
def main(http_body, http_status_code, http_headers=None, http_files=None):
"""
处理 HTTP 请求节点的输出,格式化能源数据。
输入: http_body (字符串), http_status_code (数字)
输出: 一个字典,包含格式化后的文本结果。
"""
try:
# 1. 检查HTTP请求是否成功
if http_status_code != 200:
return {"result": f"【数据服务暂不可用】API请求失败,状态码:{http_status_code}"}
# 2. 解析body中的JSON字符串
import json
data = json.loads(http_body)
records = data.get('records', [])
# 3. 检查数据是否为空
if not records:
return {"result": "【实时数据更新】当前未查询到相关电价数据。"}
# 4. 提取关键信息并格式化
formatted_text = "## 实时电力现货价格\n\n"
formatted_text += "以下为从 Energi Data Service 官方API获取的丹麦DK1地区最新电价信息:\n\n"
# 添加表头
formatted_text += "| 时间 (UTC) | 时间 (丹麦) | 价格区域 | 价格 (DKK) | 价格 (EUR) |\n"
formatted_text += "|------------|-------------|----------|------------|------------|\n"
for record in records:
hour_utc = record.get('HourUTC', 'N/A')[:16]
hour_dk = record.get('HourDK', 'N/A')[:16]
price_area = record.get('PriceArea', 'N/A')
price_dkk = record.get('SpotPriceDKK', 'N/A')
price_eur = record.get('SpotPriceEUR', 'N/A')
# 添加到Markdown表格行
formatted_text += f"| {hour_utc} | {hour_dk} | {price_area} | {price_dkk} | {price_eur} |\n"
# 添加数据摘要
latest_record = records[0]
latest_price_eur = latest_record.get('SpotPriceEUR', 'N/A')
latest_time = latest_record.get('HourDK', 'N/A')[:16]
formatted_text += f"\n**最新数据摘要**:{latest_time} 丹麦时间,DK1地区电价为 **{latest_price_eur} EUR/MWh**。"
formatted_text += f"\n*数据来源:Energi Data Service,更新于 {records[0]['HourUTC'][:16]} UTC*"
# 返回字典
return {"result": formatted_text}
except json.JSONDecodeError:
return {"result": "【数据格式错误】处理能源数据时发生解析错误。"}
except Exception as e:
return {"result": f"【数据处理错误】发生未知错误:{str(e)}"}
函数接受的参数来源于"HTTP请求"模块的输出,分别是 响应内容,响应状态码 ,响应头列表,文件列表。
LLM提示词
{你是一名资深的电力市场分析专家,专注于中国电力市场。你的职责是帮助用户解读电力交易政策、分析市场趋势和提供专业建议。
# 能力:
- 深入分析用户提供的政策文件、市场报告等资料。
- 用通俗易懂的语言解释复杂的专业术语和政策条款。
- 基于事实和数据提供分析,不编造不确定的信息。
# 要求:
- 回答要专业、准确、逻辑清晰。
- 如果问题超出你的知识范围或信息不足,请如实告知。
- 所有分析和结论必须基于你所学到的知识,不要胡编乱造。}
# 请根据以下提供的信息来回答问题:
变量1
<!-- 这里是知识库内容的位置 --># 这是电力市场API查询得到的信息:
变量2
<!-- 这里是API查询信息的位置 --># 问题:
变量3
<!-- 这里是用户问题的位置 -->
效果展示

补充:
目前还只提供了丹麦的实时数据,后续我会继续完善,可以获取整个欧洲地区的电力市场实时电价。此外,该应用属于一个MVP,还有许多地方需要完善,欢迎有兴趣的朋友一起讨论。

865

被折叠的 条评论
为什么被折叠?



