这个问题看似小,其实很“工程”
“祝福语生成”这种场景,一旦你做过一版微调(比如「码上拜年」),很快就会有人问下一句:
“既然我们有大量祝福语样本,那要不要上 RAG?用向量数据库检索几条相似的,再让模型改写一下,会不会更稳?”
这句话听起来很对,甚至非常工程化:
有数据 → 入库 → 检索 → 生成,闭环就有了。
但祝福这件事偏偏很刁钻:它不是知识问答,不是事实查证,更不是“召回越多越好”。
它靠的是“分寸”“关系”“语气”,靠的是你能不能让对方觉得:这句话是写给我的,而不是从哪里抄来的。
所以这篇文章我想把话说得直一点:
RAG 做祝福检索不是不能做,但你得先搞清楚:你在用 RAG 解决什么问题。
否则向量库越建越大,TopK 越调越高,最后效果反而会退回“模板拼贴”。
一、先给结论:RAG 做祝福检索“靠谱吗”?取决于你要检索什么
如果你说的“祝福检索”是:
把一堆祝福语当作语料,检索几条相似的祝福,然后让模型改写成新的祝福。
这种做法在工程上能跑通,但大概率会遇到三个问题:
-
结果越来越像“模板拼接”
-
风格一致性很难保证(尤其多来源语料)
-
你以为在检索“走心”,其实只是在检索“像祝福的句子”
如果你说的“祝福检索”是:
检索与对象相关的事实材料,比如关系、经历、共同回忆、客户项目细节、最近发生的事,再让模型基于这些事实写祝福。
那 RAG 会非常靠谱,而且往往是“走心”的关键来源。
一句话总结:
RAG 更适合检索“你们之间发生过什么”,不适合检索“别人怎么写祝福”。
二、祝福场景的本质:缺的不是信息,而是“表达偏好”
春节祝福这种任务,你要的输出不是“正确答案”,而是“合适的说法”。
通用模型的问题也不是“不知道祝福怎么写”,而是它默认会落到一种安全平均的表达区:
-
词很对
-
句式很全
-
但没有你们的关系,没有具体性,没有“这句话只属于你”的感觉
微调(SFT/LoRA)擅长做的是:把“合适的说法”变成默认选项,让模型在生成空间里优先选中更自然、更贴近场景的表达方式。
而 RAG 擅长做的是:把模型看不到的信息补进来。
所以当你用 RAG 去检索祝福语本身,你其实在做一件有点别扭的事:
你用“信息补全工具”,去解决“表达偏好问题”。
这也是很多祝福 RAG 项目看起来很努力,结果却越来越像模板的原因。
三、RAG 检索祝福语为什么容易翻车:三种典型失败模式
风格混杂,模型被迫折中
向量库里祝福语来源可能很杂:公众号、朋友圈、公司模板、古风、网络梗、商务措辞。
检索出来的 TopK 往往不是同一语气体系下的东西,模型拿到这些证据后只能“强行综合”。
你最后得到的文本常见特征是:
-
前两句像微信聊天
-
后两句像正式贺电
-
中间突然插个网络梗又不搭
这不是模型水平不行,是你给它的证据本身就不一致。
相似度检索到的是“结构相似”,不是“关系相似”
向量检索很擅长找“语义相近”的句子,但祝福语里大量是固定结构:
“新春到 / 祝你 / 事业顺利 / 阖家幸福”
这类句子在 embedding 空间里会聚成一团,你检索到的往往是“同款结构”,而不是“适合你们关系”的表达。
换句话说:
你检索到的相似,是“像祝福”,不是“像你”。
召回越多,越像拼贴,越容易胡说
很多人遇到“不够走心”第一反应是把 TopK 调大:5 不够就 10,10 不够就 20。
但祝福场景里,TopK 变大几乎一定会带来:
-
重复信息增多
-
风格冲突增多
-
模型综合压力变大
-
自信但空泛的句子变多
最终输出常常更像“堆辞藻”,而不是更走心。
四、那 RAG 在祝福场景到底该怎么用才对
我更建议把祝福 RAG 的定位改成四个字:
检索“关系证据”。
你不要把向量库当成“祝福语仓库”,而要当成“关系记忆库”,里面存的应该是:
-
称呼偏好(对方喜欢被怎么叫)
-
关系类型(同事/客户/家人/恋人)
-
共同经历(项目、旅行、加班、某次饭局)
-
近期事件(换工作、升职、搬家、孩子出生)
-
对方兴趣点(马术、摄影、某个梗)
-
你们的沟通风格(爱玩笑、讨厌肉麻、喜欢简短)
这些东西才是“走心”的燃料。
而“怎么说得合适”,交给微调后的模型去做。
五、向量数据库实战:做一个“祝福关系记忆库”的最小可用方案
这里我给一个尽量实操的流程,不追求完美,但你照着做能跑起来,效果也更容易靠谱。
数据结构:不要只存文本,至少把元信息带上
你要检索的是“哪些经历最相关”,而不是“哪句祝福最像”。所以每条记录最好长这样:
-
person_id / contact_id
-
relationship(客户/同事/家人…)
-
scene(拜年/感谢/道歉/祝贺…)
-
time(时间戳)
-
content(事件描述或事实)
-
tags(马术/项目/旅行/加班…)
向量化:embedding 用来找“相关经历”,不是找“祝福模板”
你可以用中文向量模型(比如 bge 系列)做 embedding。下面是一个示意代码(以 sentence-transformers 风格写,方便理解)。
from sentence_transformers import SentenceTransformer
import numpy as np
model = SentenceTransformer("BAAI/bge-small-zh-v1.5")
def embed(texts):
vecs = model.encode(texts, normalize_embeddings=True)
return np.array(vecs, dtype="float32")
memories = [
"去年北京项目合作,你对细节的关注和高效决策让我印象深刻",
"年底饭局聊到马术运动,你分享了不少见解",
"大学室友,认识八年,一起通宵赶作业,毕业后每年约一次旅行",
]
vectors = embed(memories)
注意我这里用了 normalize_embeddings=True,是为了后续用 cosine/inner product 更稳定,少被向量长度影响。
建库:先用 FAISS 跑通,再考虑 Milvus/pgvector
如果你是从 0 到 1 验证,建议先 FAISS,因为简单,足够快。
import faiss
dim = vectors.shape[1]
index = faiss.IndexFlatIP(dim) # 归一化向量 + IP 等价 cosine
index.add(vectors)
def search(query, topk=5):
q = embed([query])
scores, ids = index.search(q, topk)
return [(int(i), float(s)) for i, s in zip(ids[0], scores[0])]
print(search("给王总发拜年祝福,提到北京项目合作和马术", topk=3))
跑通以后你再决定要不要上:
-
Milvus(更偏向规模化、多租户、运维复杂)
-
pgvector(更贴近业务系统,SQL 友好)
-
Elasticsearch kNN(如果你本来就用 ES)
祝福场景通常不是吞吐瓶颈,更多是“检索到什么”的问题。
检索策略:TopK 不是越大越好,宁可少而准
祝福场景里,你召回的“关系证据”越多,模型越容易被迫总结成套话。
所以我的建议是:
-
TopK 小一点,比如 3~5
-
做去重(同一事件的多次记录合并)
-
做时间衰减(最近一年权重更高)
你可以用一个很朴素的打分融合:
import math
from datetime import datetime
def time_decay(days_ago, half_life=180):
# 半衰期 180 天
return 0.5 ** (days_ago / half_life)
def fused_score(similarity, days_ago):
return similarity * time_decay(days_ago)
生成提示:让模型“基于证据写”,而不是“参考模板改写”
把检索到的关系证据作为“事实素材”,提示模型不要编造新的经历。
System:
你是一位有分寸感的祝福语助手。只使用用户提供的信息与证据要点,不要虚构经历。
User:
祝福对象称呼:王总
关系:客户/服务关系
风格:商务得体风
字数:50-100字
证据要点:
- 去年北京项目合作,对方对细节关注、高效决策
- 年底饭局聊到马术,对方分享见解
请写一段微信拜年祝福。
这一步非常关键:你用 RAG 的方式把“走心素材”喂进去,而不是把“别人的祝福句子”喂进去。
六、要不要把祝福语本身也入库?可以,但别当主力
如果你一定要做“祝福语检索库”,建议把它当作“辅助”,并加两道护栏:
-
先按风格分库或分区(商务/轻松/科技梗/传统)
-
检索出来的祝福只给模型当“灵感片段”,不能当证据
-
让模型必须引用“关系证据”,模板只能做润色
否则你会非常稳定地走向:模板拼贴、风格混杂、越写越像公众号。
七、怎么判断“RAG 做祝福检索到底靠不靠谱”:三条评估线
祝福是主观任务,但评估不是完全没法做,你至少要盯住三个维度:
- 事实一致性
是否出现未提供的经历、捏造细节、关系写错
- 风格一致性
同一风格下输出是否稳定,是否出现突然正式或突然玩梗
- 可直接发送率
用户是否愿意不改就发,或改动幅度是否很大(这比任何指标都诚实)
如果你的 RAG 方案让“可直接发送率”下降,那它基本就不靠谱,哪怕召回看起来很强。
八、工程取舍:什么时候“RAG + 向量库”值得做,什么时候不值得
值得做的情况
- 你有真实的关系素材来源
CRM、聊天摘要、项目纪要、活动记录
- 你要“个性化”,而不是“更华丽”
走心的关键是具体经历,而不是更漂亮的辞藻
- 你在意隐私与合规
你宁可让模型少说一点,也不让它胡编经历
不太值得做的情况
- 你只有一堆祝福语模板,没有关系素材
你检索到的只会是“像祝福”的句子
- 你希望靠 RAG 解决风格问题
风格一致性更像微调的职责,不是检索的职责
- 你准备靠 TopK 把效果堆上去
祝福场景里这招副作用很大
如果你的目标是让祝福既走心又稳定,比较靠谱的路线往往是:用向量数据库做“关系证据召回”,用微调把风格和分寸塑成默认值。像LLaMA-Factory Online这种能快速跑通微调闭环的平台,更适合把“表达偏好”先稳住,再去接 RAG 做个性化证据补全,否则你很容易把检索当成风格修补工具,越修越乱。
总结:RAG 做祝福检索靠谱不靠谱,关键看你检索的是“人”,还是“句子”
我最后用一句话收住:
RAG 在祝福场景里不是不靠谱,而是你不能让它去检索“祝福本身”。
它更适合检索“你们的关系”,把走心的素材找出来;而“怎么说得合适”,更适合用微调去解决。