mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-10-08 03:10:24 +00:00
up readme
This commit is contained in:
parent
7832f20d41
commit
acb2262bb8
10 changed files with 0 additions and 1444 deletions
|
|
@ -1 +0,0 @@
|
|||
__version__ = "0.1.0"
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
金融分析师Agent使用示例
|
||||
"""
|
||||
|
||||
import sys
|
||||
from experiencemaker.utils.util_function import load_env_keys
|
||||
|
||||
load_env_keys("../../.env")
|
||||
# 添加项目根目录到Python路径
|
||||
# project_root = Path(__file__).parent.parent
|
||||
# sys.path.insert(0, str(project_root))
|
||||
sys.path.append(".")
|
||||
from financial_agent import FinancialAgent
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
# 加载环境变量
|
||||
load_env_keys()
|
||||
|
||||
# 初始实体列表
|
||||
init_entity_list = [
|
||||
"美元债务",
|
||||
"美债利率",
|
||||
"美元指数",
|
||||
"工业金属银、铜、铝",
|
||||
"黄金",
|
||||
"稳定币",
|
||||
"石油",
|
||||
"能源",
|
||||
"军工",
|
||||
"海运",
|
||||
]
|
||||
|
||||
# 创建金融分析师Agent
|
||||
agent = FinancialAgent(
|
||||
model_name="qwen-max-2025-01-25",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# 执行知识图谱构建
|
||||
output_file = "金融知识图谱.jsonl"
|
||||
stats = agent.execute(
|
||||
init_entity_list=init_entity_list,
|
||||
dump_file_path=output_file,
|
||||
max_iter=5, # 减少迭代次数用于演示
|
||||
search_strategy="mixed"
|
||||
)
|
||||
|
||||
print("\n" + "=" * 50)
|
||||
print("执行结果统计:")
|
||||
print(f"总实体数: {stats['total_entities']}")
|
||||
print(f"总关系数: {stats['total_relations']}")
|
||||
print(f"新增关系数: {stats['new_relations']}")
|
||||
print(f"迭代次数: {stats['iterations']}")
|
||||
print("=" * 50)
|
||||
|
||||
# 查询示例
|
||||
print("\n查询示例:")
|
||||
query_results = agent.query_knowledge_graph("美元")
|
||||
print(f"包含'美元'的关系数量: {len(query_results)}")
|
||||
|
||||
# 获取特定实体的关系
|
||||
print("\n美元指数的关系:")
|
||||
usd_relations = agent.get_entity_relations("美元指数")
|
||||
for i, relation in enumerate(usd_relations[:3]): # 只显示前3个
|
||||
print(f"{i + 1}. {relation}")
|
||||
|
||||
# 生成可视化图表
|
||||
print("\n生成可视化图表...")
|
||||
agent.visualize("financial_knowledge_graph.html")
|
||||
|
||||
print(f"\n知识图谱已保存到: {output_file}")
|
||||
print("可视化图表已保存到: financial_knowledge_graph.html")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -1,345 +0,0 @@
|
|||
"""
|
||||
金融分析师Agent主类
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import re
|
||||
from typing import List, Dict
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from experiencemaker.enumeration.role import Role
|
||||
from experiencemaker.model import OpenAICompatibleBaseLLM
|
||||
from experiencemaker.schema.trajectory import Message
|
||||
from experiencemaker.tool import CodeTool, DashscopeSearchTool
|
||||
from knowledge_graph import KnowledgeGraphBuilder
|
||||
from schema import FinancialRelation
|
||||
|
||||
|
||||
class FinancialAgent:
|
||||
"""金融分析师Agent"""
|
||||
|
||||
def __init__(self, model_name: str = "qwen-max-2025-01-25", verbose: bool = True):
|
||||
"""初始化金融分析师Agent"""
|
||||
self.llm = OpenAICompatibleBaseLLM(model_name=model_name)
|
||||
self.search_tool = DashscopeSearchTool()
|
||||
self.code_tool = CodeTool()
|
||||
self.tools = [self.search_tool, self.code_tool]
|
||||
self.verbose = verbose
|
||||
|
||||
# 知识图谱构建器
|
||||
self.knowledge_graph = KnowledgeGraphBuilder()
|
||||
|
||||
# 系统提示词
|
||||
self.system_prompt = """你是一个专业的金融分析师,专门负责分析金融市场中各种实体之间的逻辑关系。
|
||||
|
||||
你的任务:
|
||||
1. 通过搜索发现多个实体之间的逻辑关系
|
||||
2. 不断补充新的实体到实体列表中
|
||||
3. 将多跳的实体关系拆分成多个单跳的实体关系
|
||||
|
||||
实体关系格式:
|
||||
{
|
||||
"input_entities": ["实体1", "实体2"],
|
||||
"output_entities": ["实体3", "实体4"],
|
||||
"relation": "正向、负向、中性",
|
||||
"reasoning": "实体1和实体2是通过什么样的逻辑影响到实体3和实体4",
|
||||
"source": "来源",
|
||||
"confidence": "置信度(0-1)",
|
||||
"timestamp": "时间戳",
|
||||
}
|
||||
|
||||
请确保:
|
||||
- 关系描述准确、具体
|
||||
- 置信度合理评估
|
||||
- 来源信息完整
|
||||
- 时间戳格式:YYYY-MM-DD HH:MM:SS
|
||||
- 多跳关系要拆分成多个单跳关系
|
||||
"""
|
||||
|
||||
def _search_entity_relations(self, entity_list: List[str]) -> List[FinancialRelation]:
|
||||
"""搜索实体间的关系"""
|
||||
if self.verbose:
|
||||
logger.info(f"Searching relations for entities: {entity_list[:5]}...")
|
||||
|
||||
# 构建搜索查询
|
||||
entities_str = "、".join(entity_list[:5]) # 限制实体数量
|
||||
query = f"请分析以下金融实体之间的关系:{entities_str}。请详细说明它们之间的逻辑关系,包括正向、负向或中性的影响关系。"
|
||||
|
||||
# 使用搜索工具
|
||||
try:
|
||||
search_result = self.search_tool.execute(query=query)
|
||||
if self.verbose:
|
||||
logger.info(f"Search completed, result length: {len(str(search_result))}")
|
||||
except Exception as e:
|
||||
logger.error(f"Search failed: {e}")
|
||||
return []
|
||||
|
||||
# 使用LLM分析搜索结果并提取关系
|
||||
analysis_prompt = f"""
|
||||
基于以下搜索结果,请分析金融实体之间的关系:
|
||||
|
||||
搜索结果:
|
||||
{search_result[:10000]}
|
||||
|
||||
当前实体列表:
|
||||
{entity_list[:100]}
|
||||
|
||||
请提取出实体间的关系,格式如下(JSON格式):
|
||||
{{
|
||||
"relations": [
|
||||
{{
|
||||
"input_entities": ["实体1", "实体2"],
|
||||
"output_entities": ["实体3", "实体4"],
|
||||
"relation": "正向/负向/中性",
|
||||
"reasoning": "详细的分析逻辑",
|
||||
"source": "信息来源",
|
||||
"confidence": 0.8
|
||||
}}
|
||||
],
|
||||
"new_entities": ["新实体1", "新实体2"]
|
||||
}}
|
||||
|
||||
请确保:
|
||||
1. 关系描述准确具体
|
||||
2. 置信度在0-1之间
|
||||
3. 如果发现新的相关实体,请添加到new_entities中
|
||||
4. 只返回JSON格式,不要其他内容
|
||||
5. 多跳关系要拆分成多个单跳关系
|
||||
"""
|
||||
|
||||
messages = [
|
||||
Message(role=Role.SYSTEM, content=self.system_prompt),
|
||||
Message(role=Role.USER, content=analysis_prompt)
|
||||
]
|
||||
|
||||
try:
|
||||
response = self.llm.chat(messages, self.tools)
|
||||
|
||||
# 尝试解析JSON响应
|
||||
content = str(response.content)
|
||||
json_match = re.search(r'\{.*\}', content, re.DOTALL)
|
||||
if json_match:
|
||||
data = json.loads(json_match.group())
|
||||
|
||||
relations = []
|
||||
for rel_data in data.get("relations", []):
|
||||
try:
|
||||
relation = FinancialRelation(
|
||||
input_entities=rel_data["input_entities"],
|
||||
output_entities=rel_data["output_entities"],
|
||||
relation=rel_data["relation"],
|
||||
reasoning=rel_data["reasoning"],
|
||||
source=rel_data["source"],
|
||||
confidence=rel_data["confidence"],
|
||||
timestamp=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
)
|
||||
relations.append(relation)
|
||||
except Exception as e:
|
||||
logger.exception(f"Failed to create relation: {e}, data: {rel_data}")
|
||||
|
||||
# 添加新实体
|
||||
for new_entity in data.get("new_entities", []):
|
||||
self.knowledge_graph.entities.add(new_entity)
|
||||
|
||||
if self.verbose:
|
||||
logger.info(
|
||||
f"Extracted {len(relations)} relations and {len(data.get('new_entities', []))} new entities")
|
||||
|
||||
return relations
|
||||
except Exception as e:
|
||||
logger.error(f"Error parsing LLM response: {e}")
|
||||
if self.verbose:
|
||||
logger.error(f"Response content: {response.content if 'response' in locals() else 'No response'}")
|
||||
|
||||
return []
|
||||
|
||||
def _search_specific_entity_pairs(self, entity_pairs: List[List[str]]) -> List[FinancialRelation]:
|
||||
"""搜索特定实体对之间的关系"""
|
||||
all_relations = []
|
||||
|
||||
for pair in entity_pairs:
|
||||
if len(pair) < 2:
|
||||
continue
|
||||
|
||||
query = f"请分析{pair[0]}和{pair[1]}之间的金融关系,包括它们如何相互影响,以及对其他金融实体的影响。"
|
||||
|
||||
try:
|
||||
search_result = self.search_tool.execute(query=query)
|
||||
|
||||
analysis_prompt = f"""
|
||||
基于搜索结果,分析{pair[0]}和{pair[1]}之间的关系:
|
||||
|
||||
搜索结果:
|
||||
{search_result[:800] if isinstance(search_result, str) else str(search_result)[:800]}
|
||||
|
||||
请提取关系,格式如下(JSON格式):
|
||||
{{
|
||||
"relations": [
|
||||
{{
|
||||
"input_entities": ["{pair[0]}", "{pair[1]}"],
|
||||
"output_entities": ["影响实体1", "影响实体2"],
|
||||
"relation": "正向/负向/中性",
|
||||
"reasoning": "详细分析",
|
||||
"source": "来源",
|
||||
"confidence": 0.8
|
||||
}}
|
||||
]
|
||||
}}
|
||||
|
||||
只返回JSON格式。
|
||||
"""
|
||||
|
||||
messages = [
|
||||
Message(role=Role.SYSTEM, content=self.system_prompt),
|
||||
Message(role=Role.USER, content=analysis_prompt)
|
||||
]
|
||||
|
||||
response = self.llm.chat(messages, self.tools)
|
||||
|
||||
content = str(response.content)
|
||||
json_match = re.search(r'\{.*\}', content, re.DOTALL)
|
||||
if json_match:
|
||||
data = json.loads(json_match.group())
|
||||
|
||||
for rel_data in data.get("relations", []):
|
||||
try:
|
||||
relation = FinancialRelation(
|
||||
input_entities=rel_data["input_entities"],
|
||||
output_entities=rel_data["output_entities"],
|
||||
relation=rel_data["relation"],
|
||||
reasoning=rel_data["reasoning"],
|
||||
source=rel_data["source"],
|
||||
confidence=rel_data["confidence"],
|
||||
timestamp=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
)
|
||||
all_relations.append(relation)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to create relation: {e}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error searching pair {pair}: {e}")
|
||||
|
||||
return all_relations
|
||||
|
||||
def _generate_entity_pairs(self, entity_list: List[str], max_pairs: int = 10) -> List[List[str]]:
|
||||
"""生成实体对用于搜索"""
|
||||
pairs = []
|
||||
entities = list(entity_list)
|
||||
|
||||
# 生成所有可能的二元组合
|
||||
for i in range(len(entities)):
|
||||
for j in range(i + 1, len(entities)):
|
||||
pairs.append([entities[i], entities[j]])
|
||||
if len(pairs) >= max_pairs:
|
||||
break
|
||||
if len(pairs) >= max_pairs:
|
||||
break
|
||||
|
||||
return pairs
|
||||
|
||||
def execute(self, init_entity_list: List[str], dump_file_path: str, max_iter: int = 10,
|
||||
search_strategy: str = "mixed") -> Dict:
|
||||
"""
|
||||
执行金融知识图谱构建
|
||||
|
||||
Args:
|
||||
init_entity_list: 初始实体列表
|
||||
dump_file_path: 输出文件路径
|
||||
max_iter: 最大迭代次数
|
||||
search_strategy: 搜索策略 ("general", "pairs", "mixed")
|
||||
|
||||
Returns:
|
||||
执行结果统计
|
||||
"""
|
||||
logger.info(f"Starting financial knowledge graph construction with {len(init_entity_list)} initial entities")
|
||||
|
||||
# 1. 初始化实体列表
|
||||
self.knowledge_graph.entities = set(init_entity_list)
|
||||
|
||||
# 2. 加载历史数据
|
||||
self.knowledge_graph.load_from_jsonl(dump_file_path)
|
||||
|
||||
# 3. 迭代搜索
|
||||
iteration = 0
|
||||
total_new_relations = 0
|
||||
|
||||
while iteration < max_iter:
|
||||
iteration += 1
|
||||
logger.info(f"Iteration {iteration}/{max_iter}")
|
||||
|
||||
new_relations_count = 0
|
||||
|
||||
if search_strategy in ["general", "mixed"]:
|
||||
# 通用搜索
|
||||
entity_list = list(self.knowledge_graph.entities)
|
||||
relations = self._search_entity_relations(entity_list)
|
||||
|
||||
for relation in relations:
|
||||
if self.knowledge_graph.add_relation(relation):
|
||||
new_relations_count += 1
|
||||
|
||||
if search_strategy in ["pairs", "mixed"] and iteration % 2 == 0:
|
||||
# 实体对搜索
|
||||
entity_list = list(self.knowledge_graph.entities)
|
||||
entity_pairs = self._generate_entity_pairs(entity_list, max_pairs=5)
|
||||
relations = self._search_specific_entity_pairs(entity_pairs)
|
||||
|
||||
for relation in relations:
|
||||
if self.knowledge_graph.add_relation(relation):
|
||||
new_relations_count += 1
|
||||
|
||||
total_new_relations += new_relations_count
|
||||
logger.info(f"Added {new_relations_count} new relations in iteration {iteration}")
|
||||
|
||||
# 检查是否还有新的关系可以添加
|
||||
if new_relations_count == 0:
|
||||
logger.info("No new relations found, stopping iteration")
|
||||
break
|
||||
|
||||
# 保存中间结果
|
||||
self.knowledge_graph.export_to_jsonl(dump_file_path)
|
||||
|
||||
# 4. 保存最终结果
|
||||
self.knowledge_graph.export_to_jsonl(dump_file_path)
|
||||
|
||||
# 5. 生成统计信息
|
||||
stats = self.knowledge_graph.get_entity_statistics()
|
||||
stats["new_relations"] = total_new_relations
|
||||
stats["iterations"] = iteration
|
||||
|
||||
logger.info(f"Financial knowledge graph construction completed!")
|
||||
logger.info(f"Total entities: {stats['total_entities']}")
|
||||
logger.info(f"Total relations: {stats['total_relations']}")
|
||||
logger.info(f"New relations added: {total_new_relations}")
|
||||
|
||||
return stats
|
||||
|
||||
def query_knowledge_graph(self, query: str) -> List[FinancialRelation]:
|
||||
"""查询知识图谱"""
|
||||
# 简单的关键词匹配查询
|
||||
query_lower = query.lower()
|
||||
results = []
|
||||
|
||||
for relation in self.knowledge_graph.relations:
|
||||
# 检查输入实体、输出实体、推理过程是否包含查询关键词
|
||||
all_text = " ".join([
|
||||
" ".join(relation.input_entities),
|
||||
" ".join(relation.output_entities),
|
||||
relation.reasoning,
|
||||
relation.source
|
||||
]).lower()
|
||||
|
||||
if query_lower in all_text:
|
||||
results.append(relation)
|
||||
|
||||
return results
|
||||
|
||||
def get_entity_relations(self, entity: str) -> List[FinancialRelation]:
|
||||
"""获取特定实体的所有关系"""
|
||||
return self.knowledge_graph.find_related_entities(entity)
|
||||
|
||||
def visualize(self, output_path: str = "financial_knowledge_graph.html"):
|
||||
"""生成可视化图表"""
|
||||
self.knowledge_graph.visualize_graph(output_path)
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
"""
|
||||
金融知识图谱构建器
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from typing import List, Set, Dict
|
||||
|
||||
from schema import FinancialRelation
|
||||
|
||||
|
||||
class KnowledgeGraphBuilder:
|
||||
"""金融知识图谱构建器"""
|
||||
|
||||
def __init__(self):
|
||||
"""初始化知识图谱构建器"""
|
||||
self.entities: Set[str] = set()
|
||||
self.relations: List[FinancialRelation] = []
|
||||
self.relation_hashes: Set[str] = set() # 用于去重
|
||||
self.entity_aliases: Dict[str, Set[str]] = {} # 实体别名映射
|
||||
|
||||
def _generate_relation_hash(self, relation: FinancialRelation) -> str:
|
||||
"""生成关系的哈希值用于去重"""
|
||||
content = f"{sorted(relation.input_entities)}_{sorted(relation.output_entities)}_{relation.relation}_{relation.reasoning}"
|
||||
return hashlib.md5(content.encode()).hexdigest()
|
||||
|
||||
def add_relation(self, relation: FinancialRelation) -> bool:
|
||||
"""添加关系,如果重复则返回False"""
|
||||
relation_hash = self._generate_relation_hash(relation)
|
||||
if relation_hash in self.relation_hashes:
|
||||
return False
|
||||
|
||||
self.relation_hashes.add(relation_hash)
|
||||
self.relations.append(relation)
|
||||
|
||||
# 添加新实体到实体列表
|
||||
for entity in relation.input_entities + relation.output_entities:
|
||||
self.entities.add(entity)
|
||||
|
||||
return True
|
||||
|
||||
def add_entity_alias(self, main_entity: str, aliases: List[str]):
|
||||
"""添加实体别名"""
|
||||
if main_entity not in self.entity_aliases:
|
||||
self.entity_aliases[main_entity] = set()
|
||||
|
||||
for alias in aliases:
|
||||
self.entity_aliases[main_entity].add(alias)
|
||||
self.entities.add(alias)
|
||||
|
||||
def get_entity_aliases(self, entity: str) -> Set[str]:
|
||||
"""获取实体的所有别名"""
|
||||
for main_entity, aliases in self.entity_aliases.items():
|
||||
if entity in aliases or entity == main_entity:
|
||||
return aliases | {main_entity}
|
||||
return {entity}
|
||||
|
||||
def find_related_entities(self, entity: str, max_depth: int = 2) -> List[FinancialRelation]:
|
||||
"""查找与指定实体相关的所有关系"""
|
||||
related_relations = []
|
||||
visited_entities = set()
|
||||
entities_to_check = {entity}
|
||||
|
||||
for depth in range(max_depth):
|
||||
current_entities = entities_to_check.copy()
|
||||
entities_to_check.clear()
|
||||
|
||||
for relation in self.relations:
|
||||
# 检查关系是否涉及当前实体
|
||||
relation_entities = set(relation.input_entities + relation.output_entities)
|
||||
if relation_entities & current_entities:
|
||||
related_relations.append(relation)
|
||||
# 添加新的实体到下一轮检查
|
||||
entities_to_check.update(relation_entities - visited_entities)
|
||||
|
||||
visited_entities.update(current_entities)
|
||||
|
||||
if not entities_to_check:
|
||||
break
|
||||
|
||||
return related_relations
|
||||
|
||||
def get_entity_statistics(self) -> Dict:
|
||||
"""获取实体统计信息"""
|
||||
return {
|
||||
"total_entities": len(self.entities),
|
||||
"total_relations": len(self.relations),
|
||||
"unique_relations": len(self.relation_hashes),
|
||||
"entity_aliases": len(self.entity_aliases)
|
||||
}
|
||||
|
||||
def export_to_jsonl(self, file_path: str):
|
||||
"""导出到JSONL文件"""
|
||||
# os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
for relation in self.relations:
|
||||
f.write(json.dumps(relation.to_dict(), ensure_ascii=False) + '\n')
|
||||
|
||||
def load_from_jsonl(self, file_path: str):
|
||||
"""从JSONL文件加载"""
|
||||
if not os.path.exists(file_path):
|
||||
return
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line:
|
||||
data = json.loads(line)
|
||||
relation = FinancialRelation.from_dict(data)
|
||||
self.add_relation(relation)
|
||||
|
||||
def export_to_networkx_format(self) -> Dict:
|
||||
"""导出为NetworkX可用的格式"""
|
||||
nodes = []
|
||||
edges = []
|
||||
|
||||
# 添加节点
|
||||
for entity in self.entities:
|
||||
nodes.append({
|
||||
"id": entity,
|
||||
"label": entity,
|
||||
"type": "entity"
|
||||
})
|
||||
|
||||
# 添加边
|
||||
for i, relation in enumerate(self.relations):
|
||||
for input_entity in relation.input_entities:
|
||||
for output_entity in relation.output_entities:
|
||||
edges.append({
|
||||
"source": input_entity,
|
||||
"target": output_entity,
|
||||
"relation": relation.relation,
|
||||
"reasoning": relation.reasoning,
|
||||
"confidence": relation.confidence,
|
||||
"source_info": relation.source,
|
||||
"timestamp": relation.timestamp
|
||||
})
|
||||
|
||||
return {
|
||||
"nodes": nodes,
|
||||
"edges": edges,
|
||||
"metadata": self.get_entity_statistics()
|
||||
}
|
||||
|
||||
def visualize_graph(self, output_path: str = "financial_knowledge_graph.html"):
|
||||
"""生成可视化图表(HTML格式)"""
|
||||
try:
|
||||
import plotly.graph_objects as go
|
||||
import networkx as nx
|
||||
|
||||
# 创建NetworkX图
|
||||
G = nx.DiGraph()
|
||||
|
||||
# 添加节点
|
||||
for entity in self.entities:
|
||||
G.add_node(entity)
|
||||
|
||||
# 添加边
|
||||
for relation in self.relations:
|
||||
for input_entity in relation.input_entities:
|
||||
for output_entity in relation.output_entities:
|
||||
G.add_edge(
|
||||
input_entity,
|
||||
output_entity,
|
||||
relation=relation.relation,
|
||||
confidence=relation.confidence
|
||||
)
|
||||
|
||||
# 使用spring布局
|
||||
pos = nx.spring_layout(G, k=1, iterations=50)
|
||||
|
||||
# 创建边轨迹
|
||||
edge_x = []
|
||||
edge_y = []
|
||||
edge_text = []
|
||||
|
||||
for edge in G.edges(data=True):
|
||||
x0, y0 = pos[edge[0]]
|
||||
x1, y1 = pos[edge[1]]
|
||||
edge_x.extend([x0, x1, None])
|
||||
edge_y.extend([y0, y1, None])
|
||||
edge_text.append(f"{edge[0]} → {edge[1]} ({edge[2]['relation']})")
|
||||
|
||||
edge_trace = go.Scatter(
|
||||
x=edge_x, y=edge_y,
|
||||
line=dict(width=0.5, color='#888'),
|
||||
hoverinfo='text',
|
||||
text=edge_text,
|
||||
mode='lines')
|
||||
|
||||
# 创建节点轨迹
|
||||
node_x = []
|
||||
node_y = []
|
||||
node_text = []
|
||||
|
||||
for node in G.nodes():
|
||||
x, y = pos[node]
|
||||
node_x.append(x)
|
||||
node_y.append(y)
|
||||
node_text.append(node)
|
||||
|
||||
node_trace = go.Scatter(
|
||||
x=node_x, y=node_y,
|
||||
mode='markers+text',
|
||||
hoverinfo='text',
|
||||
text=node_text,
|
||||
textposition="top center",
|
||||
marker=dict(
|
||||
showscale=True,
|
||||
colorscale='YlGnBu',
|
||||
size=10,
|
||||
color=[],
|
||||
line_width=2))
|
||||
|
||||
# 设置节点颜色
|
||||
node_adjacency_list = []
|
||||
for node in G.nodes():
|
||||
node_adjacency_list.append(len(list(G.neighbors(node))))
|
||||
node_trace.marker.color = node_adjacency_list
|
||||
|
||||
# 创建图形
|
||||
fig = go.Figure(data=[edge_trace, node_trace],
|
||||
layout=go.Layout(
|
||||
title='金融知识图谱',
|
||||
showlegend=False,
|
||||
hovermode='closest',
|
||||
margin=dict(b=20, l=5, r=5, t=40),
|
||||
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
|
||||
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False))
|
||||
)
|
||||
|
||||
fig.write_html(output_path)
|
||||
print(f"知识图谱已保存到: {output_path}")
|
||||
|
||||
except ImportError:
|
||||
print("需要安装 plotly 和 networkx 来生成可视化图表")
|
||||
print("运行: pip install plotly networkx")
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
"""
|
||||
金融实体关系的schema定义
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import List
|
||||
|
||||
|
||||
@dataclass
|
||||
class FinancialRelation:
|
||||
"""金融实体关系的数据结构"""
|
||||
input_entities: List[str]
|
||||
output_entities: List[str]
|
||||
relation: str # "正向", "负向", "中性"
|
||||
reasoning: str
|
||||
source: str
|
||||
confidence: float
|
||||
timestamp: str
|
||||
|
||||
def __post_init__(self):
|
||||
"""初始化后的验证"""
|
||||
if not isinstance(self.confidence, (int, float)) or not 0 <= self.confidence <= 1:
|
||||
raise ValueError("confidence must be a float between 0 and 1")
|
||||
|
||||
if self.relation not in ["正向", "负向", "中性"]:
|
||||
raise ValueError("relation must be one of: 正向, 负向, 中性")
|
||||
|
||||
def to_dict(self):
|
||||
"""转换为字典格式"""
|
||||
return {
|
||||
"input_entities": self.input_entities,
|
||||
"output_entities": self.output_entities,
|
||||
"relation": self.relation,
|
||||
"reasoning": self.reasoning,
|
||||
"source": self.source,
|
||||
"confidence": self.confidence,
|
||||
"timestamp": self.timestamp
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict):
|
||||
"""从字典创建实例"""
|
||||
return cls(**data)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.input_entities} -> {self.output_entities} ({self.relation}, 置信度: {self.confidence})"
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
# 金融分析师Agent
|
||||
|
||||
一个智能的金融分析师Agent,能够通过搜索和分析构建金融知识图谱,发现金融实体之间的逻辑关系。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- 🔍 **智能搜索**: 使用大模型和搜索工具发现金融实体关系
|
||||
- 🧠 **知识图谱构建**: 自动构建和更新金融知识图谱
|
||||
- 🔗 **关系分析**: 分析正向、负向、中性关系
|
||||
- 📊 **可视化**: 生成交互式知识图谱可视化
|
||||
- 🔄 **迭代优化**: 支持多轮迭代,不断丰富知识图谱
|
||||
- 📝 **数据导出**: 支持JSONL格式导出
|
||||
|
||||
## 安装
|
||||
|
||||
1. 克隆项目并安装依赖:
|
||||
```bash
|
||||
pip install -r financial_agent/requirements.txt
|
||||
```
|
||||
|
||||
2. 设置环境变量:
|
||||
```bash
|
||||
export OPENAI_API_KEY="your_openai_api_key"
|
||||
export OPENAI_BASE_URL="your_openai_base_url"
|
||||
export DASHSCOPE_API_KEY="your_dashscope_api_key"
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 基本使用
|
||||
|
||||
```python
|
||||
from financial_agent import FinancialAgent
|
||||
|
||||
# 创建Agent
|
||||
agent = FinancialAgent(model_name="qwen-max-2025-01-25")
|
||||
|
||||
# 初始实体列表
|
||||
init_entities = ["美元债务", "美债利率", "美元指数", "黄金", "石油"]
|
||||
|
||||
# 执行知识图谱构建
|
||||
stats = agent.execute(
|
||||
init_entity_list=init_entities,
|
||||
dump_file_path="金融知识图谱.jsonl",
|
||||
max_iter=10,
|
||||
search_strategy="mixed"
|
||||
)
|
||||
|
||||
print(f"构建完成!总实体数: {stats['total_entities']}, 总关系数: {stats['total_relations']}")
|
||||
```
|
||||
|
||||
### 运行示例
|
||||
|
||||
```bash
|
||||
python financial_agent/example.py
|
||||
```
|
||||
|
||||
## 核心组件
|
||||
|
||||
### FinancialAgent
|
||||
|
||||
主要的金融分析师Agent类,负责:
|
||||
- 搜索和分析金融实体关系
|
||||
- 构建和更新知识图谱
|
||||
- 提供查询接口
|
||||
|
||||
### FinancialRelation
|
||||
|
||||
金融实体关系的数据结构:
|
||||
```python
|
||||
{
|
||||
"input_entities": ["实体1", "实体2"],
|
||||
"output_entities": ["实体3", "实体4"],
|
||||
"relation": "正向、负向、中性",
|
||||
"reasoning": "关系推理过程",
|
||||
"source": "信息来源",
|
||||
"confidence": "置信度(0-1)",
|
||||
"timestamp": "时间戳"
|
||||
}
|
||||
```
|
||||
|
||||
### KnowledgeGraphBuilder
|
||||
|
||||
知识图谱构建器,提供:
|
||||
- 关系去重和验证
|
||||
- 实体别名管理
|
||||
- 图谱查询和统计
|
||||
- 可视化生成
|
||||
|
||||
## 配置选项
|
||||
|
||||
### 搜索策略
|
||||
|
||||
- `"general"`: 通用搜索,分析多个实体间的关系
|
||||
- `"pairs"`: 实体对搜索,专注于特定实体对
|
||||
- `"mixed"`: 混合策略,结合两种方法
|
||||
|
||||
### 模型配置
|
||||
|
||||
支持多种大模型:
|
||||
- `qwen-max-2025-01-25`
|
||||
- `qwen3-32b`
|
||||
- 其他OpenAI兼容模型
|
||||
|
||||
## 输出格式
|
||||
|
||||
### JSONL文件格式
|
||||
|
||||
每行一个JSON对象,包含完整的金融关系信息:
|
||||
|
||||
```jsonl
|
||||
{"input_entities": ["美债利率", "美元债务"], "output_entities": ["美元指数"], "relation": "负向", "reasoning": "美债利率上升和美元债务增加会导致美元走弱", "source": "金融分析报告", "confidence": 0.85, "timestamp": "2024-01-15 10:30:00"}
|
||||
{"input_entities": ["石油价格", "美元指数"], "output_entities": ["通胀预期"], "relation": "正向", "reasoning": "石油价格上涨和美元走弱会推高通胀预期", "source": "经济分析", "confidence": 0.78, "timestamp": "2024-01-15 10:31:00"}
|
||||
```
|
||||
|
||||
### 可视化输出
|
||||
|
||||
生成交互式HTML图表,支持:
|
||||
- 节点拖拽
|
||||
- 关系查看
|
||||
- 缩放和平移
|
||||
- 悬停信息显示
|
||||
|
||||
## API参考
|
||||
|
||||
### FinancialAgent.execute()
|
||||
|
||||
执行知识图谱构建:
|
||||
|
||||
```python
|
||||
def execute(self, init_entity_list: List[str], dump_file_path: str,
|
||||
max_iter: int = 10, search_strategy: str = "mixed") -> Dict
|
||||
```
|
||||
|
||||
### FinancialAgent.query_knowledge_graph()
|
||||
|
||||
查询知识图谱:
|
||||
|
||||
```python
|
||||
def query_knowledge_graph(self, query: str) -> List[FinancialRelation]
|
||||
```
|
||||
|
||||
### FinancialAgent.get_entity_relations()
|
||||
|
||||
获取特定实体的关系:
|
||||
|
||||
```python
|
||||
def get_entity_relations(self, entity: str) -> List[FinancialRelation]
|
||||
```
|
||||
|
||||
## 使用场景
|
||||
|
||||
1. **金融研究**: 自动发现金融市场中的实体关系
|
||||
2. **投资分析**: 分析投资标的之间的相互影响
|
||||
3. **风险管理**: 识别风险传导路径
|
||||
4. **政策分析**: 分析政策对市场的影响机制
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **API限制**: 注意搜索API的调用频率限制
|
||||
2. **数据质量**: 建议对生成的关系进行人工验证
|
||||
3. **成本控制**: 大模型调用会产生费用,注意控制迭代次数
|
||||
4. **环境配置**: 确保正确配置API密钥和基础URL
|
||||
|
||||
## 贡献
|
||||
|
||||
欢迎提交Issue和Pull Request来改进项目!
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT License
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
|
||||
entity_list = [
|
||||
"美元债务",
|
||||
"美债利率",
|
||||
"美元指数",
|
||||
"工业金属银、铜、铝",
|
||||
"黄金",
|
||||
"稳定币",
|
||||
"石油",
|
||||
"能源",
|
||||
"军工",
|
||||
"海运",
|
||||
]
|
||||
|
||||
|
||||
|
||||
"""
|
||||
现在初始状态你有以下的实体列表:
|
||||
|
||||
美元债务
|
||||
美债利率
|
||||
美元指数
|
||||
工业金属银、铜、铝
|
||||
黄金
|
||||
稳定币
|
||||
石油
|
||||
能源
|
||||
军工
|
||||
海运
|
||||
|
||||
|
||||
你有一个大模型调用的Client
|
||||
from experiencemaker.model import OpenAICompatibleBaseLLM
|
||||
|
||||
你有两个工具:
|
||||
1. 代码执行工具
|
||||
from experiencemaker.tool import CodeTool
|
||||
2. web search工具
|
||||
from experiencemaker.tool import DashscopeSearchTool
|
||||
|
||||
请你根据以上内容,设计一个金融分析师的Agent,并给出Agent的代码。
|
||||
Agent的任务:
|
||||
1. 通过不断的搜索,发现多个实体之间的逻辑关系,例如“美债利率高”、“美元债务高”会让美元变弱,从而导致“美元指数”变弱。
|
||||
2. 同时通过不断的搜索,不断的补充新的实体到**实体列表**。
|
||||
3. 多跳的实体关系,可以拆成多个单跳的实体关系。
|
||||
|
||||
实体关系的schema如下:
|
||||
{
|
||||
"input_entities": ["实体1", "实体2"],
|
||||
"output_entities": ["实体3", "实体4"],
|
||||
"relation": "正向、负向、中性",
|
||||
"reasoning": "实体1和实体2是通过什么样的逻辑影响到实体3和实体4",
|
||||
"source": "来源",
|
||||
"confidence": "置信度",
|
||||
"timestamp": "时间戳",
|
||||
}
|
||||
|
||||
最后这些schema的list会变成一个jsonl文件,文件名是:
|
||||
金融知识图谱.jsonl
|
||||
|
||||
```python
|
||||
class FinAgent(object):
|
||||
|
||||
def execute(self, init_entity_list: list[str], dump_file_path: str, max_iter: int = 100):
|
||||
# init_entity_list 是初始的实体列表
|
||||
# dump_file_path 是最终的jsonl文件路径
|
||||
# max_iter 是最大迭代次数
|
||||
|
||||
# 1. 初始化实体列表
|
||||
# 2. 读取dump_file_path中历史的金融知识图谱(如果有),加载到内容
|
||||
# 2. 迭代搜索,不断更新已有的知识图谱,不断补充新的知识图谱,不断增加新的实体(和已有的语义去重)
|
||||
# 3. 迭代到max_iter次,或者没有新的知识图谱可以补充,则停止迭代, 保存到dump_file_path中
|
||||
pass
|
||||
```
|
||||
|
||||
帮忙把整个project写一下
|
||||
"""
|
||||
|
|
@ -1,294 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
金融分析师Agent测试脚本
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import datetime
|
||||
from typing import List, Dict, Set
|
||||
from dataclasses import dataclass
|
||||
import hashlib
|
||||
import re
|
||||
|
||||
from experiencemaker.model import OpenAICompatibleBaseLLM
|
||||
from experiencemaker.tool import CodeTool, DashscopeSearchTool
|
||||
from experiencemaker.schema.trajectory import Message
|
||||
from experiencemaker.enumeration.role import Role
|
||||
|
||||
|
||||
@dataclass
|
||||
class FinancialRelation:
|
||||
"""金融实体关系的数据结构"""
|
||||
input_entities: List[str]
|
||||
output_entities: List[str]
|
||||
relation: str # "正向", "负向", "中性"
|
||||
reasoning: str
|
||||
source: str
|
||||
confidence: float
|
||||
timestamp: str
|
||||
|
||||
|
||||
class FinancialAgent:
|
||||
"""金融分析师Agent"""
|
||||
|
||||
def __init__(self, model_name: str = "qwen-max-2025-01-25"):
|
||||
"""初始化金融分析师Agent"""
|
||||
self.llm = OpenAICompatibleBaseLLM(model_name=model_name)
|
||||
self.search_tool = DashscopeSearchTool()
|
||||
self.code_tool = CodeTool()
|
||||
self.tools = [self.search_tool, self.code_tool]
|
||||
|
||||
# 存储实体和关系
|
||||
self.entities: Set[str] = set()
|
||||
self.relations: List[FinancialRelation] = []
|
||||
self.relation_hashes: Set[str] = set() # 用于去重
|
||||
|
||||
# 系统提示词
|
||||
self.system_prompt = """你是一个专业的金融分析师,专门负责分析金融市场中各种实体之间的逻辑关系。
|
||||
|
||||
你的任务:
|
||||
1. 通过搜索发现多个实体之间的逻辑关系
|
||||
2. 不断补充新的实体到实体列表中
|
||||
3. 将多跳的实体关系拆分成多个单跳的实体关系
|
||||
|
||||
实体关系格式:
|
||||
{
|
||||
"input_entities": ["实体1", "实体2"],
|
||||
"output_entities": ["实体3", "实体4"],
|
||||
"relation": "正向、负向、中性",
|
||||
"reasoning": "实体1和实体2是通过什么样的逻辑影响到实体3和实体4",
|
||||
"source": "来源",
|
||||
"confidence": "置信度(0-1)",
|
||||
"timestamp": "时间戳",
|
||||
}
|
||||
|
||||
请确保:
|
||||
- 关系描述准确、具体
|
||||
- 置信度合理评估
|
||||
- 来源信息完整
|
||||
- 时间戳格式:YYYY-MM-DD HH:MM:SS
|
||||
"""
|
||||
|
||||
def _generate_relation_hash(self, relation: FinancialRelation) -> str:
|
||||
"""生成关系的哈希值用于去重"""
|
||||
content = f"{sorted(relation.input_entities)}_{sorted(relation.output_entities)}_{relation.relation}_{relation.reasoning}"
|
||||
return hashlib.md5(content.encode()).hexdigest()
|
||||
|
||||
def _add_relation(self, relation: FinancialRelation) -> bool:
|
||||
"""添加关系,如果重复则返回False"""
|
||||
relation_hash = self._generate_relation_hash(relation)
|
||||
if relation_hash in self.relation_hashes:
|
||||
return False
|
||||
|
||||
self.relation_hashes.add(relation_hash)
|
||||
self.relations.append(relation)
|
||||
|
||||
# 添加新实体到实体列表
|
||||
for entity in relation.input_entities + relation.output_entities:
|
||||
self.entities.add(entity)
|
||||
|
||||
return True
|
||||
|
||||
def _load_existing_relations(self, file_path: str):
|
||||
"""加载已存在的关系数据"""
|
||||
if not os.path.exists(file_path):
|
||||
return
|
||||
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line:
|
||||
data = json.loads(line)
|
||||
relation = FinancialRelation(**data)
|
||||
self._add_relation(relation)
|
||||
print(f"Loaded {len(self.relations)} existing relations from {file_path}")
|
||||
except Exception as e:
|
||||
print(f"Error loading existing relations: {e}")
|
||||
|
||||
def _save_relations(self, file_path: str):
|
||||
"""保存关系到文件"""
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
for relation in self.relations:
|
||||
f.write(json.dumps(relation.__dict__, ensure_ascii=False) + '\n')
|
||||
print(f"Saved {len(self.relations)} relations to {file_path}")
|
||||
|
||||
def _search_entity_relations(self, entity_list: List[str]) -> List[FinancialRelation]:
|
||||
"""搜索实体间的关系"""
|
||||
# 构建搜索查询
|
||||
entities_str = "、".join(entity_list[:5]) # 限制实体数量
|
||||
query = f"请分析以下金融实体之间的关系:{entities_str}。请详细说明它们之间的逻辑关系,包括正向、负向或中性的影响关系。"
|
||||
|
||||
# 使用搜索工具
|
||||
search_result = self.search_tool.execute(query=query)
|
||||
|
||||
# 使用LLM分析搜索结果并提取关系
|
||||
analysis_prompt = f"""
|
||||
基于以下搜索结果,请分析金融实体之间的关系:
|
||||
|
||||
搜索结果:
|
||||
{search_result[:1000] if isinstance(search_result, str) else str(search_result)[:1000]} # 限制长度
|
||||
|
||||
当前实体列表:
|
||||
{entity_list[:10]} # 限制显示数量
|
||||
|
||||
请提取出实体间的关系,格式如下(JSON格式):
|
||||
{{
|
||||
"relations": [
|
||||
{{
|
||||
"input_entities": ["实体1", "实体2"],
|
||||
"output_entities": ["实体3", "实体4"],
|
||||
"relation": "正向/负向/中性",
|
||||
"reasoning": "详细的分析逻辑",
|
||||
"source": "信息来源",
|
||||
"confidence": 0.8
|
||||
}}
|
||||
],
|
||||
"new_entities": ["新实体1", "新实体2"]
|
||||
}}
|
||||
|
||||
请确保:
|
||||
1. 关系描述准确具体
|
||||
2. 置信度在0-1之间
|
||||
3. 如果发现新的相关实体,请添加到new_entities中
|
||||
4. 只返回JSON格式,不要其他内容
|
||||
"""
|
||||
|
||||
messages = [
|
||||
Message(role=Role.SYSTEM, content=self.system_prompt),
|
||||
Message(role=Role.USER, content=analysis_prompt)
|
||||
]
|
||||
|
||||
response = self.llm._chat(messages, self.tools)
|
||||
|
||||
try:
|
||||
# 尝试解析JSON响应
|
||||
content = str(response.content)
|
||||
json_match = re.search(r'\{.*\}', content, re.DOTALL)
|
||||
if json_match:
|
||||
data = json.loads(json_match.group())
|
||||
|
||||
relations = []
|
||||
for rel_data in data.get("relations", []):
|
||||
relation = FinancialRelation(
|
||||
input_entities=rel_data["input_entities"],
|
||||
output_entities=rel_data["output_entities"],
|
||||
relation=rel_data["relation"],
|
||||
reasoning=rel_data["reasoning"],
|
||||
source=rel_data["source"],
|
||||
confidence=rel_data["confidence"],
|
||||
timestamp=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
)
|
||||
relations.append(relation)
|
||||
|
||||
# 添加新实体
|
||||
for new_entity in data.get("new_entities", []):
|
||||
self.entities.add(new_entity)
|
||||
|
||||
return relations
|
||||
except Exception as e:
|
||||
print(f"Error parsing LLM response: {e}")
|
||||
print(f"Response content: {response.content}")
|
||||
|
||||
return []
|
||||
|
||||
def execute(self, init_entity_list: List[str], dump_file_path: str, max_iter: int = 5):
|
||||
"""
|
||||
执行金融知识图谱构建
|
||||
|
||||
Args:
|
||||
init_entity_list: 初始实体列表
|
||||
dump_file_path: 输出文件路径
|
||||
max_iter: 最大迭代次数
|
||||
"""
|
||||
print(f"Starting financial knowledge graph construction with {len(init_entity_list)} initial entities")
|
||||
|
||||
# 1. 初始化实体列表
|
||||
self.entities = set(init_entity_list)
|
||||
|
||||
# 2. 加载历史数据
|
||||
self._load_existing_relations(dump_file_path)
|
||||
|
||||
# 3. 迭代搜索
|
||||
iteration = 0
|
||||
new_relations_count = 0
|
||||
|
||||
while iteration < max_iter:
|
||||
iteration += 1
|
||||
print(f"Iteration {iteration}/{max_iter}")
|
||||
|
||||
# 搜索实体间关系
|
||||
entity_list = list(self.entities)
|
||||
relations = self._search_entity_relations(entity_list)
|
||||
|
||||
# 添加新关系
|
||||
added_count = 0
|
||||
for relation in relations:
|
||||
if self._add_relation(relation):
|
||||
added_count += 1
|
||||
|
||||
new_relations_count += added_count
|
||||
print(f"Added {added_count} new relations in iteration {iteration}")
|
||||
|
||||
# 检查是否还有新的关系可以添加
|
||||
if added_count == 0:
|
||||
print("No new relations found, stopping iteration")
|
||||
break
|
||||
|
||||
# 保存中间结果
|
||||
if iteration % 2 == 0:
|
||||
self._save_relations(dump_file_path)
|
||||
|
||||
# 4. 保存最终结果
|
||||
self._save_relations(dump_file_path)
|
||||
|
||||
print(f"Financial knowledge graph construction completed!")
|
||||
print(f"Total entities: {len(self.entities)}")
|
||||
print(f"Total relations: {len(self.relations)}")
|
||||
print(f"New relations added: {new_relations_count}")
|
||||
|
||||
return {
|
||||
"entities": list(self.entities),
|
||||
"relations": [rel.__dict__ for rel in self.relations],
|
||||
"total_entities": len(self.entities),
|
||||
"total_relations": len(self.relations),
|
||||
"new_relations": new_relations_count
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
from experiencemaker.utils.util_function import load_env_keys
|
||||
|
||||
# 加载环境变量
|
||||
load_env_keys()
|
||||
|
||||
# 初始实体列表
|
||||
init_entities = [
|
||||
"美元债务",
|
||||
"美债利率",
|
||||
"美元指数",
|
||||
"黄金",
|
||||
"石油",
|
||||
]
|
||||
|
||||
# 创建Agent并执行
|
||||
agent = FinancialAgent()
|
||||
result = agent.execute(
|
||||
init_entity_list=init_entities,
|
||||
dump_file_path="test/金融知识图谱.jsonl",
|
||||
max_iter=3 # 减少迭代次数用于测试
|
||||
)
|
||||
|
||||
print("=" * 50)
|
||||
print("构建完成!")
|
||||
print(f"总实体数: {result['total_entities']}")
|
||||
print(f"总关系数: {result['total_relations']}")
|
||||
print(f"新增关系数: {result['new_relations']}")
|
||||
print("=" * 50)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -1,191 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
简化的金融Agent测试脚本
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
# 添加项目根目录到Python路径
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
# 模拟环境变量(如果没有设置的话)
|
||||
if not os.getenv("OPENAI_API_KEY"):
|
||||
os.environ["OPENAI_API_KEY"] = "test_key"
|
||||
if not os.getenv("OPENAI_BASE_URL"):
|
||||
os.environ["OPENAI_BASE_URL"] = "http://localhost:8000/v1"
|
||||
if not os.getenv("DASHSCOPE_API_KEY"):
|
||||
os.environ["DASHSCOPE_API_KEY"] = "test_key"
|
||||
|
||||
from financial_agent.schema import FinancialRelation
|
||||
from financial_agent.knowledge_graph import KnowledgeGraphBuilder
|
||||
|
||||
|
||||
def test_schema():
|
||||
"""测试FinancialRelation schema"""
|
||||
print("测试FinancialRelation schema...")
|
||||
|
||||
# 创建测试关系
|
||||
relation = FinancialRelation(
|
||||
input_entities=["美债利率", "美元债务"],
|
||||
output_entities=["美元指数"],
|
||||
relation="负向",
|
||||
reasoning="美债利率上升和美元债务增加会导致美元走弱",
|
||||
source="金融分析报告",
|
||||
confidence=0.85,
|
||||
timestamp="2024-01-15 10:30:00"
|
||||
)
|
||||
|
||||
print(f"创建的关系: {relation}")
|
||||
print(f"转换为字典: {relation.to_dict()}")
|
||||
|
||||
# 测试验证
|
||||
try:
|
||||
invalid_relation = FinancialRelation(
|
||||
input_entities=["实体1"],
|
||||
output_entities=["实体2"],
|
||||
relation="无效关系", # 应该报错
|
||||
reasoning="测试",
|
||||
source="测试",
|
||||
confidence=0.5,
|
||||
timestamp="2024-01-15 10:30:00"
|
||||
)
|
||||
except ValueError as e:
|
||||
print(f"验证错误(预期): {e}")
|
||||
|
||||
print("Schema测试通过!\n")
|
||||
|
||||
|
||||
def test_knowledge_graph():
|
||||
"""测试KnowledgeGraphBuilder"""
|
||||
print("测试KnowledgeGraphBuilder...")
|
||||
|
||||
# 创建知识图谱
|
||||
kg = KnowledgeGraphBuilder()
|
||||
|
||||
# 添加关系
|
||||
relation1 = FinancialRelation(
|
||||
input_entities=["美债利率", "美元债务"],
|
||||
output_entities=["美元指数"],
|
||||
relation="负向",
|
||||
reasoning="美债利率上升和美元债务增加会导致美元走弱",
|
||||
source="金融分析报告",
|
||||
confidence=0.85,
|
||||
timestamp="2024-01-15 10:30:00"
|
||||
)
|
||||
|
||||
relation2 = FinancialRelation(
|
||||
input_entities=["石油价格", "美元指数"],
|
||||
output_entities=["通胀预期"],
|
||||
relation="正向",
|
||||
reasoning="石油价格上涨和美元走弱会推高通胀预期",
|
||||
source="经济分析",
|
||||
confidence=0.78,
|
||||
timestamp="2024-01-15 10:31:00"
|
||||
)
|
||||
|
||||
# 添加关系
|
||||
kg.add_relation(relation1)
|
||||
kg.add_relation(relation2)
|
||||
|
||||
# 添加实体别名
|
||||
kg.add_entity_alias("美元指数", ["USD Index", "DXY"])
|
||||
|
||||
# 测试统计
|
||||
stats = kg.get_entity_statistics()
|
||||
print(f"知识图谱统计: {stats}")
|
||||
|
||||
# 测试查询
|
||||
usd_relations = kg.find_related_entities("美元指数")
|
||||
print(f"美元指数相关关系数量: {len(usd_relations)}")
|
||||
|
||||
# 测试导出
|
||||
test_file = "test_knowledge_graph.jsonl"
|
||||
kg.export_to_jsonl(test_file)
|
||||
print(f"知识图谱已导出到: {test_file}")
|
||||
|
||||
# 测试加载
|
||||
new_kg = KnowledgeGraphBuilder()
|
||||
new_kg.load_from_jsonl(test_file)
|
||||
print(f"加载后的实体数量: {len(new_kg.entities)}")
|
||||
|
||||
# 清理测试文件
|
||||
if os.path.exists(test_file):
|
||||
os.remove(test_file)
|
||||
|
||||
print("KnowledgeGraphBuilder测试通过!\n")
|
||||
|
||||
|
||||
def test_mock_agent():
|
||||
"""测试模拟的Agent(不调用真实API)"""
|
||||
print("测试模拟Agent...")
|
||||
|
||||
# 创建模拟的搜索结果
|
||||
mock_search_result = """
|
||||
根据最新金融分析,美债利率上升和美元债务增加会对美元指数产生负面影响。
|
||||
当美债利率上升时,投资者会要求更高的收益率,这可能导致美元走弱。
|
||||
同时,美元债务的增加也会增加市场对美元贬值的担忧。
|
||||
"""
|
||||
|
||||
# 模拟LLM响应
|
||||
mock_llm_response = {
|
||||
"relations": [
|
||||
{
|
||||
"input_entities": ["美债利率", "美元债务"],
|
||||
"output_entities": ["美元指数"],
|
||||
"relation": "负向",
|
||||
"reasoning": "美债利率上升和美元债务增加会导致美元走弱",
|
||||
"source": "金融分析报告",
|
||||
"confidence": 0.85
|
||||
}
|
||||
],
|
||||
"new_entities": ["美联储政策", "市场情绪"]
|
||||
}
|
||||
|
||||
print(f"模拟搜索结果: {mock_search_result[:100]}...")
|
||||
print(f"模拟LLM响应: {json.dumps(mock_llm_response, ensure_ascii=False, indent=2)}")
|
||||
|
||||
# 测试关系创建
|
||||
try:
|
||||
relation = FinancialRelation(
|
||||
input_entities=mock_llm_response["relations"][0]["input_entities"],
|
||||
output_entities=mock_llm_response["relations"][0]["output_entities"],
|
||||
relation=mock_llm_response["relations"][0]["relation"],
|
||||
reasoning=mock_llm_response["relations"][0]["reasoning"],
|
||||
source=mock_llm_response["relations"][0]["source"],
|
||||
confidence=mock_llm_response["relations"][0]["confidence"],
|
||||
timestamp="2024-01-15 10:30:00"
|
||||
)
|
||||
print(f"成功创建关系: {relation}")
|
||||
except Exception as e:
|
||||
print(f"创建关系失败: {e}")
|
||||
|
||||
print("模拟Agent测试通过!\n")
|
||||
|
||||
|
||||
def main():
|
||||
"""主测试函数"""
|
||||
print("=" * 50)
|
||||
print("金融Agent测试开始")
|
||||
print("=" * 50)
|
||||
|
||||
try:
|
||||
test_schema()
|
||||
test_knowledge_graph()
|
||||
test_mock_agent()
|
||||
|
||||
print("=" * 50)
|
||||
print("所有测试通过!")
|
||||
print("=" * 50)
|
||||
|
||||
except Exception as e:
|
||||
print(f"测试失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Reference in a new issue