feat: 添加最核心的ai审查和吐槽功能
This commit is contained in:
parent
72591b7e2c
commit
ea70179075
BIN
aiComplain
Executable file
BIN
aiComplain
Executable file
Binary file not shown.
38
configs/configs.go
Normal file
38
configs/configs.go
Normal 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
7
go.mod
Normal 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
4
go.sum
Normal 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
4
internal/send.go
Normal file
@ -0,0 +1,4 @@
|
||||
package internal
|
||||
|
||||
// func HandleSend(message string) (string, error) {
|
||||
// }
|
32
internal/snedAndAudit.go
Normal file
32
internal/snedAndAudit.go
Normal 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
13
main.go
Normal 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
100
pkg/ai/api.go
Normal 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
44
pkg/ai/format.go
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user