AI从38万句古诗词中为你取个好名字
时间:2026-07-11 14:33
基于38万句古诗词,集成八字五行分析、FAISS向量检索与大语言模型生成,通过五格吉凶、谐音、生僻字、音律评分及五行匹配五道过滤,最终输出五个兼具文化底蕴与数理吉凶的候选名,实现取名流程自动化。
当古诗词遇上AI:从38万句诗词中取一个好名字
给新生儿取名这件事,对很多新手父母来说堪比一场“信息战”——要查八字五行、翻诗词典故、算五格吉凶、排除谐音梗,最后还得在家族群里投票。每一项单独看都不难,但叠在一起就变成了一项耗时数周的系统工程。
这个项目试图用AI把整个流程自动化:输入姓氏、性别和出生时辰,系统会从38万句古诗词中检索灵感,结合八字五行约束,调用大语言模型生成名字,再经过音律评分、五格校验和谐音过滤,最终返回5个兼顾文化底蕴和数理吉凶的候选名。
整个系统可以拆成三层来理解:数据层(诗词预处理 + 向量索引 + 康熙字典)、服务层(八字计算 → 五行分析 → 向量检索 → LLM 生成 → 多维过滤 → 综合排序)、接入层(Web H5、微信/支付宝小程序)。
架构全景
先看整体架构。系统采用经典的分层设计,从上到下依次是客户端、网关、API 路由、中间件链、核心服务、数据存储和外部 AI 服务:
接入层支持 Vue 3 H5 页面和微信/支付宝小程序,所有请求统一经过 Nginx 反代进入 FastAPI 后端。
中间件链是第一个有意思的设计。每个请求在到达业务逻辑之前,要依次通过四道关卡:反爬虫校验(UA 黑名单 + HMAC 签名)、邀请码验证、IP 速率限制(滑动窗口 + 每日配额)、免费额度检查。这个链式结构让安全策略和业务逻辑完全解耦,任何一层的规则变更都不需要改动其他部分。
核心服务层是取名流水线的主战场,下面重点展开。
取名流水线:从出生时辰到好名字
上图展示了一个名字从请求到返回的完整旅程。整个流程可以分为四个阶段:命理分析、诗词检索、LLM 生成、质量过滤。
**阶段一:命理分析 —— 搞清楚五行缺什么**
用户提交出生年月日和时辰后,系统首先用寿星天文历(sxtwl)排出八字四柱,然后分析五行强弱,确定“喜用神”。
这一步的关键在于五行强弱的量化判定。系统不是简单地数个数,而是综合月令、长生十二宫和天地干得分来计算一个综合分数:
```python
# 五行强弱判定核心逻辑
def analyze_wuxing_strength(bazi_chart):
day_master = bazi_chart.day_master_stem # 日主天干
month_order_score = get_month_shishen_score(day_master, bazi_chart)
changsheng_score = get_changsheng_score(day_master, bazi_chart)
ground_score = sum(score_stem(stem) for stem in bazi_chart.dizhi_stems)
stem_score = sum(score_stem(stem) for stem in bazi_chart.tiangan_stems)
total = month_order_score + changsheng_score + ground_score + stem_score
if total >= 3.0:
verdict = "偏旺" # 日主强,喜泄耗
elif total > -2.5:
verdict = "中和" # 平衡,喜本气
else:
verdict = "偏弱" # 日主弱,喜生扶
xi_shen = derive_fa vorable_element(verdict, day_master.wuxing)
return WuxingResult(verdict=verdict, xi=xi_shen, ji=opposite(xi_shen))
```
这里有个容易踩的坑:晚子时(23:00-24:00)的处理。传统八字学认为晚子时属于第二天,需要将日柱和时柱推进到下一天。很多八字排盘程序在这里出错,系统用 sxtwl 的 isLateZiHour 标志做了专门处理。
**阶段二:诗词检索 —— 从38万句中找灵感**
这是整个系统最有技术含量的一环。
数据准备阶段,原始诗词数据来自 chinese-poetry 开源项目,涵盖诗经、楚辞、全唐诗、宋词和四书五经。预处理管线做了三件事:繁体转简体(OpenCC)、按标点断句、过滤负面关键词(悼、亡、死、悲、愁等30多个字)。最终得到约38万条干净诗句,存入 processed_poems.json。
向量化阶段,每条诗句调用智谱AI的Embedding-3模型生成2048维向量,写入FAISS索引。为了在有限内存下跑起来,索引使用了 IndexScalarQuantizer + QT_8bit 量化,配合 IO_FLAG_MMAP 做内存映射,比float32方案节省约75%内存,且不需要把整个索引加载到RAM。
```python
# 向量检索 + 多样性采样
def search_poetry(surname, gender, wuxing_keywords, zodiac_keywords):
# 1. 构建复合查询:姓氏 + 性别 + 五行意象 + 生肖宜忌
query = f"{surname} {gender} {' '.join(wuxing_keywords)} {' '.join(zodiac_keywords)}"
embedding = zhipu_embedding(query) # 2048-dim vector
# 2. FAISS 检索 top_k * 2 条候选
candidates = faiss_index.search(embedding, top_k=100)
# 3. 分层采样,避免唐诗因语料量大而过度代表
quotas = {"诗经": 12, "楚辞": 8, "唐诗": 18, "宋词": 12, "其他": 10}
sampled = stratified_sample(candidates, quotas)
return sampled # ~50 条,来源均衡
```
多样性采样是这里的设计亮点。如果直接取FAISS的Top-K结果,由于唐诗数量远超其他朝代,检索到的诗句会严重偏向唐诗。系统采用分层配额采样,确保诗经、楚辞、唐诗、宋词各有代表,让LLM看到风格多元的灵感素材。
**阶段三:LLM生成 —— 大模型登场**
拿到诗词素材后,naming_engine 模块开始组装Prompt。这个Prompt相当“重”——它需要把八字分析结论、五行宜忌(附带示例字)、生肖取名规则、音律约束(姓氏的声母和声调信息)、以及采样到的诗句全部注入进去。
```python
# Prompt 核心结构
prompt = f"""
你是一位精通古诗词和姓名学的取名专家。
## 基本信息
姓氏:{surname}(声母:{shengmu},声调:{tone})
性别:{gender}
## 五行分析
{bazi_analysis}
喜用神:{xi_shen},宜用五行属性为「{xi_shen}」的字。
## 音律约束
姓氏声母为「{shengmu}」,名字中避免使用相同或相近声母。
姓氏声调为第{tone}声,名字应有声调变化。
## 诗词素材
{sampled_poems}
请根据以上约束,生成6个名字,每个名字需注明诗词出处。
"""
```
系统通过OpenAI兼容接口调用DeepSeek-V4 Flash(主力)或Mimo V2.5 Pro。支持SSE流式输出,使用 `<>` 分隔符协议而非增量JSON解析,让流式场景下的名字逐个呈现更加稳健。
**阶段四:质量过滤 —— 五道关卡**
LLM生成的名字不能直接用,还要经过五道过滤关卡:
第一关:五格吉凶。根据康熙字典笔画数计算天格、人格、地格、外格、总格,对照81数理吉凶表。30个“大凶”数理直接淘汰。
第二关:禁用字和谐音。检查名字中是否包含禁用字,以及是否存在不雅的谐音联想。
第三关:生僻字。排除用户可能不认识、输入法打不出的字。
第四关:音律评分。基于pypinyin检查五个维度——声母重复、声调单调、声母相近、韵母雷同等,每项违规扣分,低于60分淘汰。
```python
# 音律评分核心规则
def check_phonetics(surname, char1, char2):
score = 100
s_sm, c1_sm, c2_sm = get_shengmu(surname), get_shengmu(char1), get_shengmu(char2)
s_tone, c1_tone, c2_tone = get_tone(surname), get_tone(char1), get_tone(char2)
if s_sm == c1_sm: score -= 20 # 姓与名同声母
if c1_sm == c2_sm: score -= 15 # 两字同声母
if s_tone == c1_tone == c2_tone: score -= 25 # 三字同声调
if are_similar_groups(s_sm, c1_sm): score -= 10 # 相邻声母组
if get_yunmu(char1) == get_yunmu(char2): score -= 10 # 同韵母
return score # < 60 则淘汰
```
第五关:五行加分。对通过前面所有关卡的名字,根据字的五行属性给予加分。这里用了三级回退策略:硬编码字典 → 康熙字典查询 → 偏旁部首推断,最大化覆盖率。
最终的综合排序公式是:
```
总分 = 音律 × 0.4 + 五格 × 0.3 + 诗词来源 × 0.2 + 五行匹配 × 0.1
```
音律权重最高(40%),体现了系统的设计理念:一个好名字首先得好听。诗词来源的时代权重也有讲究——先秦诗词(诗经、楚辞)得分100,唐代80,宋代70,鼓励系统优先引用更古老的经典。
几个值得聊的技术选型
**为什么用FAISS而不是向量数据库?** 这个项目的数据规模(38万条 × 2048维)其实不大,FAISS配合8-bit量化后单机就能跑,不需要额外部署Milvus或Pinecone这样的分布式向量数据库。IO_FLAG_MMAP让索引文件常驻磁盘按需加载,对内存友好。对于中小规模的RAG场景,FAISS仍然是性价比最高的选择。
**为什么用SSE而不是WebSocket?** 取名场景是典型的“服务端单向推送”——用户发一次请求,服务端陆续返回多个名字。SSE天然适合这种单向流,实现简单且对HTTP袋里友好(只需设置X-Accel-Buffering: no)。WebSocket的双工能力在这里是多余的。
**为什么用分隔符协议而不是流式JSON?** LLM的输出是逐token生成的,增量解析JSON既脆弱又复杂。系统让LLM用`<>`分隔每个名字块,服务端按分隔符split后逐块解析,比尝试从流中拼凑合法JSON稳健得多。
**会话缓存的设计。** 系统一次让LLM生成6个名字,但只返回前5个。第6个(以及可能的更多溢出名字)缓存在内存中的session_store里,TTL 60分钟。这支持了“换一批”的UX模式——用户不满意时可以快速获得备选,而不需要重新调用LLM。
数据管线:从原始诗词到向量索引
整个数据准备过程由三个脚本串联完成:
```
chinese-poetry/ (Git submodule, 原始数据)
│
▼ preprocess.py
processed_poems.json (38万句, ~64MB)
│
▼ vectorize.py
poetry.faiss + metadata.db (向量索引 + 元数据)
```
preprocess.py的负面关键词过滤值得一提。系统维护了一个30多个字的黑名单(悼、亡、死、悲、愁、苦、泪……),任何包含这些字的诗句都会被丢弃。这确保了取名素材的情感基调是积极向上的——毕竟没人想用一个充满悲伤意象的名字。
vectorize.py使用异步并发 + 信号量控制(asyncio.Semaphore(20))来加速Embedding生成,支持多API Key轮询和断点续传。每处理5个batch就flush一次到FAISS索引,避免内存中积累过多数据。
安全与运营
一个面向公众的AI服务不能没有安全防护。系统的中间件链实现了多层防御:
反爬虫层使用双重认证策略——Web端走Session Token(2小时TTL,绑定IP),小程序端走HMAC签名。签名算法用了双哈希方案:hash(secret:timestamp:nonce) + hash(reverse(secret:timestamp:nonce)),增加了逆向难度。
速率限制层采用IP滑动窗口 + 每日配额 + 会话冷却的三重机制,默认配置是每60秒最多5次请求、每天最多200次API调用、同一会话两次请求间隔至少30秒。
免费额度层支持按天或按终身两种模式,可以灵活配置免费体验次数。
小结
这个项目的核心价值在于把“取名”这个看似感性的过程,拆解成了一条可量化、可追溯的工程流水线。八字五行不再是玄学黑箱,而是可以计算和验证的数值;诗词检索不再是随机翻阅,而是基于语义相似度的定向搜索;质量过滤不再是人工逐条检查,而是五道自动化关卡加综合评分。
从技术栈的角度看,FAISS + DeepSeek + pypinyin + sxtwl的组合覆盖了向量检索、大模型生成、音律分析和历法计算四个维度,每个组件都各司其职。分层架构和中间件链让系统具备良好的可维护性,而多样性采样、分隔符协议、会话缓存这些细节设计则体现了工程实践中的务实思考。
如果你正在考虑构建一个类似的“传统文化 + AI”应用,希望这个项目的架构思路和技术选型能给你一些启发。
来源:https://juejin.cn/post/7660103124166410275
古诗词
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。