channel_monitor_challenge.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package service
  2. import (
  3. "fmt"
  4. "math/rand/v2"
  5. "regexp"
  6. "strconv"
  7. )
  8. // monitorChallengePromptTemplate 1:1 复刻 BingZi-233/check-cx 的 few-shot 模板。
  9. const monitorChallengePromptTemplate = `Calculate and respond with ONLY the number, nothing else.
  10. Q: 3 + 5 = ?
  11. A: 8
  12. Q: 12 - 7 = ?
  13. A: 5
  14. Q: %d %s %d = ?
  15. A:`
  16. // monitorChallengeNumberRegex 提取响应中的所有整数(含负号)。
  17. var monitorChallengeNumberRegex = regexp.MustCompile(`-?\d+`)
  18. // monitorChallenge 一次 challenge 的 prompt + 期望答案。
  19. type monitorChallenge struct {
  20. Prompt string
  21. Expected string
  22. }
  23. // generateChallenge 生成一次随机算术 challenge:
  24. // - 随机两个 [monitorChallengeMin, monitorChallengeMax] 整数
  25. // - 50% 加 / 50% 减;减法用 max - min 保证非负
  26. // - 渲染 few-shot 模板
  27. //
  28. // 不强求加密随机:math/rand/v2 足够分散,避免 crypto/rand 的开销。
  29. func generateChallenge() monitorChallenge {
  30. a := randIntInRange(monitorChallengeMin, monitorChallengeMax)
  31. b := randIntInRange(monitorChallengeMin, monitorChallengeMax)
  32. if rand.IntN(2) == 0 { //nolint:gosec // 仅用于生成测试问题,无安全影响
  33. // 加法
  34. return monitorChallenge{
  35. Prompt: fmt.Sprintf(monitorChallengePromptTemplate, a, "+", b),
  36. Expected: strconv.Itoa(a + b),
  37. }
  38. }
  39. // 减法,保证非负
  40. hi, lo := a, b
  41. if lo > hi {
  42. hi, lo = lo, hi
  43. }
  44. return monitorChallenge{
  45. Prompt: fmt.Sprintf(monitorChallengePromptTemplate, hi, "-", lo),
  46. Expected: strconv.Itoa(hi - lo),
  47. }
  48. }
  49. // randIntInRange 返回 [min, max] 闭区间的随机整数。
  50. func randIntInRange(minVal, maxVal int) int {
  51. if maxVal <= minVal {
  52. return minVal
  53. }
  54. return minVal + rand.IntN(maxVal-minVal+1) //nolint:gosec
  55. }
  56. // validateChallenge 在响应文本中查找 expected 整数答案,返回是否通过校验。
  57. func validateChallenge(responseText, expected string) bool {
  58. if responseText == "" || expected == "" {
  59. return false
  60. }
  61. matches := monitorChallengeNumberRegex.FindAllString(responseText, -1)
  62. for _, m := range matches {
  63. if m == expected {
  64. return true
  65. }
  66. }
  67. return false
  68. }