15

逐字返回的内容如何做关键词屏蔽

 2 years ago
source link: https://www.v2ex.com/t/954296
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  程序员

逐字返回的内容如何做关键词屏蔽

  brader · 17 小时 11 分钟前 · 3058 次点击
用过 chatgpt 产品的都知道,返回内容都是那种打字机效果,逐字返回显示的。
那么问题来了,这种如何做关键词屏蔽呢?
好像服务端做比较困难,因为关键词有多个字的,如果服务端等整句话检测完再返回内容给前端的话,体验就太糟糕了。
我目前能想到的兼顾原有用户体验的方式是放在客户端来检测屏蔽关键字,客户端每次接收到服务端的返回的字,就拼接之前接收到的内容,检测关键字,检测到了,就把展示的内容屏蔽替换。这样就还是有打字机的实时效果。

不知道各位有没有更好的实现想法,欢迎讨论
69 条回复    2023-07-06 00:56:10 +08:00
yolee599

yolee599      17 小时 5 分钟前

整段接收完,检测完,再逐字返回给客户端。至于延迟,都做检测了还考虑啥延迟
brader

brader      17 小时 3 分钟前

@yolee599 这样就太糟糕了啊,你知道一篇长回答的话,chatgpt 多久返回完吗,有超过 1 分钟的,如果用户每问个问题,都要等几十秒甚至 1 分钟以上,那完全没用户体验可言了
yougg

yougg      16 小时 59 分钟前

那依靠文字排版的藏头藏尾你怎么流式处理?
brader

brader      16 小时 54 分钟前

@yougg 什么?没听懂你表达的意思,返回给用户的答案,是 chatgpt 的回答啊,chatgpt 又不是人,不会主动搞事情、搞伪装的,只是你知道国情的,有时候有些问题比较敏感,不允许用户问,和给用户展示答案的。
ChefIsAwesome

ChefIsAwesome      16 小时 53 分钟前

你自己控制每收 n 个字,审查下,不就完事了。
InDom

InDom      16 小时 51 分钟前   ❤️ 1

反过来,把接收到的字(尾)去关键词列表匹配(头)。

如果有匹配到,保留到缓冲区,继续接收下一个字,如果没匹配到,输出到客户端,清空缓冲区。

需要处理的是这样的情况,
文字流是:锄禾日当午
而黑名单列表有:禾日苗,日当午
时,因为匹配到一部分“禾日” 最后没有命中而导致没有去匹配“日当午”
JiangZeYi

JiangZeYi      16 小时 50 分钟前 via Android   ❤️ 4

chatgpt 加一句只回答符合 XX 国情的答案
dobelee

dobelee      16 小时 50 分钟前

比较难啊,后面的内容还没计算完,你不可能知道是否有 g 点。
非要做只能加一个代理层,每接收到一段文字就检查并替换 g 点,然后再流式丢出去。缺点就是性能会大幅降低,很多算法优化派不上用场。
感概一下墙锅现状。
putyy

putyy      16 小时 49 分钟前

1.你说的这种也可以在服务端做检查
2.先逐字返回客户端,等 chatgpt 返回完,服务端做好检查,然后在返给客户端覆盖已有内容
brader

brader      16 小时 47 分钟前

@ChefIsAwesome 每收 N 个字审查,也不是不行,体验也还能接受,但是检测效果会有影响的,举个例子:
假设“科学上网”这四个字是关键字,假如我服务端设定每接收 5 个字检测一次,那可能发生我接收到“xx 科学上”,这个没违规,下发给客户端,接着接收到“网 xxxx”,这个也没违规,下发给客户端。

不知道这个概率高不高,高的话,检测效果就太差了
brader

brader      16 小时 45 分钟前

@putyy 那你说的这种方式,在页面表现上和我说的方案的页面表现是一样的,所以我就还不如在客户端做检测,效率还高
milukun

milukun      16 小时 44 分钟前

本地敏感词库,可以设置每次检测最近的 10 个字,在敏感词库里的就打 * 号隐藏
全部返回完之后再跑一次在线 API (阿里什么的之类的),获得最终屏蔽结果
本地的可以超严格,防止露馅,最后以 api 为准显示
brader

brader      16 小时 44 分钟前

@InDom 理解了一部分你的意思,但是又没完全理解,你看看我 10 楼的回答,你表达的意思是不是和我说的,可能检测效果不太准确?
milukun

milukun      16 小时 43 分钟前

检测最近 10 个字是为了效率考虑,如果每出一个字都要全文分词或者查询,本地有个 4 万左右敏感词的话,后期就会很卡。(实测)
本地敏感词可以在 git 上找,有个什么 tx 离线词库的
brader

brader      16 小时 39 分钟前

@milukun 我们可能不会搞很高端的检测,就是关键词匹配就行了,所以检测服务自己很容易做。
关键是分段切割来检测,有可能出现漏检的问题,概率问题,你看看我 10 楼回答的,我大概就这个意思
yinmin

yinmin      16 小时 39 分钟前

从 chatgpt 流式获取,定期审核,模拟打字机效果流式发送给客户端

(1) 收到标点符号的 data 数据包或者累计 20 个 data 数据包,就去做一次内容审核(从会话头部到截断位置的内容)。一次回答会做多次内容审核的。
(2) 审核后的回复内容(data 数据包)写入缓冲区
(3) 每隔 20ms 从缓冲区取一个 data 数据包发给客户端 (模拟打字机效果)
brader

brader      16 小时 35 分钟前

@yinmin 分段检测比较尴尬的是会漏检,参考我 10 楼的回答
putyy

putyy      16 小时 34 分钟前

@brader 有点不一样,相当于在没有得到全部结果之前是没有做任何检测的,接受完毕再检测,再替换客户端看到的信息
kennir

kennir      16 小时 32 分钟前

关注一下,也在折腾相关的问题
brader

brader      16 小时 30 分钟前

@putyy 我说的也差不多意思,要完整再检测,客户端也可以这么做,而且自己就能直接换了,不需要通过服务端下发指令来交互替换
MartinDai

MartinDai      16 小时 29 分钟前

关键词的长度总是有限的吧,也不可能能太长,假设是 N 吧,后端做一个流式输出的桥接,里面存放 N 个字符的 buffer ,gpt 返回第 N+1 个字符以后,每接受一个字符就检查一遍关键词然后往前端输出一个字符,这样前端得到的结果也就比 gpt 晚 N 个字符
InDom

InDom      16 小时 28 分钟前

@brader #13 不一样,这个做法是有点像白名单机制,只有这个字/词一定没有在黑名单中出现时才会输出到客户端。

就是把收到的字,都认为在黑名单中,一直等明确这个字与后面接受的字不在黑名单后,才把这个字输出到客户端。

相当于你收到的每一个字,都假设后面还没有收到的字与他所组成的词就是敏感词,等收到了更多的字,发现确实没有的时候,就将这个字输出到客户端,然后继续匹配剩下缓冲区的字有没有与词库有重合。

还是我上面的例子:(括号内为未输出的缓冲区)后面的是本次接收到的字符,没有就说明没有接收()
锄:在词库中没有,安全输出
禾:命中词库:禾日苗,不输出
(禾)日:命中词库:禾日苗,不输出
(禾日)当:未命中词库,输出第一个字。
-- (日):命中词库:日当午,不输出。
(日当):命中词库:日当午,不输出。
(日当)午:全量匹配,替换,输出 ***
muskill

muskill      16 小时 13 分钟前   ❤️ 14

brader

brader      16 小时 12 分钟前   ❤️ 1

@MartinDai
@InDom 我理解你们的意思了,这个方案是挺好的,客户端感受到的仅仅是开头字慢一会出来,后面应该是连续不断的出来回答的,很棒。

我整理思路就是:
假设我系统预设关键字最长为 4 个字,那么我从 chatgpt 接收到 6 个字的话,我能 100%确定前 3 个字是否违规,不违规直接输出,后面 3 个字可能现在不违规,但是有可能和未来的字组成违规词,所以暂不能输出。。。一直以此类推,后面就是源源不断的输出前面 100%能确定的不违规词。
是这样不?大佬
MoYi123

MoYi123      16 小时 9 分钟前

收 10 个字, 全检查一下, 没问题返回前 5 个, 剩下 5 个, 然后再等到有 10 个字的时候再检查, 再根据情况把 10,5 这 2 个数字调整一下不就好了.
christin

christin      16 小时 8 分钟前

可以试试分段检查或者分句检查,检测到段落标记或者句号就开始丢进去审核,审核完再返回。
完整的一段或者一句不会出现你 10l 说得无法命中关键字的情况,一般都是一句话说完了就结束了,除非有人发现了你的检测方法让 ChatGPT 在中间加上段落标记或者句号。
Felldeadbird

Felldeadbird      16 小时 6 分钟前

1. 后端设定 N 字 返回敏感检测。

2. 客户端接收到后续内容后,将当前输出区域中看到的所有文字发到敏感库,做全文敏感检测。
brader

brader      16 小时 5 分钟前

@MoYi123
@christin 嗯,这个思路可以,和前面 2 个大佬的思路差不多。我现在顺着这个思路思考接下来的问题了,我在思考和测试,在大流量下,关键字多了,这样分段频繁检测,服务器 CPU 能不能承受住
brader

brader      16 小时 4 分钟前

@Felldeadbird 嗯,在客户端做的话,和我开始说的差不多就是这个意思,这样服务端没有压力,只要客户端从服务端更新拉取关键字就行了
GTim

GTim      16 小时 2 分钟前

chain filter 啊... 你把你的过滤器嫁接上游的逐字和往下游也逐字发啊,类似于命令行下载百分比和回退效果。

[0:'这是正常获取到的,直接追加即可']
[-3: ‘客户端收到文字后,删除最后 3 个字,然后追加给予的内容']
rockyliang

rockyliang      15 小时 58 分钟前 via iPhone

@brader 回复 2 楼,其实现实中微信聊天,对方一般也是等全部内容输入完了才会发给你的,所以换到 chatgpt ,等全部内容接收完后,做一次检测再发送给用户这个我觉得问题不大。关键点是你要提醒用户你正在打字,比如“程序正在生成回答,已经生成了 xx 个字,请耐心等待”,总之就是不要让用户觉得你的程序卡住了
u20237

u20237      15 小时 53 分钟前 via Android

前端做这个事比较合适。
MoYi123

MoYi123      15 小时 53 分钟前

@brader 如果屏蔽词是用 ac 自动机的话, 可以给当前状态加一个深度, 就能精确地判断哪些部分是绝对安全, 哪些部分是不确定的.
u20237

u20237      15 小时 50 分钟前 via Android

dig google.con

echo 127.0.0.1 is google.com

貌似后端
brader

brader      15 小时 47 分钟前

@rockyliang 表面上看和微信类似,但是实际上还是有所不同的,用户心理也有所不同,主要是有些长回答要等待时间太久了,几十秒甚至 1 分钟以上。
微信和别人聊天,我知道别人没有义务实时回答我,我会切开去干别的事情。
但是 chatgpt 这种实时问答应用,用户的忍耐度低的多,这时候的用户,是渴望急于获取到答案的,让用户等待 1 分钟以上,太漫长了,就好比你去搜搜索引擎,如果搜索引擎等待 1 分钟再出结果给你,你肯定会抛弃他。
除了体验不好一个原因,另一个原因是用户有选择的余地,比如百度要 1 分钟返回结果,360 搜索却秒回,那你肯定抛弃百度了。
我做的 chatgpt 应用也是同理的,你为了检测等 1 分钟,但是别家做的,却可以实时返回,高下立判
jiaoery

jiaoery      15 小时 45 分钟前   ❤️ 1

我记得 chatgpt 上是可以加 prompt 屏蔽规则的,这样在生产端就给你屏蔽了,不用自己再搞一次;
brader

brader      15 小时 44 分钟前

@jiaoery 这是个新鲜玩意,我去试试
Admstor

Admstor      15 小时 42 分钟前

如果你做的不是套皮产品,那么自然应该在语料库,算法上调节,保证党性

如果你特么是套皮产品,我只能说,贱不贱阿
fzls

fzls      15 小时 30 分钟前

我前几天使用 bing 问了一个问题(中国朝鲜族与韩国人的关系),bing 先是一个个输出答案,最后输出完的时候,他应该是进行了检测,发现可能有政治风险,就立刻把答案替换成当前问题无法解答(具体内容忘了)

我觉得可以参考下这种,不过这样的话万一用户在中途截图,然后举报就麻烦了
brader

brader      15 小时 27 分钟前

@InDom 大佬,6
brader

brader      15 小时 27 分钟前

@fzls 这种也不是不行
EminemW

EminemW      15 小时 21 分钟前 via iPhone

你这个不就是滑动窗口吗,每次都对滑动窗口中的文字做识别
harrozze

harrozze      15 小时 11 分钟前

@brader #10 这种相对来说比较可行的。收到 4 个字,然后内容检测的时候其实是收到的所有原文做检测。如果是页面或 app 产品的话,可以在返回的 json 里用个指令表明前端需要用返回的内容做完整替换,或回退多少个字以后替换,这样前段遇到你说的问题时,第一次会显示“……xx 科学上”,第二次就变成”……xx****yyy“。如果是对外提供 api 的话,就不太好办了,第三方前端就有可能不按你给的指令去替换历史内容。
xupefei

xupefei      15 小时 11 分钟前

ring buffer 上套一个 AC 自动机,buffer 容量等于最长的关键词长度。
wqhui

wqhui      15 小时 8 分钟前

@brader 用滑动窗口
brader

brader      15 小时 2 分钟前

@wqhui 嗯,初步确定用这个,考虑做到服务端还是前端
brader

brader      15 小时 2 分钟前

@harrozze 嗯,只考虑自家产品,API 不给别人用的,别人薅羊毛的,要搞事,自己被封了不关我事
gaobh

gaobh      15 小时 0 分钟前

@fzls #39 wps 内测的 AI 功能就是这样的方案,容易截图
nothingistrue

nothingistrue      14 小时 59 分钟前

逐字返回,如果不只是前端假逐字显示,而是前后端同步逐字返回,即完全的实时逐字对话,那这行为本身就是「违法」,你竟然还在这里想怎么做屏蔽。
dode

dode      14 小时 57 分钟前

撤回消息啊
harrozze

harrozze      14 小时 55 分钟前

@brader #48 那样的话就可以,返回的 json 里加个额外字段用于描述这种替换或者回退清除指令,if 有{ 先执行指令},然后再直接结果内容的追加
popvlovs

popvlovs      14 小时 48 分钟前

没有实践过,仅仅提供一个思路
如果敏感词屏蔽是通过正则来实现的话,有些正则引擎是支持 streaming mode 的,比如 hyperscan
aduangduang

aduangduang      14 小时 37 分钟前

滑动窗口啊
shyrock

shyrock      14 小时 24 分钟前

N 个字的 buf ( N=max(len(屏蔽字)),就解决了。非常直观,用不到啥理论基础。
sampeng

sampeng      13 小时 23 分钟前

而且敏感词是国内特色。理论上你用不了 gpt 服务。那既然这样了,你利用他商业化。。。去做敏感词。。是不是很搞笑。。

而且 prompt 你也可以让他把你所有的敏感词都替换成**。

比如: 所有的回答,出现[哈哈]的全部替换成**返回给我
ily433664

ily433664      13 小时 7 分钟前

按段检测
比如整个返回的内容是“abcedfg,hijklmn,opqrst”
接受到“abcedfg”后进行检测,逐字返回;前一段返回的时候,已经在接收“hijklmn”了,同理,接收完“hijklmn”进行检测,然后逐字返回
这样的话相当于延迟为最大一段话的检测时间
gkiwi

gkiwi      12 小时 27 分钟前

SSE 返回基本都是整句的,不会中间断开。琢字是前端效果~
amywlp

amywlp      12 小时 21 分钟前

直接审查问题呗,不用那么麻烦去审查答案了。
AhECbt

AhECbt      12 小时 8 分钟前

讨论这种问题就好像黑奴农场里的黑奴围在断头台前,深情的讨论如何帮助奴隶主给每个黑奴都带上一副合适的嚼子一样可笑。
zhaidoudou123

zhaidoudou123      11 小时 54 分钟前

要不提前和 gpt 说一声,让他不返回你列表里的关键词?虽然有点多就是了…
kekxv

kekxv      11 小时 43 分钟前 via iPhone

很简单啊,先求出你关键字最大长度,然后等 gpt 返回内容,超过这个数字的时候,把最前面的返回,比如最长是 5 位的关键字,你在收到大于等于五个关键字之前,都不会把数据返回给客户端,超过之后,做检测,没问题,然后把最前面的返回,剩下最后的四个,等下一个数据,如果结束了,就直接返回最后四个?
IDAEngine

IDAEngine      11 小时 21 分钟前

从 prompt 检测不就好了,问一些稀奇古怪的 prompt 直接 nop 掉。chatgpt 也是检测 prompt ,prompt 不符合规则不做处理。
Nicified

Nicified      10 小时 51 分钟前

在 API 出结果到发出前增加一段滑动窗口
Greatshu

Greatshu      9 小时 41 分钟前

审查 prompt ,但不要尝试修改 prompt ,比如要求 gpt 不要返回某些信息等,用户很容易发现。可以规定累计触发 n 次关键词后暂停使用一段时间/要求实人认证/封停账号等。
teenight

teenight      9 小时 38 分钟前

让用户自己举报
raycool

raycool      9 小时 26 分钟前

AC 状态机。
iv2ex

iv2ex      8 小时 17 分钟前

要不参考腾讯会议的语音识别?

腾讯会议从效果上是这样的:语音识别是实时的,但是会有二次修正;

比如:
主持人实时语音:锄禾日当午
语音识别实时效果:滁河日当午
然后过 1 、2 秒,会变成:锄禾日当午
chesha1

chesha1      7 小时 14 分钟前

@brader 如果你的担心是这个场景下的,可以把关键词库做细一点

假设总体内容内容是字符串 1,2,3,4...组成的

如果当前字符串 1 中的内容,作为前缀没有匹配到任何东西,就直接发送字符串 1 ,然后对于后面的同样操作

如果当前字符串 1 中的内容,匹配到可能作为敏感词的前缀的内容,就截留字符串 1 ,把字符串 1 和 2 整体再做一次检测,如果没有问题,就发送字符串 1 ,对于字符串 2 进行是否包含前缀的检测

</div


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK