如何利用Dify實現問答系統的高效內容審查?含源碼解析與實戰優化指南 原創
背景
在當今AI應用蓬勃發展的時代,內容安全與合規性已成為開發者不可忽視的重要環節。比如用戶在客服場景中,可以通過敏感詞審查過濾用戶的辱罵性語言,并返回預設的禮貌回復。
Dify作為一款開源的大語言模型應用開發平臺,其內置的敏感詞審查機制為開發者提供了強大的內容安全保障。本文將深入解析Dify的敏感詞審查模塊(moderation)的工作原理,并通過源碼分析揭示其實現細節,幫助開發者更好地理解和應用這一功能。
dify 如何開啟敏感詞審查
要開啟敏感詞審查,需要在右下側的功能管理界面進行開啟:
dify 提供了三種敏感詞審查的策略:
- 通過openai 的 moderation(審核) 模型
- 通過關鍵詞
- 通過自定義的api擴展
審查可以配置兩個維度:
- 審查用戶輸入
- 審查模型輸出
調用 OpenAI Moderation API
OpenAI 和大多數 LLM 公司提供的模型,都帶有內容審查功能,確保不會輸出包含有爭議的內容,比如暴力,性和非法行為。
from openai import OpenAI
client = OpenAI()
response = client.moderations.create(
model="omni-moderation-latest",
input="...text to classify goes here...",
)
print(response)
下面是一個完整的輸出示例,其中輸入是來自戰爭電影的單個幀的圖像。該模型正確預測了圖像中的暴力指標,暴力類別得分大于0.8:
{
"id": "modr-970d409ef3bef3b70c73d8232df86e7d",
"model": "omni-moderation-latest",
"results": [
{
"flagged": true,
"categories": {
"sexual": false,
"sexual/minors": false,
"harassment": false,
"harassment/threatening": false,
"hate": false,
"hate/threatening": false,
"illicit": false,
"illicit/violent": false,
"self-harm": false,
"self-harm/intent": false,
"self-harm/instructions": false,
"violence": true,
"violence/graphic": false
},
"category_scores": {
"sexual": 2.34135824776394e-7,
"sexual/minors": 1.6346470245419304e-7,
"harassment": 0.0011643905680426018,
"harassment/threatening": 0.0022121340080906377,
"hate": 3.1999824407395835e-7,
"hate/threatening": 2.4923252458203563e-7,
"illicit": 0.0005227032493135171,
"illicit/violent": 3.682979260160596e-7,
"self-harm": 0.0011175734280627694,
"self-harm/intent": 0.0006264858507989037,
"self-harm/instructions": 7.368592981140821e-8,
"violence": 0.8599265510337075,
"violence/graphic": 0.37701736389561064
},
"category_applied_input_types": {
"sexual": [
"image"
],
"sexual/minors": [],
"harassment": [],
"harassment/threatening": [],
"hate": [],
"hate/threatening": [],
"illicit": [],
"illicit/violent": [],
"self-harm": [
"image"
],
"self-harm/intent": [
"image"
],
"self-harm/instructions": [
"image"
],
"violence": [
"image"
],
"violence/graphic": [
"image"
]
}
}
]
}
在dify 中,可以選擇審查輸入或者輸出內容,當審查被判斷為不通過時就會你設置的輸出預設的回復內容。
OpenAI Moderation API
自定義關鍵詞
開發者可以自定義需要審查的敏感詞,比如把“kill”作為關鍵詞,在用戶輸入的時候作審核動作,要求預設回復內容為“The content is violating usage policies.”可以預見的結果是當用戶在終端輸入包含“kill”的語料片段,就會觸發敏感詞審查工具,返回預設回復內容。
Keywords
自定義拓展
不同的企業內部往往有著不同的敏感詞審查機制,企業在開發自己的 AI 應用如企業內部知識庫 ChatBot,需要對員工輸入的查詢內容作敏感詞審查。為此,開發者可以根據自己企業內部的敏感詞審查機制寫一個 API 擴展,具體可參考 敏感內容審查,從而在 Dify 上調用,實現敏感詞審查的高度自定義和隱私保護。
Moderation Settings
dify敏感詞審查模塊解析
Dify的moderation模塊采用工廠模式設計,提供了靈活多樣的審核策略,開發者可以根據實際需求定制審核流程。整個模塊的核心架構如下:
ModerationFactory - 審核工廠類
作為模塊的核心入口,ModerationFactory負責根據配置創建具體的審核實例。通過工廠模式,Dify實現了審核策略的靈活切換和擴展。
class ModerationFactory:
__extension_instance: Moderation
def __init__(self, name: str, app_id: str, tenant_id: str, config: dict) -> None:
extension_class = code_based_extension.extension_class(ExtensionModule.MODERATION, name)
self.__extension_instance = extension_class(app_id, tenant_id, config)
s
def moderation_for_inputs(self, inputs: dict, query: str = "") -> ModerationInputsResult:
"""
Moderation for inputs.
After the user inputs, this method will be called to perform sensitive content review
on the user inputs and return the processed results.
:param inputs: user inputs
:param query: query string (required in chat app)
:return:
"""
return self.__extension_instance.moderation_for_inputs(inputs, query)
def moderation_for_outputs(self, text: str) -> ModerationOutputsResult:
"""
Moderation for outputs.
When LLM outputs content, the front end will pass the output content (may be segmented)
to this method for sensitive content review, and the output content will be shielded if the review fails.
:param text: LLM output content
:return:
"""
return self.__extension_instance.moderation_for_outputs(text)
工廠類主要提供兩個核心方法:
- ?
?moderation_for_inputs()?
?:執行輸入內容審核 - ?
?moderation_for_outputs()?
?:執行輸出內容審核
Moderation - 審核基類
作為所有具體審核類的基類,Moderation定義了審核的基本規范和通用邏輯
class Moderation(Extensible, ABC):
module: ExtensionModule = ExtensionModule.MODERATION
@abstractmethod
def moderation_for_inputs(self, inputs: dict, query: str = "") -> ModerationInputsResult:
raise NotImplementedError
@abstractmethod
def moderation_for_outputs(self, text: str) -> ModerationOutputsResult:
raise NotImplementedError
基類強制所有子類必須實現輸入輸出審核方法,確保了審核接口的一致性。
Moderation 實現類
KeywordsModeration - 關鍵詞審核類
這是Dify內置的本地敏感詞審查方案,通過匹配預設的敏感關鍵詞來檢測內容是否違規:
class KeywordsModeration(Moderation):
# 定義此審核類型的名稱
name: str = "keywords"
@classmethod
def validate_config(cls, tenant_id: str, config: dict) -> None:
"""
驗證關鍵詞審核的配置數據
確保配置具有正確的結構并滿足要求
參數:
tenant_id (str): 工作區/租戶ID
config (dict): 要驗證的配置數據
異常:
ValueError: 如果任何驗證檢查失敗
"""
# 首先驗證基本的輸入/輸出配置結構
cls._validate_inputs_and_outputs_config(config, True)
# 檢查配置中是否提供了關鍵詞
if not config.get("keywords"):
raise ValueError("keywords is required")
# 驗證關鍵詞字符串的總長度
if len(config.get("keywords", [])) > 10000:
raise ValueError("keywords length must be less than 10000")
# 按換行符分割關鍵詞并驗證行數
keywords_row_len = config["keywords"].split("\n")
if len(keywords_row_len) > 100:
raise ValueError("the number of rows for the keywords must be less than 100")
def moderation_for_inputs(self, inputs: dict, query: str = "") -> ModerationInputsResult:
flagged = False
preset_response = ""
if self.config is None:
raise ValueError("The config is not set.")
# 僅在配置中啟用輸入審核時繼續
if self.config["inputs_config"]["enabled"]:
# 獲取觸發審核時要使用的預設響應
preset_response = self.config["inputs_config"]["preset_response"]
# 如果提供了查詢,將其添加到具有特殊鍵的輸入中
if query:
inputs["query__"] = query
# 處理關鍵詞 - 按換行符分割并過濾空條目
keywords_list = [keyword for keyword in self.config["keywords"].split("\n") if keyword]
# 檢查是否有任何輸入值違反關鍵詞
flagged = self._is_violated(inputs, keywords_list)
# 返回審核結果
return ModerationInputsResult(
flagged=flagged,
actinotallow=ModerationAction.DIRECT_OUTPUT,
preset_respnotallow=preset_response
)
def moderation_for_outputs(self, text: str) -> ModerationOutputsResult:
flagged = False
preset_response = ""
if self.config is None:
raise ValueError("The config is not set.")
# 僅在配置中啟用輸出審核時繼續
if self.config["outputs_config"]["enabled"]:
# 處理關鍵詞 - 按換行符分割并過濾空條目
keywords_list = [keyword for keyword in self.config["keywords"].split("\n") if keyword]
# 檢查文本是否違反任何關鍵詞(包裝在字典中以保持一致性)
flagged = self._is_violated({"text": text}, keywords_list)
# 獲取觸發審核時要使用的預設響應
preset_response = self.config["outputs_config"]["preset_response"]
# 返回審核結果
return ModerationOutputsResult(
flagged=flagged,
actinotallow=ModerationAction.DIRECT_OUTPUT,
preset_respnotallow=preset_response
)
def _is_violated(self, inputs: dict, keywords_list: list) -> bool:
"""
檢查任何輸入值是否包含禁止的關鍵詞
參數:
inputs (dict): 要檢查的輸入數據
keywords_list (list): 禁止的關鍵詞列表
返回:
bool: 如果在任何輸入值中找到任何關鍵詞則為True,否則為False
"""
# 檢查每個輸入值是否包含關鍵詞
return any(self._check_keywords_in_value(keywords_list, value) for value in inputs.values())
def _check_keywords_in_value(self, keywords_list: Sequence[str], value: Any) -> bool:
"""
檢查單個值中是否存在任何關鍵詞
通過將值和關鍵詞轉換為小寫來執行不區分大小寫的比較
參數:
keywords_list (Sequence[str]): 禁止的關鍵詞列表
value (Any): 要檢查的值(轉換為字符串)
返回:
bool: 如果在值中找到任何關鍵詞則為True,否則為False
"""
# 將值轉換為字符串并檢查每個關鍵詞(不區分大小寫)
return any(keyword.lower() in str(value).lower() for keyword in keywords_list)
關鍵詞審核的特點:
- 完全本地化運行:不依賴外部服務,隱私性好
- 響應速度快:簡單的字符串匹配,性能高效
OpenAIModeration - OpenAI審核類
對于需要更智能識別的場景,Dify集成了OpenAI的內容審核API :
class OpenAIModeration(Moderation):
name: str = "openai_moderation"
def _is_violated(self, inputs: dict):
text = "\n".join(str(inputs.values()))
model_manager = ModelManager()
model_instance = model_manager.get_model_instance(
tenant_id=self.tenant_id,
provider="openai",
model_type=ModelType.MODERATION,
model="text-moderation-stable"
)
return model_instance.invoke_moderation(text=text)
OpenAI審核的優勢:
- 語義理解:能識別變體、諧音等復雜形式的違規內容
- 多維度檢測:可識別仇恨、暴力、色情、自殘等多類違規
- 多語言支持:支持多種語言的敏感內容識別
總結
在實際應用場景中,我傾向于采用一套精細化的審查優化策略。這套策略是經過多次實踐和反饋調整而得來的,它既考慮到了效率問題,又兼顧到了準確性和靈活性。
- 多級審核策略:結合關鍵詞匹配和AI審核,先本地快速過濾,再AI深度分析
- 上下文感知:對于某些專業場景,配置上下文相關的敏感詞白名單。通過?
?{{variable}}?
?語法注入會話變量(如用戶角色、領域標簽),這些變量可被審查模塊調用,實現動態規則切換。 - 設置分數閾值(如?
?score_threshold=0.8?
?),避免誤判近似詞
本文轉載自???AI 博物院??? 作者:longyunfeigu
