OpenAI Spring AI 中的 Moderation 模型指南
1. 簡介
我們使用 Spring AI 和OpenAI 的 Moderation 模型來偵測文本中有害或敏感的內容。模型會分析輸入內容並標記出自殘、暴力、仇恨或性內容等類別。
在本教程中,我們將學習如何建立審核服務並將其與審核模型整合。
2.依賴關係
讓我們加入[spring-ai-starter-model-openai](https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-openai-spring-boot-starter)
依賴項:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
使用它,我們得到聊天客戶端,包括審核模型請求。
3.配置
接下來,我們配置 Spring AI 用戶端:
spring:
ai:
openai:
api-key: ${OPEN_AI_API_KEY}
moderation:
options:
model: omni-moderation-latest
我們已經指定了API 金鑰和審核模型名稱。現在,我們可以開始使用審核 API 了。
4. 審核類別
讓我們回顧一下可以使用的審核類別:
- 仇恨,我們可以使用此類別來偵測基於受保護特徵表達或宣揚仇恨的內容。
- 仇恨/威脅,我們可以使用此類別來偵測包括暴力威脅或嚴重傷害在內的仇恨內容。
- 騷擾,當語言騷擾、霸凌或針對個人或群體時,我們可能面臨這一類別。
- 騷擾/威脅,當騷擾包括明確的威脅或造成傷害的意圖時,我們可能面臨這個類別。
- 自殘,我們可以使用此類別來識別宣傳或描述自殘行為的內容。
- 自殘/意圖,當某人表達自殘意圖時,我們可以使用此類別。
- 自殘/指示,當內容給予自殘的指示、方法或鼓勵時,我們可能面臨這個類別。
- 性,我們可以使用此類別來標記露骨的性內容或性服務的推廣。
- 性/未成年人,我們可以使用此類別標記任何涉及未成年人的性內容,這是嚴格禁止的。
- 暴力,當內容描繪或描述死亡、暴力或身體傷害時,我們可能面臨這個類別。
- 暴力/圖形,我們可以使用此類別來檢測對傷害、死亡或嚴重傷害的生動或圖形描述。
- 非法,我們可以使用此類別來標記建議、指示或非法活動的宣傳。
- 非法/暴力,當非法內容包含暴力元素時,我們可能會面臨這個類別。
5. 建構審核服務
現在,讓我們建構審核服務。在此服務中,我們將使用使用者輸入的訊息,並使用審核模型根據不同的類別進行驗證。
5.1. TextModerationService
讓我們從建置TextModerationService
開始:
@Service
public class TextModerationService {
private final OpenAiModerationModel openAiModerationModel;
@Autowired
public TextModerationService(OpenAiModerationModel openAiModerationModel) {
this.openAiModerationModel = openAiModerationModel;
}
public String moderate(String text) {
ModerationPrompt moderationRequest = new ModerationPrompt(text);
ModerationResponse response = openAiModerationModel.call(moderationRequest);
Moderation output = response.getResult().getOutput();
return output.getResults().stream()
.map(this::buildModerationResult)
.collect(Collectors.joining("\n"));
}
}
這裡我們使用了OpenAiModerationModel
。我們發送ModerationPrompt
,其中包含我們想要審核的文本,並根據模型的響應建立結果。現在,讓我們建立buildModerationResult()
方法:
private String buildModerationResult(ModerationResult moderationResult) {
Categories categories = moderationResult.getCategories();
String violations = Stream.of(
Map.entry("Sexual", categories.isSexual()),
Map.entry("Hate", categories.isHate()),
Map.entry("Harassment", categories.isHarassment()),
Map.entry("Self-Harm", categories.isSelfHarm()),
Map.entry("Sexual/Minors", categories.isSexualMinors()),
Map.entry("Hate/Threatening", categories.isHateThreatening()),
Map.entry("Violence/Graphic", categories.isViolenceGraphic()),
Map.entry("Self-Harm/Intent", categories.isSelfHarmIntent()),
Map.entry("Self-Harm/Instructions", categories.isSelfHarmInstructions()),
Map.entry("Harassment/Threatening", categories.isHarassmentThreatening()),
Map.entry("Violence", categories.isViolence()))
.filter(entry -> Boolean.TRUE.equals(entry.getValue()))
.map(Map.Entry::getKey)
.collect(Collectors.joining(", "));
return violations.isEmpty()
? "No category violations detected."
: "Violated categories: " + violations;
}
我們取得了審核結果類別,並建立了一個對應來新增每個類別的違規結果。如果沒有違規類別,我們只需建立預設的文字回應。
5.2. TextModerationController
在建立控制器之前,讓我們建立ModerateRequest
,我們將使用它來發送文字以供審核:
public class ModerateRequest {
private String text;
//getters and setters
}
現在,讓我們建立TextModerationController
:
@RestController
public class TextModerationController {
private final TextModerationService service;
@Autowired
public TextModerationController(TextModerationService service) {
this.service = service;
}
@PostMapping("/moderate")
public ResponseEntity<String> moderate(@RequestBody ModerateRequest request) {
return ResponseEntity.ok(service.moderate(request.getText()));
}
}
在這裡,我們從ModerateRequest
獲取文字並將其發送到我們的TextModerationService
。
5.3. 測試行為
最後,讓我們測試一下我們的審核服務:
@AutoConfigureMockMvc
@ExtendWith(SpringExtension.class)
@EnableAutoConfiguration
@SpringBootTest
@ActiveProfiles("moderation")
class ModerationApplicationLiveTest {
@Autowired
private MockMvc mockMvc;
@Test
void givenTextWithoutViolation_whenModerating_thenNoCategoryViolationsDetected() throws Exception {
String moderationResponse = mockMvc.perform(post("/moderate")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"text\": \"Please review me\"}"))
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString();
assertThat(moderationResponse).contains("No category violations detected");
}
}
我們發送了一條不違反任何類別的短信,並確認服務已確認。現在,讓我們測試一下違反某些類別時的行為:
@Test
void givenHarassingText_whenModerating_thenHarassmentCategoryShouldBeFlagged() throws Exception {
String moderationResponse = mockMvc.perform(post("/moderate")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"text\": \"You're really Bad Person! I don't like you!\"}"))
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString();
assertThat(moderationResponse).contains("Violated categories: Harassment");
}
我們看到, Harassment
類別的違規行為正如預期的那樣被違反了。現在,讓我們檢查一下我們的服務是否可以審核多項違規行為:
@Test
void givenTextViolatingMultipleCategories_whenModerating_thenAllCategoriesShouldBeFlagged() throws Exception {
String moderationResponse = mockMvc.perform(post("/moderate")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"text\": \"I hate you and I will hurt you!\"}"))
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString();
assertThat(moderationResponse).contains("Violated categories: Harassment, Harassment/Threatening, Violence");
}
我們發送了一封包含多項違規行為的簡訊。如我們所見,服務回應確認了三類違規行為。
6. 結論
在本文中,我們回顧了 OpenAI 審核模型與 Spring AI 的整合。我們探索了審核類別,並建立了一項用於審核傳入文本的服務。這項服務可以作為處理使用者內容的更複雜系統的一部分。例如,我們可以將其附加到聊天審核機器人,這有助於我們控製文章下對話的品質。
與往常一樣,程式碼可在 GitHub 上取得。