文章目录
又一优化措施。
安装依赖
bash
# 核心依赖:语义相似度+幻觉检测+文本处理
pip install deepeval sentence-transformers scikit-learn spacy
# 可选:中文分词(提升中文校验效果)
python -m spacy download zh_core_web_sm
示例
语义校验-基础校验
校验 AI 回答是否和标准答案 "语义等价"(比如 RAG 问答、客服回复校验)。
代码:
python
from sentence_transformers import SentenceTransformer, util
import numpy as np
# 1. 加载预训练模型(中文优先选 paraphrase-multilingual-MiniLM-L12-v2)
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
# 2. 定义待校验文本
reference = "魔搭社区是国内最大的AI开源社区,提供海量大模型和工具链" # 标准答案
prediction1 = "魔搭社区是国内头部AI开源平台,有很多大模型和开发工具" # 语义一致
prediction2 = "魔搭社区是收费的商业平台,主要做AI模型销售" # 语义不一致
# 3. 计算句向量 & 余弦相似度(0-1,越高越相似)
def semantic_similarity(text1, text2):
emb1 = model.encode(text1, convert_to_tensor=True)
emb2 = model.encode(text2, convert_to_tensor=True)
# 计算余弦相似度
similarity = util.cos_sim(emb1, emb2).item()
return round(similarity, 4)
# 4. 执行校验并输出结果
print("校验1(语义一致):", semantic_similarity(reference, prediction1)) # 输出≈0.92
print("校验2(语义不一致):", semantic_similarity(reference, prediction2)) # 输出≈0.45
# 5. 设定阈值判断是否通过(一般0.7以上为"语义一致")
threshold = 0.7
if semantic_similarity(reference, prediction1) >= threshold:
print("✅ 回答语义一致,校验通过")
else:
print("❌ 回答语义不一致,校验失败")
输出结果:
bash
Loading weights: 100%|██████████| 199/199 [00:00<00:00, 4055.78it/s]
BertModel LOAD REPORT from: sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2
Key | Status | |
------------------------+------------+--+-
embeddings.position_ids | UNEXPECTED | |
Notes:
- UNEXPECTED :can be ignored when loading from different task/architecture; not ok if you expect identical arch.
校验1(语义一致): 0.9093
校验2(语义不一致): 0.6829
语义校验-事实一致性/幻觉检测 todo
校验 AI 回答是否 "编造事实""偏离参考文档"(RAG 核心场景)。
语义校验-混合校验
结合「关键词规则」+「语义相似度」,既校验核心信息,又校验语义一致性。
代码:
python
import spacy
from sentence_transformers import SentenceTransformer, util
# 1. 初始化工具
nlp = spacy.load("zh_core_web_sm") # 中文NLP工具(提取实体)
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
# 2. 定义校验规则
# 规则1:必须包含核心实体(阿里云、2022、开源)
required_entities = {"阿里云", "2022", "开源"}
# 规则2:语义相似度≥0.7
similarity_threshold = 0.7
# 标准答案
reference = "魔搭社区是阿里云2022年上线的AI开源社区"
# 3. 核心校验函数
def hybrid_semantic_check(answer, reference):
# 步骤1:实体校验(提取回答中的实体)
doc = nlp(answer)
answer_entities = {ent.text for ent in doc.ents} | set(answer.split()) # 实体+关键词
missing_entities = required_entities - answer_entities
entity_pass = len(missing_entities) == 0
# 步骤2:语义相似度校验
emb1 = model.encode(reference, convert_to_tensor=True)
emb2 = model.encode(answer, convert_to_tensor=True)
similarity = util.cos_sim(emb1, emb2).item()
similarity_pass = similarity >= similarity_threshold
# 步骤3:综合判断
total_pass = entity_pass and similarity_pass
# 返回详细结果
return {
"实体校验": {"通过": entity_pass, "缺失实体": list(missing_entities)},
"语义相似度": {"分数": round(similarity, 4), "通过": similarity_pass},
"综合校验": "通过" if total_pass else "失败"
}
# 4. 测试不同回答
answer1 = "阿里云2022年推出了魔搭这个AI开源社区" # 全符合
answer2 = "腾讯2023年上线了魔搭社区" # 实体错误
answer3 = "魔搭社区是免费的AI平台" # 实体缺失
# 5. 执行校验
print("回答1校验结果:", hybrid_semantic_check(answer1, reference))
print("回答2校验结果:", hybrid_semantic_check(answer2, reference))
print("回答3校验结果:", hybrid_semantic_check(answer3, reference))
输出结果:
bash
Loading weights: 100%|██████████| 199/199 [00:00<00:00, 4214.34it/s]
BertModel LOAD REPORT from: sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2
Key | Status | |
------------------------+------------+--+-
embeddings.position_ids | UNEXPECTED | |
Notes:
- UNEXPECTED :can be ignored when loading from different task/architecture; not ok if you expect identical arch.
回答1校验结果: {'实体校验': {'通过': False, '缺失实体': ['开源', '阿里云', '2022']}, '语义相似度': {'分数': 0.9711, '通过': True}, '综合校验': '失败'}
回答2校验结果: {'实体校验': {'通过': False, '缺失实体': ['开源', '阿里云', '2022']}, '语义相似度': {'分数': 0.6133, '通过': False}, '综合校验': '失败'}
回答3校验结果: {'实体校验': {'通过': False, '缺失实体': ['开源', '阿里云', '2022']}, '语义相似度': {'分数': 0.6621, '通过': False}, '综合校验': '失败'}