Return the latest reading-signal profile update for a user. This is used to reinforce the most recent direct-upload PDF topics when the user follows up with a generic phrase like "这类我最近想多看".
(
user_id: str,
minutes: int = 30,
*,
source_prefix: str = "feishu_",
)
| 1715 | |
| 1716 | |
| 1717 | def get_recent_reading_signal( |
| 1718 | user_id: str, |
| 1719 | minutes: int = 30, |
| 1720 | *, |
| 1721 | source_prefix: str = "feishu_", |
| 1722 | ) -> Optional[Dict[str, Any]]: |
| 1723 | """ |
| 1724 | Return the latest reading-signal profile update for a user. |
| 1725 | |
| 1726 | This is used to reinforce the most recent direct-upload PDF topics when the |
| 1727 | user follows up with a generic phrase like "这类我最近想多看". |
| 1728 | """ |
| 1729 | since_timestamp = (datetime.now() - timedelta(minutes=max(1, int(minutes)))).isoformat(sep=" ") |
| 1730 | |
| 1731 | conn = get_connection() |
| 1732 | cursor = conn.cursor() |
| 1733 | cursor.execute( |
| 1734 | """ |
| 1735 | SELECT id, user_id, push_id, paper_id, action, action_type, category, timestamp, metadata |
| 1736 | FROM behavior_logs |
| 1737 | WHERE user_id = ? |
| 1738 | AND action = 'profile_updated' |
| 1739 | AND action_type = 'reading_signal' |
| 1740 | AND timestamp >= ? |
| 1741 | ORDER BY timestamp DESC, id DESC |
| 1742 | LIMIT 20 |
| 1743 | """, |
| 1744 | (user_id, since_timestamp), |
| 1745 | ) |
| 1746 | rows = cursor.fetchall() |
| 1747 | conn.close() |
| 1748 | |
| 1749 | for row in rows: |
| 1750 | record = dict(row) |
| 1751 | metadata = _load_json_metadata(record.get("metadata")) |
| 1752 | source_type = _normalize_identifier(metadata.get("source_type") or metadata.get("report_source_type")) |
| 1753 | if source_prefix and (not source_type or not source_type.startswith(source_prefix)): |
| 1754 | continue |
| 1755 | |
| 1756 | topics = _deserialize_json_list(metadata.get("signal_topics") or metadata.get("topics")) |
| 1757 | activated_topics = _deserialize_json_list(metadata.get("activated_topics")) |
| 1758 | if not topics: |
| 1759 | continue |
| 1760 | |
| 1761 | record["metadata"] = metadata |
| 1762 | record["topics"] = topics |
| 1763 | record["activated_topics"] = activated_topics |
| 1764 | record["source_type"] = source_type |
| 1765 | record["source_key"] = _normalize_identifier(metadata.get("source_key") or metadata.get("report_source_key")) |
| 1766 | record["signal_strength"] = str(metadata.get("signal_strength") or metadata.get("strength") or "").strip() |
| 1767 | return record |
| 1768 | |
| 1769 | return None |
| 1770 | |
| 1771 | |
| 1772 | def get_push_papers(push_id: str) -> Optional[Dict]: |
nothing calls this directly
no test coverage detected