feat: FAM-Edge chat proxy + PyMySQL migration for FAM-UI + config update

- FAM-Edge: add /api/edge/chat proxy endpoint forwarding to local Ollama
  (Ollama port 11434 not exposed externally, FAM-Edge acts as reverse proxy)
- FAM-Core config: edge_url and ollama_url switched from Tailscale IP to
  Oracle public IP (Tailscale firewall blocking between NAS and Oracle)
- FAM-UI: migrate mysql.connector to PyMySQL (same as FAM-Core)
- FAM-UI: cursor(dictionary=True) replaced with cursorclass=DictCursor
- End-to-end chat verified: FAM-Core -> FAM-Edge proxy -> Ollama -> response
  Answer: 今天没有观察到张三 (no events in DB yet, expected)
This commit is contained in:
ericwyuan
2026-08-19 23:59:28 +08:00
parent c8cd2f2665
commit 94a8805045
4 changed files with 35 additions and 11 deletions

View File

@@ -1,5 +1,5 @@
streamlit>=1.30.0
mysql-connector-python>=8.3.0
PyMySQL>=1.1.0
pandas>=2.1.0
requests>=2.31.0
PyYAML>=6.0

View File

@@ -8,7 +8,8 @@ import os
import sys
import requests
import streamlit as st
import mysql.connector
import pymysql
import pymysql.cursors
import pandas as pd
import json
from datetime import datetime, date
@@ -26,13 +27,14 @@ _db_cfg = _cfg.get('database', {})
def get_db_conn():
"""获取数据库连接"""
return mysql.connector.connect(
return pymysql.connect(
host=_db_cfg.get('host', '127.0.0.1'),
port=_db_cfg.get('port', 3306),
user=_db_cfg.get('user', 'root'),
password=_db_cfg.get('password', ''),
database=_db_cfg.get('database', 'sentinel_home_ai'),
charset='utf8mb4'
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
@@ -83,7 +85,7 @@ if page == "📊 事件列表":
conn = get_db_conn()
try:
cursor = conn.cursor(dictionary=True)
cursor = conn.cursor()
# 查询条件
date_str = date_filter.isoformat() if date_filter else None
@@ -185,7 +187,7 @@ elif page == "💬 AI 对话":
# 快捷人物按钮
conn = get_db_conn()
try:
cursor = conn.cursor(dictionary=True)
cursor = conn.cursor()
cursor.execute("SELECT DISTINCT real_name FROM family_members WHERE real_name IS NOT NULL AND is_active = TRUE")
named = [row['real_name'] for row in cursor.fetchall()]
finally:
@@ -256,7 +258,7 @@ elif page == "📝 对话历史":
conn = get_db_conn()
try:
cursor = conn.cursor(dictionary=True)
cursor = conn.cursor()
cursor.execute(
"""SELECT chat_id, user_question, ai_answer, context_summary,
queried_date, queried_person, created_at
@@ -311,7 +313,7 @@ elif page == "👤 成员命名":
st.subheader("未命名人物")
conn = get_db_conn()
try:
cursor = conn.cursor(dictionary=True)
cursor = conn.cursor()
cursor.execute(
"""SELECT fm.abstract_label, fm.feature_description, fm.first_seen_at,
(SELECT COUNT(*) FROM event_details ed WHERE ed.person = fm.abstract_label) AS event_count
@@ -399,7 +401,7 @@ elif page == "📈 统计图表":
conn = get_db_conn()
try:
cursor = conn.cursor(dictionary=True)
cursor = conn.cursor()
# compute_provider 分布
st.subheader("模型来源分布")