news 2026/9/7 5:03:15

用FastAPI和SQLite构建本地情感关怀服务:定时祝福与情感分析实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用FastAPI和SQLite构建本地情感关怀服务:定时祝福与情感分析实践

这次我们来看一个很适合个人开发者和家庭场景的服务型小项目:“你的幸福就是我最大的幸福”。它不是一个图像生成工作流,也不是语音克隆工具,而是一套用 FastAPI 搭起来的本地情感关怀服务,用来记录你在意的人的重要日期和情绪状态,在关键时刻自动生成并推送一条祝福文案。项目的核心理念很朴素:把“关心”变成数据、规则和定时任务,不让任何一个值得记住的日子被漏掉。

这个项目最值得关注的点有几个:所有隐私数据默认存在本地 SQLite,不需要把家庭成员记录传到外部平台;提供完整的 REST API,可以接自己的任务流;支持批量生成祝福文案和定时扫描提醒;硬件门槛低,轻量模式在普通办公电脑上就能运行;同时保留了接入更强情感分析模型的空间。如果后续要接入本地大模型做语义分析,才会涉及显卡和显存评估,基础版本并不依赖 GPU。

本文会带读者从零搭建完整闭环:先初始化项目结构和数据库,再启动 API 服务,然后录入用户和情感记录,跑一轮情感分析与祝福文案生成,最后配置定时任务和批量任务队列。每一步都给出了可复制的代码和使用方法,读者跟着操作就能得到一个可运行的本地服务。

适合的读者有两类:一类是想要给家人、伴侣、朋友做一套私人提醒系统的个人开发者;另一类是正在学习 FastAPI、SQLite、定时任务和本地数据存储全栈思路的初学者。如果只是好奇,也可以先看第 5 节的功能测试和第 8 节的资源占用部分,能快速判断这套方案是否符合自己的需求。

1. 核心能力速览

先把项目的关键规格放在前面,方便快速判断这个方案值不值得花时间。

能力项说明
项目类型本地部署的情感关怀与幸福记录服务(示例项目)
主要功能用户管理、情感记录、轻量情感分析、祝福文案生成、日期提醒、批量文案生成
存储方式SQLite 本地数据库,数据默认不出本机
推荐运行环境Python 3.9 及以上,Windows / Linux / macOS 均可
硬件门槛轻量模式普通办公电脑即可;接入本地大模型做语义分析时才需要评估显存
启动方式命令行启动 FastAPI 服务
接口 API提供 REST API,可通过 /docs 查看交互文档
批量任务支持批量生成祝福文案、定时扫描提醒日期
推送方式默认输出 JSON 文件和日志,可自行扩展邮件、机器人等通道
适合场景个人与家庭隐私场景、FastAPI 全栈学习、自动化关怀任务

需要强调一点:这个项目是一个通用实现模板,不是某个组织发布的闭源软件。读者拿到的是代码骨架,实际的情感词典、文案风格、数据库表结构都可以按自己的场景改。表格里的“本地部署”“REST API”等说法,都是围绕这个模板本身的能力来描述的,不绑定任何特定开源模型或第三方平台账号。

2. 适用场景与使用边界

这个服务最合适的场景是个人和家庭内部使用。你可以记录父母的生日、伴侣的结婚纪念日、孩子的重要成长节点,然后让系统到点提醒你:该打个电话,该发条消息,该准备一份小礼物。相比在手机上单纯设一个日历闹钟,这套项目的优势在于它把人物关系、情感记录和文案生成串在了一起,提醒的不只是一个“日期”,而是一个“为什么要做这件事”的上下文。

它也能用于学习完整的后端开发流程。FastAPI 负责接口层,SQLite 负责持久化,APScheduler 负责定时任务,情感分析和模板生成负责业务逻辑。整个项目结构足够小,但已经覆盖了一个服务端应用的主要模块,适合作为练手项目逐步扩展。

使用边界要提前说清楚。第一,不要在没有鉴权的情况下把服务暴露到公网,默认监听 127.0.0.1 就是为安全考虑的,如果要多设备访问,应该自己加 Token 或身份校验。第二,情感分析结果只做参考,它不能替代心理咨询或医疗判断,如果发现记录对象长期处于明显的负面情绪,应该用真实的人际关怀去介入。第三,如果你要把家人的情绪记录、日期信息录入系统,最好征得对方同意,这些信息属于个人敏感数据。第四,未来如果扩展成自动发送短信、微信消息、生成照片或语音祝福,必须使用合规的推送通道,并确保肖像权和声音权已经获得授权。

3. 环境准备与项目结构

先准备 Python 环境。推荐使用虚拟环境隔离依赖,避免和系统 Python 包冲突。Windows 用户在命令提示符或 PowerShell 中执行,Linux / macOS 用户使用终端。

mkdir happiness_service cd happiness_service python -m venv venv

激活虚拟环境:

# Windows venv\Scripts\activate # Linux / macOS source venv/bin/activate

创建依赖文件 requirements.txt,写入以下内容:

fastapi>=0.110 uvicorn>=0.29 apscheduler>=3.10 pydantic>=2.6

然后安装依赖:

pip install -r requirements.txt

依赖安装完成后,创建项目目录结构。推荐按下面的方式组织文件,后续扩展功能时不容易乱:

happiness_service/ ├── app.py ├── config.py ├── database.py ├── analyzer.py ├── template_engine.py ├── scheduler.py ├── requirements.txt ├── data/ └── scripts/ └── send_blessing.py

每个文件的职责如下:config.py 保存路径和端口配置;database.py 负责 SQLite 初始化和增删改查;analyzer.py 做轻量情感分析;template_engine.py 负责祝福文案生成;scheduler.py 是定时提醒任务;app.py 是 FastAPI 入口;scripts 目录放独立的批量脚本。

先写 config.py,把路径集中管理:

import os BASE_DIR = os.path.dirname(os.path.abspath(__file__)) DATA_DIR = os.path.join(BASE_DIR, "data") DB_PATH = os.path.join(DATA_DIR, "happiness.db") HOST = os.getenv("HAPPINESS_HOST", "127.0.0.1") PORT = int(os.getenv("HAPPINESS_PORT", "8000"))

然后写 database.py,包含建表和基础数据访问方法:

import sqlite3 from pathlib import Path from config import DATA_DIR, DB_PATH def get_connection(): Path(DB_PATH).parent.mkdir(parents=True, exist_ok=True) conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row return conn def init_db(): conn = get_connection() conn.executescript( """ CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, relationship TEXT DEFAULT 'default', birthday TEXT, anniversary_date TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS records ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, content TEXT NOT NULL, mood_type TEXT, mood_score REAL, keywords TEXT, remark TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ); CREATE TABLE IF NOT EXISTS remind_tasks ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, task_type TEXT NOT NULL, task_date TEXT NOT NULL, message TEXT, status TEXT DEFAULT 'pending', created_at TEXT DEFAULT CURRENT_TIMESTAMP ); """ ) conn.commit() conn.close()

数据表设计为三张:users 保存人物信息,records 保存每次情感记录和分析结果,remind_tasks 保存待触发的提醒任务。birthday 和 anniversary_date 统一使用“YYYY-MM-DD”格式字符串,方便定时任务按月日匹配。

analyzer.py 先实现一个离线情感词典版本,不需要联网,也不需要 GPU。这个版本用来演示完整流程够了,后续想提高准确率,可以把 analyze_sentiment 函数内部换成调用本地部署的情感分类模型。

POSITIVE_WORDS = {"幸福", "开心", "快乐", "温暖", "感动", "满足", "喜欢", "顺利", "健康", "值得"} NEGATIVE_WORDS = {"难过", "失落", "疲惫", "焦虑", "生气", "委屈", "压力", "糟糕", "失眠", "担心"} def analyze_sentiment(text: str) -> dict: positive_hits = [w for w in POSITIVE_WORDS if w in text] negative_hits = [w for w in NEGATIVE_WORDS if w in text] if not positive_hits and not negative_hits: return { "mood_type": "neutral", "mood_score": 5.0, "keywords": [], } total = len(positive_hits) + len(negative_hits) ratio = len(positive_hits) / total if ratio >= 0.6: mood_type = "positive" elif ratio <= 0.4: mood_type = "negative" else: mood_type = "neutral" return { "mood_type": mood_type, "mood_score": round(ratio * 10, 1), "keywords": positive_hits + negative_hits, }

template_engine.py 使用模板生成祝福文案。这里先做离线模板版本,避免把家庭场景的文案请求发送到外部大模型接口。按场景区分生日、纪念日、日常问候,后续可以按人物关系继续扩展模板库。

TEMPLATES = { "birthday": [ "{name},生日快乐。愿你想要的都拥有,愿你珍惜的人一直陪在身边。你的幸福就是我最大的幸福。", "今天是你的生日,{name}。不用赶着成为谁,今天只做开心的自己。", ], "anniversary": [ "{name},纪念日快乐。谢谢你在那些平常日子里给的陪伴,愿以后每个重要日子我们都不缺席。", "属于我们的纪念日又到了,{name}。时间在走,想给你的心意不变。", ], "daily": [ "{name},今天有没有按时吃饭?稍微停下来歇一会儿,别让自己太累。", "想跟你说声,{name},今天也辛苦了。你的笑容就是我最想守护的东西。", ], } RELATIONSHIP_NOTES = { "partner": "最珍惜的人", "parent": "最想孝顺的人", "child": "最想守护的人", "friend": "重要的朋友", "default": "在乎的人", } def build_relationship_prefix(relationship: str) -> str: return RELATIONSHIP_NOTES.get(relationship, RELATIONSHIP_NOTES["default"]) def generate_blessing(user_name: str, scenario: str = "daily", relationship: str = "default") -> str: templates = TEMPLATES.get(scenario, TEMPLATES["daily"]) template = templates[0] return template.format(name=user_name)

到这一步,项目骨架已经完整。没有 GPU 也能跑,因为你还没有调用任何深度学习模型。下面进入服务启动和接口验证。

4. 启动 API 服务与基础验证

现在写 FastAPI 入口 app.py。这里直接调用 init_db 初始化数据库,减少启动时序问题。再定义用户创建、情感记录、情感趋势和祝福生成等接口。

from typing import Optional from fastapi import FastAPI from pydantic import BaseModel from analyzer import analyze_sentiment from config import init_app_config from database import ( add_record, add_user, get_mood_trend, init_db, list_records, list_users, ) from template_engine import generate_blessing app = FastAPI(title="你的幸福就是我最大的幸福", version="0.1.0") init_db() class UserCreate(BaseModel): name: str relationship: str = "default" birthday: Optional[str] = None anniversary_date: Optional[str] = None class RecordCreate(BaseModel): user_id: int content: str remark: Optional[str] = None class BlessingRequest(BaseModel): name: str scenario: str = "daily" relationship: str = "default" @app.get("/health") def health_check(): return {"status": "ok", "service": "happiness-service"} @app.post("/users") def create_user(payload: UserCreate): user_id = add_user( name=payload.name, relationship=payload.relationship, birthday=payload.birthday, anniversary_date=payload.anniversary_date, ) return {"user_id": user_id, "message": "用户创建成功"} @app.get("/users") def query_users(): return list_users() @app.post("/records") def create_record(payload: RecordCreate): mood_result = analyze_sentiment(payload.content) record_id = add_record( user_id=payload.user_id, content=payload.content, mood_result=mood_result, remark=payload.remark, ) return {"record_id": record_id, "analysis": mood_result} @app.get("/users/{user_id}/records") def query_records(user_id: int): return list_records(user_id=user_id) @app.get("/users/{user_id}/mood_trend") def query_mood_trend(user_id: int): return get_mood_trend(user_id=user_id) @app.post("/blessing") def create_blessing(payload: BlessingRequest): return { "scenario": payload.scenario, "message": generate_blessing( user_name=payload.name, scenario=payload.scenario, relationship=payload.relationship, ), }

注意,这个版本没有给接口加鉴权,只适合本机测试。启动命令如下:

uvicorn app:app --host 127.0.0.1 --port 8000

启动后终端会输出访问地址。浏览器打开 http://127.0.0.1:8000/docs,如果能看到 FastAPI 自带的 Swagger 交互文档,说明服务已经跑起来了。Swagger 页面会把所有接口列出,并且支持直接在页面上点击 Try it out 发送请求,这是最方便的接口验证方式。

也可以先验证健康检查接口:

curl http://127.0.0.1:8000/health

返回结果:

{"status":"ok","service":"happiness-service"}

看到这个输出,服务就是可用的。接下来开始录入真实数据,做功能测试。

5. 功能测试:情感记录与祝福生成

先创建一个用户。比如要记录妈妈的信息,接口请求如下:

curl -X POST http://127.0.0.1:8000/users \ -H "Content-Type: application/json" \ -d '{"name": "妈妈", "relationship": "parent", "birthday": "1965-08-20"}'

预期返回:

{"user_id":1,"message":"用户创建成功"}

如果返回其他内容,先看 Swagger 页面里的错误提示,通常是 JSON 格式错误或者日期字段格式不对。

创建用户后,添加一条情感记录。这里设计接口会先调用 analyzer.py 的情感分析,再把分析结果和原文一起存入数据库。

curl -X POST http://127.0.0.1:8000/records \ -H "Content-Type: application/json" \ -d '{"user_id": 1, "content": "今天陪妈妈复查,医生说恢复得很好,她特别开心。", "remark": "复查日"}'

预期返回:

{ "record_id": 1, "analysis": { "mood_type": "positive", "mood_score": 10.0, "keywords": ["开心"] } }

这里 mood_type 有三种可能:positive、neutral、negative。mood_score 范围是 0 到 10,分数越高代表文本中包含的积极词汇占比越高。keywords 是文本中命中的情感词典词汇。因为原文里有“开心”而没有负面词,所以判定为 positive,分数是 10。

再测试一条负面记录:

curl -X POST http://127.0.0.1:8000/records \ -H "Content-Type: application/json" \ -d '{"user_id": 1, "content": "她说最近总是失眠,工作压力很大。", "remark": "日常记录"}'

返回结果里 mood_type 应该是 negative,mood_score 偏低,keywords 至少包含“失眠”“压力”。这说明情感分析接口能区分正向和负向表达。

情感趋势接口能把一段时间内的记录聚合成折线数据。请求:

curl http://127.0.0.1:8000/users/1/mood_trend

返回按日期分组的平均 mood_score。这个接口适合后续做一个小型 Web 看板,用来观察记录对象的情绪变化。

祝福生成接口测试:

curl -X POST http://127.0.0.1:8000/blessing \ -H "Content-Type: application/json" \ -d '{"name": "妈妈", "scenario": "daily", "relationship": "parent"}'

预期返回:

{ "scenario": "daily", "message": "妈妈,今天有没有按时吃饭?稍微停下来歇一会儿,别让自己太累。" }

如果返回的是英文或者乱码,检查终端编码。在 Windows 的 PowerShell 里发送中文 JSON 可能会出现编码问题,更稳妥的办法是用 Python 脚本调用接口,或者把 JSON 写入文件再通过 curl 的 --data @file 方式发送。

6. 接口 API 调用示例

接口跑通后,可以把服务接到自己的脚本里。下面是 Python 调用示例,适合在本地批量录入数据和生成文案。

import requests BASE = "http://127.0.0.1:8000" # 创建用户 user = requests.post( f"{BASE}/users", json={ "name": "妈妈", "relationship": "parent", "birthday": "1965-08-20", "anniversary_date": None, }, ).json() print(user) # 添加一条情感记录 record = requests.post( f"{BASE}/records", json={ "user_id": user["user_id"], "content": "今天陪妈妈复查,医生说恢复得很好,她特别开心。", "remark": "复查日", }, ).json() print(record) # 生成祝福文案 blessing = requests.post( f"{BASE}/blessing", json={ "name": "妈妈", "scenario": "daily", "relationship": "parent", }, ).json() print(blessing["message"])

如果只需要生成文案,不一定要先创建用户。祝福接口只依赖 name、scenario、relationship 三个字段,可以直接使用。

批量生成祝福文案时,建议把名单放到一个 JSON 文件里,例如 people.json:

[ {"name": "爸爸", "relationship": "parent", "scenario": "birthday"}, {"name": "伴侣", "relationship": "partner", "scenario": "anniversary"}, {"name": "朋友", "relationship": "friend", "scenario": "daily"} ]

再写一个批量脚本 scripts/send_blessing.py:

import argparse import json import requests BASE = "http://127.0.0.1:8000" def load_people(path): with open(path, encoding="utf-8") as f: return json.load(f) def batch_generate(people): results = [] for person in people: response = requests.post( f"{BASE}/blessing", json={ "name": person["name"], "scenario": person.get("scenario", "daily"), "relationship": person.get("relationship", "default"), }, timeout=10, ) data = response.json() results.append( { "name": person["name"], "message": data["message"], } ) return results if __name__ == "__main__": parser = argparse.ArgumentParser(description="批量生成祝福文案") parser.add_argument("--people", default="people.json", help="名单文件") parser.add_argument("--output", default="blessing_output.json", help="输出文件") args = parser.parse_args() people = load_people(args.people) results = batch_generate(people) with open(args.output, "w", encoding="utf-8") as f: json.dump(results, f, ensure_ascii=False, indent=2) print(f"已生成 {len(results)} 条文案,输出到 {args.output}")

运行命令:

python scripts/send_blessing.py --people people.json --output blessing_output.json

运行后打开 blessing_output.json,应该能看到三条已经填充好人名的祝福文案。这样即使一次要写几十个人的祝福,也只需要维护一份名单文件,剩下的事情交给脚本。

批量脚本有一个明显的优点:它只依赖 /blessing 接口,改动模板时不需要重新学脚本。缺点是如果服务没有启动,所有请求都会失败,所以脚本里需要增加超时和异常处理。更完整的版本可以加日志记录,把失败的用户单独输出到一个 retry.json 文件,方便二次重跑。

7. 定时提醒与批量任务扩展

只记录数据和生成文案还不够,真正让“你的幸福就是我最大的幸福”落地的是定时提醒。APScheduler 可以放在服务里,每隔一段时间扫描一次数据库,把当天需要提醒的人物找出来,写入队列文件。

scheduler.py 实现定时扫描逻辑:

import json import os from datetime import datetime from apscheduler.schedulers.background import BackgroundScheduler from config import DATA_DIR from database import get_connection QUEUE_FILE = os.path.join(DATA_DIR, "remind_queue.json") def scan_reminders(): today = datetime.now().strftime("%m-%d") conn = get_connection() rows = conn.execute( """ SELECT u.id, u.name, u.relationship, u.birthday, u.anniversary_date FROM users u WHERE (substr(u.birthday, 6) = ?) OR (substr(u.anniversary_date, 6) = ?) """, (today, today), ).fetchall() pending = [] for row in rows: user = dict(row) if user["birthday"] and user["birthday"][5:] == today: task_type = "birthday" elif user["anniversary_date"] and user["anniversary_date"][5:] == today: task_type = "anniversary" else: continue pending.append( { "user_id": user["id"], "name": user["name"], "task_type": task_type, "date": datetime.now().strftime("%Y-%m-%d"), } ) conn.close() os.makedirs(DATA_DIR, exist_ok=True) with open(QUEUE_FILE, "w", encoding="utf-8") as f: json.dump(pending, f, ensure_ascii=False, indent=2) if pending: print(f"[reminder] 检测到 {len(pending)} 条应提醒事项") else: print("[reminder] 今天没有匹配的日期") def start_scheduler(): scheduler = BackgroundScheduler() scheduler.add_job(scan_reminders, "interval", minutes=1, id="scan_reminders") scheduler.start() print("[scheduler] 定时任务已启动,每 1 分钟扫描一次") return scheduler

这个逻辑的核心是把日期字符串的“MM-DD”部分和今天的“MM-DD”比较。birthday 如果传的是 “1965-08-20”,substr(birthday, 6) 得到 “08-20”,和今天的 “08-20” 匹配,就说明今天是这个人的生日。

定时任务不建议通过接口启动,因为 uvicorn 开启 --reload 时可能重复启动多个调度器。更稳妥的做法是把定时任务独立成一个进程。在 scripts 下新建 run_scheduler.py:

import sys import threading from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from scheduler import start_scheduler if __name__ == "__main__": scheduler = start_scheduler() print("按 Ctrl+C 退出") try: threading.Event().wait() except KeyboardInterrupt: scheduler.shutdown()

运行:

python scripts/run_scheduler.py

默认情况下,扫描结果写到 data/remind_queue.json。实际使用中,你可以在 scan_reminders 函数末尾追加真实的推送通道,比如发送邮件、调用企业微信群机器人、写入自己的待办应用。推送通道需要单独申请权限,因此这套项目先统一走 JSON 文件,方便你自己对接。

批量任务可以分为两种。一种是周期性批量生成文案,用第 6 节的 send_blessing.py 就能实现。另一种是批量发送提醒,需要你把发送状态回写到数据库的 remind_tasks 表里,至少增加一个 processed 字段,避免每次扫描都重复发送同一条消息。这是从示例走向生产环境必须补上的细节。

8. 资源占用与性能观察

这个项目的基础版本没有任何深度学习模型,资源占用很低。启动 uvicorn 和 APScheduler 后,主要消耗来自 Python 进程本身。普通办公电脑上,内存占用通常在几十 MB 到一两百 MB 区间,具体数值会因 Python 版本和已安装依赖不同而有差异。CPU 占用在没有请求时接近 0,每隔一分钟的定时扫描任务也只需要执行几条 SQLite 查询和少量字符串比较。

显存占用在这个项目里是可选项。如果你只使用情感词典和模板生成,整个过程完全不需要 GPU。后续如果需要更准确的情感语义分析,可以在 analyzer.py 中改为调用本地部署的开源情感分类模型或本地大模型,这时才需要关注显存。显存占用取决于你接的模型参数量、输入文本长度和推理框架,没有统一数字,必须按本机实测为准。

观察资源占用有三种方式。第一,Windows 任务管理器里看 python 进程的 CPU 和内存。第二,Linux 下使用 top 或 htop 查看。第三,如果接入了本地 GPU 模型,使用 nvidia-smi 观察当前进程的显存占用。

nvidia-smi

批量任务对性能的影响要分开看。批量生成祝福文案时,瓶颈一般在模板引擎和 JSON 序列化,数千条文案也是秒级完成。批量写入情感记录时,瓶颈可能出现在 SQLite 写入频率上,建议批量插入时使用事务,而不是逐条提交。另外,定时扫描任务如果间隔太短,并且扫描逻辑里加了外部推送,就要考虑推送通道的频率限制,避免被平台当成垃圾请求。

内存泄漏和端口残留是本地服务最常见的两个问题。开发调试时,uvicorn 进程没有正常退出,再次启动就会提示端口被占用。遇到这种情况,先找到占用端口的进程并终止,再重新启动服务。

# Windows netstat -aon | findstr :8000 taskkill /PID 进程号 /F # Linux / macOS lsof -i :8000 kill -9 进程号

9. 常见问题与排查方法

本地部署这个流程不长,但会遇到一些典型问题。整理成表格,方便直接对照。

问题现象可能原因排查方式解决方案
启动时提示端口被占用8000 端口被其他进程使用netstat 或 lsof 查看端口占用关闭占用进程,或修改 config.py 里的 PORT
uvicorn 命令找不到没有激活虚拟环境,或依赖未安装检查命令行前是否出现 venv 前缀激活虚拟环境后重新安装 requirements.txt
运行时提示 sqlite3.OperationalError: database is locked多个进程同时写入数据库检查是否有多个 API 进程或调度器进程关掉重复进程,使用 WAL 模式,避免多进程写同一个 SQLite 文件
中文返回乱码Windows 终端编码不是 UTF-8在 Swagger 页面看响应体是否正常使用 Python 脚本调用,或把 JSON 写入文件再读取
情感分析结果全部为 neutral文本中未命中情感词典词汇打印 keywords 字段扩充 POSITIVE_WORDS 和 NEGATIVE_WORDS,或者接入更强模型
定时任务一直没有输出APScheduler 未启动,或用户日期格式不对确认 run_scheduler.py 是否在运行,检查 users 表中日期格式统一日期为 YYYY-MM-DD,确认扫描进程已启动
POST /records 返回 422JSON 字段名称或类型不匹配查看响应中的 detail 错误信息按 Pydantic 模型传字段,user_id 必须为数字
调用 /docs 无法打开服务未启动,或浏览器代理异常检查后台进程和访问地址确认 uvicorn 启动成功,访问 127.0.0.1 而不是远程地址
重启后数据丢失data 目录未生成或数据库路径错误检查 data/happiness.db 是否存在确认 config.py 中 DATA_DIR 路径正确

如果接口报 422,通常是请求 JSON 和 Pydantic 模型字段不一致。比如 RecordCreate 要求的是 user_id 和 content,你却传了 userId 和 text,校验直接失败。先看 Swagger 文档中的请求示例,再对比自己的请求体。

情感分析部分最容易让使用者误判。当前默认的情感词典只有十几个词,不可能覆盖复杂的中文表达。比如“虽然很累,但是看到他就踏实了”这句话,可能同时命中“累”和“踏实”,需要靠情绪分数加权判断。更准确的做法是把 analyzer.py 里的逻辑替换成语义模型,而不是继续堆关键词。

10. 最佳实践、合规建议与下一步

第一次运行时,不要急着录入大量数据。先创建 1 到 2 个测试用户,分别插入正向和负向情感记录,确认情感分析、祝福生成、定时扫描三个主链路都正常,再开始正式使用。

数据备份要养成习惯。SQLite 只有一个文件,直接复制 data/happiness.db 就能备份。本地服务没有自动备份机制,建议手动备份,或者写一个简单的定时复制脚本。敏感数据不要放到公开仓库,尤其是包含真实姓名、出生日期、关系标签的数据库文件。

合规层面,控制三点。第一,只在获得当事人知情同意后记录信息,不要把工具变成暗中监视他人情绪的手段。第二,推送消息要控制频率和措辞,避免给对方造成打扰。如果对方明确表示不需要,应该允许关闭对该用户的提醒。第三,这个项目不适合用来做心理状态诊断。情感分析只是辅助,真实的关系维护仍然需要面对面沟通。

下一步的扩展方向比较明确。第一,把模板引擎升级为支持多个模板随机选择,避免每次都发一模一样的文案。第二,给 analyzer.py 接入本地情感分类模型,提高语义判断能力。第三,把数据从 SQLite 换成 PostgreSQL,增加用户鉴权和多端访问,就能从个人工具升级成一个小型家庭服务。第四,增加 Web 看板,把情绪趋势用图表展示出来,让记录变得可视化。第五,设计发送确认机制,在 send_blessing.py 里加入“已发送”状态,防止同一批人重复收到祝福。

如果你也想做一套“幸福守护”小服务,建议从今天的项目结构开始:先跑通 FastAPI 接口,再加入定时任务,最后逐步增强分析和推送能力。代码不复杂,但至少能把你的关心从“心里惦记”变成一条准时的消息。你的幸福就是我最大的幸福,这句话放到代码里,就是一张人物表、一套情感分析规则、一批定时任务,以及一条不迟到的祝福。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 5:02:21

基于BP神经网络的人流量检测系统实战:从特征提取到论文答辩

简介&#xff1a;一份面向本科毕业设计的BP神经网络人流量检测系统完整资料&#xff0c;整合论文撰写与项目编码两大核心部分&#xff0c;适合计算机、自动化、智能交通等相关专业的学生参考&#xff0c;覆盖数据采集、预处理、网络设计、训练预测和结果展示的完整链条。资源共…

作者头像 李华
网站建设 2026/9/7 5:01:06

继电保护二次回路识读:从图纸到实操的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 5:00:30

PCIe 4.0 NVMe SSD实战指南:从选购、安装到系统迁移

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 4:59:35

FastAPI 文档多语言生态:LLM 驱动的自动化翻译机制与贡献指南

FastAPI 文档多语言生态&#xff1a;LLM 驱动的自动化翻译机制与贡献指南 【免费下载链接】fastapi FastAPI framework, high performance, easy to learn, fast to code, ready for production 项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi 本文基于 doc…

作者头像 李华
网站建设 2026/9/7 4:59:07

破竹樽PvE循环:层数管理与增伤节奏实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 4:58:01

猫抓资源嗅探完全指南:3 步把网页视频存进本地

猫抓资源嗅探完全指南&#xff1a;3 步把网页视频存进本地 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 想把网页上的视频存到本地&#xff0c;结…

作者头像 李华