feat: 添加最核心的ai审查和吐槽功能

This commit is contained in:
mei 2025-09-12 21:06:00 +08:00
parent 72591b7e2c
commit ea70179075
9 changed files with 242 additions and 0 deletions

BIN
aiComplain Executable file

Binary file not shown.

38
configs/configs.go Normal file
View File

@ -0,0 +1,38 @@
package configs
const (
DB_USERNAME = "aiCpmplain"
DB_PASSWORD = ""
DB_NAME = "aiComplain"
DB_PORT = 3306
OPEN_LIKE_URL = "http://127.0.0.1:11434/v1/chat/completions"
OPENAI_LIKE_API_KEY = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
LLM_MODEL_TINY = "qwen:4b" //用于内容审核的模型
LLM_MODEL_LARGE = "gemma3:12b" // 用于吐槽的模型
AUDIT_PROMPT_TEMPLATE = `
你是一名专业的网络内容审核员负责审核用户发布的言论内容确保其符合中国法律法规和社会道德规范你的工作是公正客观地判断内容是否可以发布
审核标准包括但不限于
违法违禁内容如毒品赌博暴力恐怖主义等
色情低俗内容
族宗教歧视内容
人身攻击侮辱诽谤内容
虚假信息或谣言
广告营销信息
暴露他人隐私的内容
请对用户输入的言论进行审核返回JSON格式结果包含
"approved"布尔值true表示通过false表示未通过
"reason"字符串未通过时的原因通过时为"无"
输出必须严格为JSON格式不要包含其他任何内容示例
{
"approved": true,
"reason": "无"
}
{
"approved": false,
"reason": "包含色情低俗内容"
}`
COMPLAIN_PROMPT_TEMPLATE = `
你是一名资深吐槽墙网站的顶级吐槽手专精于"怼天怼地嘴强王者"的尖锐"阴阳怪气十级学者"的表面客气实则刀刀致命等风格用户传入任何言论你必须创作20-50字的吐槽内容戳肺管子句句直击痛点用网络热梗或方言脏话避免直接脏话表面客气实则刀刀致命输出必须严格为JSON格式不要包含其他任何内容,尤其是反引号{"taunt": "吐槽内容"}吐槽内容必须精准在20-50不加任何其他说明`
)

7
go.mod Normal file
View File

@ -0,0 +1,7 @@
module git.mmeiblog.cn/mei/aiComplain
go 1.23.4
require github.com/go-dev-frame/sponge v1.15.1
require github.com/sashabaranov/go-openai v1.41.1 // indirect

4
go.sum Normal file
View File

@ -0,0 +1,4 @@
github.com/go-dev-frame/sponge v1.15.1 h1:I+2bWBQHqySkmG4d/K+KaYUeU37wjuiOaO6pT8dMSno=
github.com/go-dev-frame/sponge v1.15.1/go.mod h1:kTYWZQUSR5Iuu9Ur4tHC+v/1eP48W7hGxhvO6hVylNs=
github.com/sashabaranov/go-openai v1.41.1 h1:zf5tM+GuxpyiyD9XZg8nCqu52eYFQg9OOew0gnIuDy4=
github.com/sashabaranov/go-openai v1.41.1/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=

4
internal/send.go Normal file
View File

@ -0,0 +1,4 @@
package internal
// func HandleSend(message string) (string, error) {
// }

32
internal/snedAndAudit.go Normal file
View File

@ -0,0 +1,32 @@
package internal
import "git.mmeiblog.cn/mei/aiComplain/pkg/ai"
type SendAndAuditResponse struct {
Data string `json:"data"`
Message string `json:"message"`
}
func SendAndAudit(message string) (SendAndAuditResponse, error) {
AuditResponse, err := ai.SendAudit(message)
var ComplainResponse ai.ComplainMessage
if err != nil {
return SendAndAuditResponse{
Data: "",
Message: "审核失败",
}, err
}
if AuditResponse.Approved {
ComplainResponse, err = ai.SendComplain(message)
if err != nil {
return SendAndAuditResponse{
Data: "",
Message: "AI吐槽失败",
}, err
}
}
return SendAndAuditResponse{
Data: ComplainResponse.Taunt,
Message: "AI吐槽成功",
}, nil
}

13
main.go Normal file
View File

@ -0,0 +1,13 @@
package main
import (
"fmt"
"git.mmeiblog.cn/mei/aiComplain/internal"
)
func main() {
// 先写点数据测试
response, err := internal.SendAndAudit("2024级11班某女同学(🐭老鼠)于上周周五晚上在女生宿舍四处投毒,毒物为霉菌饼子,在霉菌里发现少量饼子。食用过的某同学说因为宿舍灯光暗,还以为是葱花饼。\r\n据说219(12班)宿舍三人受害严重,一人第二夜深夜直接被送回家,一人第三天下午回家,证物已上交老师,但该名女同学并无悔过之心,四处与他人就此事讲笑话,并单方面说受害同学原谅了她,事后还去各个宿舍索要食物。\r\n希望大家多加小心该名女同学其外号在学校叫为老鼠🐭可询问周围同学其真名目前在2024级的11班")
fmt.Println(response.Data, err)
}

100
pkg/ai/api.go Normal file
View File

@ -0,0 +1,100 @@
package ai
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"git.mmeiblog.cn/mei/aiComplain/configs"
)
// 定义请求格式(兼容 OpenAI 格式)
type ChatMessage struct {
Role string `json:"role"`
Content string `json:"content"`
}
type ChatRequest struct {
Model string `json:"model"`
Messages []ChatMessage `json:"messages"`
}
type ChatResponse struct {
ID string `json:"id"`
Object string `json:"object"`
Created int64 `json:"created"`
Choices []struct {
Index int `json:"index"`
Message struct {
Role string `json:"role"`
Content string `json:"content"`
} `json:"message"`
} `json:"choices"`
}
// Client 封装接口调用
type Client struct {
APIKey string
BaseURL string
Model string
}
// Send 发送对话请求
func (c *Client) Send(messages []ChatMessage) (string, error) {
reqBody := ChatRequest{
Model: c.Model,
Messages: messages,
}
data, err := json.Marshal(reqBody)
if err != nil {
return "", err
}
req, err := http.NewRequest("POST", c.BaseURL, bytes.NewBuffer(data))
if err != nil {
return "", err
}
req.Header.Set("Content-Type", "application/json")
if c.APIKey != "" {
req.Header.Set("Authorization", "Bearer "+c.APIKey)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("http error: %s, body: %s", resp.Status, string(body))
}
var chatResp ChatResponse
if err := json.Unmarshal(body, &chatResp); err != nil {
return "", err
}
if len(chatResp.Choices) == 0 {
return "", fmt.Errorf("no response choices")
}
return chatResp.Choices[0].Message.Content, nil
}
func NewClient(message string, prompt string, model string) (string, error) {
var c Client
c.BaseURL = configs.OPEN_LIKE_URL
c.Model = model
c.APIKey = configs.OPENAI_LIKE_API_KEY
msgs := []ChatMessage{
{Role: "system", Content: prompt},
{Role: "user", Content: message},
}
response, err := c.Send(msgs)
if err != nil {
return "", err
}
return response, nil
}

44
pkg/ai/format.go Normal file
View File

@ -0,0 +1,44 @@
package ai
import (
"encoding/json"
"git.mmeiblog.cn/mei/aiComplain/configs"
)
type ComplainMessage struct {
Taunt string `json:"Taunt"`
}
type AuditMessage struct {
Approved bool `json:"approved"`
Reason string `json:"reason"`
}
// SendComplain 发送返回一个ai的吐槽内容
func SendComplain(message string) (ComplainMessage, error) {
response, err := NewClient(message, configs.COMPLAIN_PROMPT_TEMPLATE, configs.LLM_MODEL_LARGE)
if err != nil {
return ComplainMessage{}, err
}
var format ComplainMessage
err = json.Unmarshal([]byte(response), &format)
if err != nil {
return ComplainMessage{}, err
}
return format, nil
}
// SendAudit 检测内容是否合规
func SendAudit(message string) (AuditMessage, error) {
response, err := NewClient(message, configs.AUDIT_PROMPT_TEMPLATE, configs.LLM_MODEL_TINY)
if err != nil {
return AuditMessage{}, err
}
var format AuditMessage
err = json.Unmarshal([]byte(response), &format)
if err != nil {
return AuditMessage{}, err
}
return format, nil
}