feat: 重构项目结构并添加新功能

- 新增Cloudflare AutoRAG/Vectorize集成文档
- 实现Vertex AI记忆银行功能
- 重构项目目录结构,清理无用文件
- 更新README以反映最新架构
- 添加Google ADK集成测试脚本
- 完善需求文档和设计规范
This commit is contained in:
ben
2025-08-16 10:37:11 +00:00
parent 26338d48cf
commit c4e8cfefc7
106 changed files with 12243 additions and 1839 deletions

View File

@@ -0,0 +1,106 @@
{
"timestamp": "2025-08-02T17:01:29.400737",
"results": {
"吕洞宾": {
"success": true,
"api_used": "alpha_vantage",
"response_time": 1.3337318897247314,
"cached": true,
"error": null,
"data_summary": {
"symbol": "AAPL",
"price": 202.38,
"change_percent": "-2.5004%"
}
},
"何仙姑": {
"success": true,
"api_used": "yahoo_finance_15",
"response_time": 1.87269926071167,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"张果老": {
"success": true,
"api_used": "webull",
"response_time": 2.0619537830352783,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"韩湘子": {
"success": true,
"api_used": "webull",
"response_time": 1.681612253189087,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"汉钟离": {
"success": true,
"api_used": "yahoo_finance_15",
"response_time": 2.100069761276245,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"蓝采和": {
"success": true,
"api_used": "webull",
"response_time": 2.9622411727905273,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"曹国舅": {
"success": true,
"api_used": "yahoo_finance_15",
"response_time": 2.1098716259002686,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"铁拐李": {
"success": true,
"api_used": "alpha_vantage",
"response_time": 0.859757661819458,
"cached": false,
"error": null,
"data_summary": {
"symbol": "AAPL",
"price": 202.38,
"change_percent": "-2.5004%"
}
}
},
"summary": {
"total_immortals": 8,
"successful_calls": 8,
"failed_calls": 0
}
}

View File

@@ -0,0 +1,106 @@
{
"timestamp": "2025-08-02T17:02:25.557362",
"results": {
"吕洞宾": {
"success": true,
"api_used": "webull",
"response_time": 1.8372488021850586,
"cached": true,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"何仙姑": {
"success": true,
"api_used": "yahoo_finance_15",
"response_time": 2.010622262954712,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"张果老": {
"success": true,
"api_used": "webull",
"response_time": 3.3547699451446533,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"韩湘子": {
"success": true,
"api_used": "alpha_vantage",
"response_time": 0.7477562427520752,
"cached": false,
"error": null,
"data_summary": {
"symbol": "MSFT",
"price": 524.11,
"change_percent": "-1.7601%"
}
},
"汉钟离": {
"success": true,
"api_used": "yahoo_finance_15",
"response_time": 2.068232536315918,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"蓝采和": {
"success": true,
"api_used": "webull",
"response_time": 5.828888893127441,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"曹国舅": {
"success": true,
"api_used": "yahoo_finance_15",
"response_time": 4.461008787155151,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"铁拐李": {
"success": true,
"api_used": "alpha_vantage",
"response_time": 1.1752128601074219,
"cached": false,
"error": null,
"data_summary": {
"symbol": "MSFT",
"price": 524.11,
"change_percent": "-1.7601%"
}
}
},
"summary": {
"total_immortals": 8,
"successful_calls": 8,
"failed_calls": 0
}
}

View File

@@ -0,0 +1,106 @@
{
"timestamp": "2025-08-02T17:01:59.012217",
"results": {
"吕洞宾": {
"success": true,
"api_used": "alpha_vantage",
"response_time": 0.7236087322235107,
"cached": true,
"error": null,
"data_summary": {
"symbol": "TSLA",
"price": 302.63,
"change_percent": "-1.8296%"
}
},
"何仙姑": {
"success": true,
"api_used": "yahoo_finance_15",
"response_time": 1.7378709316253662,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"张果老": {
"success": true,
"api_used": "webull",
"response_time": 2.667297601699829,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"韩湘子": {
"success": true,
"api_used": "webull",
"response_time": 1.9658794403076172,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"汉钟离": {
"success": true,
"api_used": "yahoo_finance_15",
"response_time": 3.024261951446533,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"蓝采和": {
"success": true,
"api_used": "webull",
"response_time": 1.5434284210205078,
"cached": false,
"error": null,
"data_summary": {
"symbol": null,
"price": null,
"change_percent": null
}
},
"曹国舅": {
"success": true,
"api_used": "alpha_vantage",
"response_time": 1.1568174362182617,
"cached": false,
"error": null,
"data_summary": {
"symbol": "TSLA",
"price": 302.63,
"change_percent": "-1.8296%"
}
},
"铁拐李": {
"success": true,
"api_used": "alpha_vantage",
"response_time": 1.3348329067230225,
"cached": false,
"error": null,
"data_summary": {
"symbol": "TSLA",
"price": 302.63,
"change_percent": "-1.8296%"
}
}
},
"summary": {
"total_immortals": 8,
"successful_calls": 8,
"failed_calls": 0
}
}

View File

@@ -0,0 +1,283 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
稷下学宫负载均衡演示脚本
展示八仙论道的API负载分担策略
"""
import os
import sys
import time
import json
from datetime import datetime
# 添加项目路径
sys.path.append('/home/ben/liurenchaxin/src')
from jixia.engines.jixia_load_balancer import JixiaLoadBalancer, APIResult
def print_banner():
"""打印横幅"""
print("\n" + "="*80)
print("🏛️ 稷下学宫八仙论道 - API负载均衡演示系统")
print("📊 RapidAPI多源数据整合与负载分担策略")
print("="*80)
print(f"⏰ 演示时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print()
def print_immortal_intro():
"""介绍八仙角色"""
immortals_info = {
'吕洞宾': '主力剑仙 - 综合分析与决策 (Alpha Vantage)',
'何仙姑': '风控专家 - 风险管理与合规 (Yahoo Finance)',
'张果老': '技术分析师 - 技术指标与图表分析 (Webull)',
'韩湘子': '基本面研究员 - 财务分析与估值 (Seeking Alpha)',
'汉钟离': '量化专家 - 数据挖掘与算法交易 (Yahoo Finance)',
'蓝采和': '情绪分析师 - 市场情绪与舆情监控 (Webull)',
'曹国舅': '宏观分析师 - 宏观经济与政策分析 (Seeking Alpha)',
'铁拐李': '逆向投资专家 - 价值发现与逆向思维 (Alpha Vantage)'
}
print("👥 八仙角色与API分配:")
print("-" * 60)
for immortal, description in immortals_info.items():
print(f" {immortal}: {description}")
print()
def demonstrate_single_immortal(load_balancer, immortal_name, symbol):
"""演示单个仙人的数据获取"""
print(f"\n🎭 {immortal_name} 单独获取数据演示:")
print("-" * 40)
# 获取股票报价
result = load_balancer.get_data_for_immortal(immortal_name, 'stock_quote', symbol)
if result.success:
data = result.data
print(f" ✅ 成功获取 {symbol} 数据:")
print(f" 💰 价格: ${data.get('price', 'N/A')}")
print(f" 📈 涨跌: {data.get('change_percent', 'N/A')}")
volume = data.get('volume', 'N/A')
if isinstance(volume, (int, float)):
print(f" 📊 成交量: {volume:,}")
else:
print(f" 📊 成交量: {volume}")
print(f" 🔗 数据源: {result.api_used}")
print(f" ⏱️ 响应时间: {result.response_time:.2f}")
print(f" 💾 缓存状态: {'' if result.cached else ''}")
else:
print(f" ❌ 获取失败: {result.error}")
def demonstrate_load_distribution(load_balancer):
"""演示负载分布"""
print("\n📊 API负载分布统计:")
print("-" * 40)
distribution = load_balancer.get_load_distribution()
if not distribution:
print(" 📝 暂无API调用记录")
return
total_calls = sum(stats['calls'] for stats in distribution.values())
for api_name, stats in distribution.items():
status_icon = "🟢" if stats['healthy'] else "🔴"
print(f" {status_icon} {api_name}:")
print(f" 📞 调用次数: {stats['calls']}")
print(f" 📊 负载占比: {stats['percentage']:.1f}%")
print(f" ❌ 连续失败: {stats['consecutive_failures']}")
print()
def demonstrate_api_comparison(load_balancer, symbol):
"""演示不同API的数据对比"""
print(f"\n🔍 {symbol} 多API数据对比:")
print("-" * 50)
apis = ['alpha_vantage', 'yahoo_finance_15', 'webull']
results = {}
for api in apis:
# 临时修改API分配来测试不同数据源
original_mapping = load_balancer.immortal_api_mapping['stock_quote']['吕洞宾']
load_balancer.immortal_api_mapping['stock_quote']['吕洞宾'] = api
result = load_balancer.get_data_for_immortal('吕洞宾', 'stock_quote', symbol)
results[api] = result
# 恢复原始配置
load_balancer.immortal_api_mapping['stock_quote']['吕洞宾'] = original_mapping
time.sleep(0.5) # 避免过快请求
# 显示对比结果
print(" API数据源对比:")
for api, result in results.items():
if result.success:
data = result.data
print(f" 📡 {api}:")
print(f" 💰 ${data.get('price', 'N/A')} ({data.get('change_percent', 'N/A')})")
print(f" ⏱️ {result.response_time:.2f}s")
else:
print(f" 📡 {api}: ❌ {result.error}")
print()
def demonstrate_cache_effectiveness(load_balancer, symbol):
"""演示缓存效果"""
print(f"\n💾 缓存效果演示 - {symbol}:")
print("-" * 40)
# 第一次调用(无缓存)
print(" 🔄 第一次调用(无缓存):")
start_time = time.time()
result1 = load_balancer.get_data_for_immortal('吕洞宾', 'stock_quote', symbol)
first_call_time = time.time() - start_time
if result1.success:
print(f" ⏱️ 响应时间: {result1.response_time:.2f}")
print(f" 💾 缓存状态: {'命中' if result1.cached else '未命中'}")
time.sleep(1)
# 第二次调用(有缓存)
print(" 🔄 第二次调用(有缓存):")
start_time = time.time()
result2 = load_balancer.get_data_for_immortal('吕洞宾', 'stock_quote', symbol)
second_call_time = time.time() - start_time
if result2.success:
print(f" ⏱️ 响应时间: {result2.response_time:.2f}")
print(f" 💾 缓存状态: {'命中' if result2.cached else '未命中'}")
if result2.cached:
speedup = (first_call_time / second_call_time) if second_call_time > 0 else float('inf')
print(f" 🚀 性能提升: {speedup:.1f}")
def demonstrate_failover(load_balancer, symbol):
"""演示故障转移"""
print(f"\n🔄 故障转移演示 - {symbol}:")
print("-" * 40)
# 模拟API故障
print(" ⚠️ 模拟主API故障...")
# 临时标记API为不健康
original_health = load_balancer.health_checker.health_status['alpha_vantage']['healthy']
load_balancer.health_checker.health_status['alpha_vantage']['healthy'] = False
load_balancer.health_checker.health_status['alpha_vantage']['consecutive_failures'] = 5
# 尝试获取数据(应该自动故障转移)
result = load_balancer.get_data_for_immortal('吕洞宾', 'stock_quote', symbol)
if result.success:
print(f" ✅ 故障转移成功使用备用API: {result.api_used}")
print(f" 💰 获取到价格: ${result.data.get('price', 'N/A')}")
else:
print(f" ❌ 故障转移失败: {result.error}")
# 恢复API健康状态
load_balancer.health_checker.health_status['alpha_vantage']['healthy'] = original_health
load_balancer.health_checker.health_status['alpha_vantage']['consecutive_failures'] = 0
print(" 🔧 API健康状态已恢复")
def save_demo_results(results, filename='demo_results.json'):
"""保存演示结果"""
demo_data = {
'timestamp': datetime.now().isoformat(),
'results': {},
'summary': {
'total_immortals': len(results),
'successful_calls': sum(1 for r in results.values() if r.success),
'failed_calls': sum(1 for r in results.values() if not r.success)
}
}
for immortal, result in results.items():
demo_data['results'][immortal] = {
'success': result.success,
'api_used': result.api_used,
'response_time': result.response_time,
'cached': result.cached,
'error': result.error,
'data_summary': {
'symbol': result.data.get('symbol') if result.success else None,
'price': result.data.get('price') if result.success else None,
'change_percent': result.data.get('change_percent') if result.success else None
}
}
with open(filename, 'w', encoding='utf-8') as f:
json.dump(demo_data, f, indent=2, ensure_ascii=False)
print(f"\n💾 演示结果已保存到: {filename}")
def main():
"""主演示函数"""
# 检查API密钥
rapidapi_key = os.getenv('RAPIDAPI_KEY')
if not rapidapi_key:
print("❌ 错误: 请设置RAPIDAPI_KEY环境变量")
print(" 提示: 使用 'doppler run python demo_jixia_load_balancing.py' 运行")
return
print_banner()
print_immortal_intro()
# 创建负载均衡器
print("🔧 初始化稷下学宫负载均衡器...")
load_balancer = JixiaLoadBalancer(rapidapi_key)
print("✅ 负载均衡器初始化完成\n")
# 演示股票代码
demo_symbols = ['AAPL', 'TSLA', 'MSFT']
for i, symbol in enumerate(demo_symbols, 1):
print(f"\n{'='*20} 演示 {i}: {symbol} {'='*20}")
# 1. 单个仙人演示
demonstrate_single_immortal(load_balancer, '吕洞宾', symbol)
# 2. 八仙论道演示
print(f"\n🏛️ 八仙论道完整演示 - {symbol}:")
debate_results = load_balancer.conduct_immortal_debate(symbol)
# 3. 负载分布演示
demonstrate_load_distribution(load_balancer)
# 只在第一个股票上演示高级功能
if i == 1:
# 4. API对比演示
demonstrate_api_comparison(load_balancer, symbol)
# 5. 缓存效果演示
demonstrate_cache_effectiveness(load_balancer, symbol)
# 6. 故障转移演示
demonstrate_failover(load_balancer, symbol)
# 保存结果
save_demo_results(debate_results, f'demo_results_{symbol.lower()}.json')
if i < len(demo_symbols):
print("\n⏳ 等待3秒后继续下一个演示...")
time.sleep(3)
# 最终统计
print("\n" + "="*80)
print("📈 演示完成 - 最终负载分布统计:")
demonstrate_load_distribution(load_balancer)
print("\n🎉 稷下学宫API负载均衡演示完成")
print("\n💡 关键特性:")
print(" ✅ 智能负载分担 - 八仙各司其职分散API压力")
print(" ✅ 自动故障转移 - API异常时自动切换备用源")
print(" ✅ 数据标准化 - 统一不同API的数据格式")
print(" ✅ 智能缓存 - 减少重复调用,提升响应速度")
print(" ✅ 实时监控 - 跟踪API健康状态和负载分布")
print("\n📚 查看详细配置: /home/ben/liurenchaxin/src/jixia/config/immortal_api_config.json")
print("🔧 核心引擎: /home/ben/liurenchaxin/src/jixia/engines/jixia_load_balancer.py")
print("="*80)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,245 @@
#!/usr/bin/env python3
"""
Vertex AI Memory Bank 演示脚本
展示稷下学宫记忆增强AI辩论系统
"""
import asyncio
import sys
import os
# 添加项目根目录到路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from src.jixia.agents.memory_enhanced_agent import create_memory_enhanced_council
from config.doppler_config import validate_config
async def demo_memory_enhanced_debate():
"""演示记忆增强的AI辩论"""
print("🏛️ 稷下学宫 Vertex AI Memory Bank 演示")
print("=" * 60)
# 验证配置
print("🔧 验证配置...")
if not validate_config("google_adk"):
print("❌ 配置验证失败,请检查环境变量")
return
try:
# 创建记忆增强议会
print("\n🎭 创建八仙记忆增强议会...")
council = await create_memory_enhanced_council()
# 演示主题
topics = [
"特斯拉股票投资价值分析",
"人工智能行业投资机会",
"加密货币市场前景展望"
]
# 选择参与的仙人(为了演示,只选择几位)
participants = ["tieguaili", "lvdongbin", "hexiangu", "zhangguolao"]
for i, topic in enumerate(topics, 1):
print(f"\n{'='*40}")
print(f"🎯 第 {i} 场辩论: {topic}")
print(f"{'='*40}")
# 进行记忆增强辩论
result = await council.conduct_memory_debate(
topic=topic,
participants=participants,
rounds=2 # 每场2轮保持演示简洁
)
print(f"\n📊 辩论结果:")
print(f" 主题: {result['topic']}")
print(f" 参与者: {len(result['participants'])} 位仙人")
print(f" 总发言: {result['total_exchanges']}")
# 显示部分对话内容
print(f"\n💬 精彩观点摘录:")
for exchange in result['conversation_history'][:4]: # 只显示前4条
content_preview = exchange['content'][:120] + "..." if len(exchange['content']) > 120 else exchange['content']
print(f" 🗣️ {exchange['chinese_name']}: {content_preview}")
# 获取集体记忆摘要
print(f"\n📚 获取集体记忆...")
summary = await council.get_collective_memory_summary(topic)
if "暂无相关集体记忆" not in summary:
print(f" ✅ 已生成 {len(summary)} 字符的记忆摘要")
else:
print(f" 这是新主题,正在建立记忆")
# 演示间隔
if i < len(topics):
print(f"\n⏳ 准备下一场辩论...")
await asyncio.sleep(1)
# 最终演示:展示记忆的累积效果
print(f"\n{'='*60}")
print("🧠 记忆累积效果演示")
print(f"{'='*60}")
# 让铁拐李基于所有记忆回答一个综合问题
tieguaili = council.agents.get("tieguaili")
if tieguaili:
print(f"\n🤔 向铁拐李提问: '基于你的所有记忆,总结一下当前市场的主要风险'")
comprehensive_response = await tieguaili.respond_with_memory(
message="基于你参与的所有辩论和积累的记忆,总结一下当前市场的主要风险和你的投资建议。",
topic="综合市场分析"
)
print(f"\n🧙‍♂️ 铁拐李的综合分析:")
print(f" {comprehensive_response}")
# 展示记忆学习功能
print(f"\n🎓 演示记忆学习功能...")
# 让何仙姑学习一个用户偏好
hexiangu = council.agents.get("hexiangu")
if hexiangu:
await hexiangu.learn_preference(
preference="用户偏好ESG投资关注环境和社会责任",
topic="投资偏好"
)
print(f" ✅ 何仙姑学习了ESG投资偏好")
# 基于新学到的偏好回答问题
esg_response = await hexiangu.respond_with_memory(
message="推荐一些符合ESG标准的投资标的",
topic="ESG投资"
)
print(f"\n👸 何仙姑基于学习的偏好回应:")
print(f" {esg_response[:200]}...")
print(f"\n🎉 演示完成!")
print(f"\n💡 Memory Bank 的优势:")
print(f" ✅ 智能体能记住历史对话和分析")
print(f" ✅ 学习用户偏好,提供个性化建议")
print(f" ✅ 积累投资策略和市场洞察")
print(f" ✅ 跨会话保持一致的人格和观点")
print(f" ✅ 基于历史经验做出更好的决策")
except Exception as e:
print(f"❌ 演示过程中出现错误: {e}")
print(f"💡 请检查:")
print(f" - Google Cloud Project ID 是否正确配置")
print(f" - Vertex AI API 是否已启用")
print(f" - 网络连接是否正常")
async def demo_individual_memory_features():
"""演示个体记忆功能"""
print(f"\n{'='*60}")
print("🔍 个体记忆功能详细演示")
print(f"{'='*60}")
try:
from src.jixia.memory.vertex_memory_bank import VertexMemoryBank
from src.jixia.agents.memory_enhanced_agent import MemoryEnhancedAgent
# 创建记忆银行
memory_bank = VertexMemoryBank.from_config()
# 创建单个智能体进行详细演示
agent = MemoryEnhancedAgent("tieguaili", memory_bank)
print(f"\n🧙‍♂️ 与 {agent.personality.chinese_name} 的记忆互动演示")
# 1. 添加不同类型的记忆
print(f"\n📝 添加不同类型的记忆...")
memories_to_add = [
{
"content": "在2008年金融危机中逆向投资者获得了丰厚回报",
"memory_type": "knowledge",
"topic": "历史教训"
},
{
"content": "用户偏好价值投资,不喜欢高风险的成长股",
"memory_type": "preference",
"topic": "用户偏好"
},
{
"content": "当市场过度乐观时,应该保持谨慎并寻找反向机会",
"memory_type": "strategy",
"topic": "投资策略"
}
]
for memory in memories_to_add:
await memory_bank.add_memory(
agent_name="tieguaili",
content=memory["content"],
memory_type=memory["memory_type"],
debate_topic=memory["topic"]
)
print(f" ✅ 添加{memory['memory_type']}记忆: {memory['content'][:50]}...")
# 2. 搜索记忆
print(f"\n🔍 搜索相关记忆...")
search_queries = ["金融危机", "价值投资", "投资策略"]
for query in search_queries:
results = await memory_bank.search_memories(
agent_name="tieguaili",
query=query,
limit=3
)
print(f" 🔎 搜索 '{query}': 找到 {len(results)} 条相关记忆")
for result in results:
relevance = result.get('relevance_score', 'N/A')
print(f" - {result['content'][:60]}... (相关度: {relevance})")
# 3. 基于记忆的智能回应
print(f"\n🤖 基于记忆的智能回应演示...")
questions = [
"现在市场很乐观,你有什么建议?",
"推荐一些适合保守投资者的标的",
"历史上有哪些值得借鉴的投资教训?"
]
for question in questions:
print(f"\n❓ 问题: {question}")
response = await agent.respond_with_memory(
message=question,
topic="投资咨询"
)
print(f"🧙‍♂️ 铁拐李: {response[:150]}...")
print(f"\n✨ 个体记忆功能演示完成!")
except Exception as e:
print(f"❌ 个体记忆演示失败: {e}")
async def main():
"""主演示函数"""
print("🚀 启动 Vertex AI Memory Bank 完整演示")
# 主要演示:记忆增强辩论
await demo_memory_enhanced_debate()
# 详细演示:个体记忆功能
await demo_individual_memory_features()
print(f"\n🏛️ 稷下学宫 Memory Bank 演示结束")
print(f"📖 更多信息请参考: docs/VERTEX_MEMORY_BANK_SETUP.md")
if __name__ == "__main__":
# 运行演示
asyncio.run(main())