stock-ai-agent/backend/app/models/news.py
2026-02-25 19:59:20 +08:00

100 lines
4.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
新闻文章数据库模型
"""
from datetime import datetime
from sqlalchemy import Column, Integer, String, Text, DateTime, JSON, Boolean, Float
from sqlalchemy.orm import relationship
from app.models.database import Base
class NewsArticle(Base):
"""新闻文章表"""
__tablename__ = "news_articles"
id = Column(Integer, primary_key=True, index=True)
# 新闻基本信息
title = Column(String(500), nullable=False)
content = Column(Text, nullable=True) # 完整内容或摘要
content_hash = Column(String(64), nullable=False, index=True) # 内容哈希,用于去重
url = Column(String(1000), nullable=False, unique=True) # 原文链接
source = Column(String(100), nullable=False, index=True) # 来源网站
author = Column(String(200), nullable=True) # 作者
# 新闻分类
category = Column(String(50), nullable=False, index=True) # 'crypto', 'stock', 'forex', 'commodity'
tags = Column(JSON, nullable=True) # 标签列表
# 时间信息
published_at = Column(DateTime, nullable=True, index=True) # 发布时间
crawled_at = Column(DateTime, default=datetime.utcnow, index=True) # 爬取时间
# LLM 分析结果
llm_analyzed = Column(Boolean, default=False, index=True) # 是否已分析
market_impact = Column(String(20), nullable=True, index=True) # 'high', 'medium', 'low'
impact_type = Column(String(50), nullable=True) # 'bullish', 'bearish', 'neutral'
relevant_symbols = Column(JSON, nullable=True) # 相关的币种/股票代码
# LLM 分析详情
sentiment = Column(String(20), nullable=True) # 'positive', 'negative', 'neutral'
summary = Column(Text, nullable=True) # LLM 生成的摘要
key_points = Column(JSON, nullable=True) # 关键点列表
trading_advice = Column(Text, nullable=True) # 交易建议
# 优先级队列
priority = Column(Float, default=0.0, index=True) # 优先级分数
priority_reason = Column(Text, nullable=True) # 优先级原因
# 通知状态
notified = Column(Boolean, default=False, index=True) # 是否已发送通知
notification_sent_at = Column(DateTime, nullable=True)
notification_channel = Column(String(50), nullable=True) # 'feishu', 'telegram', etc.
# 质量控制
quality_score = Column(Float, nullable=True) # 质量分数 0-1
duplicate_of = Column(Integer, nullable=True) # 如果是重复指向原始文章ID
# 状态
is_active = Column(Boolean, default=True, index=True) # 是否有效
# 时间戳
created_at = Column(DateTime, default=datetime.utcnow, index=True)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
def __repr__(self):
return f"<NewsArticle({self.category} {self.source} {self.title[:50]}...)>"
def to_dict(self):
"""转换为字典"""
return {
'id': self.id,
'title': self.title,
'content': self.content,
'url': self.url,
'source': self.source,
'author': self.author,
'category': self.category,
'tags': self.tags,
'published_at': self.published_at.isoformat() if self.published_at else None,
'crawled_at': self.crawled_at.isoformat() if self.crawled_at else None,
'llm_analyzed': self.llm_analyzed,
'market_impact': self.market_impact,
'impact_type': self.impact_type,
'relevant_symbols': self.relevant_symbols,
'sentiment': self.sentiment,
'summary': self.summary,
'key_points': self.key_points,
'trading_advice': self.trading_advice,
'priority': self.priority,
'priority_reason': self.priority_reason,
'notified': self.notified,
'notification_sent_at': self.notification_sent_at.isoformat() if self.notification_sent_at else None,
'notification_channel': self.notification_channel,
'quality_score': self.quality_score,
'duplicate_of': self.duplicate_of,
'is_active': self.is_active,
'created_at': self.created_at.isoformat() if self.created_at else None,
'updated_at': self.updated_at.isoformat() if self.updated_at else None,
}