```
package task

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"strconv"
	"sync"
	"time"
	"xagent/aiclient"
	"xagent/db"
	taskhistory "xagent/db/taskHistory"
	"xagent/models"
	"xagent/service/chat"
	service "xagent/service/user"
	"xagent/utils"

	"github.com/google/uuid"
	"github.com/sashabaranov/go-openai"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

type AITask struct {
	InitMessage    openai.ChatCompletionMessage
	PreMessage     openai.ChatCompletionMessage
	PostMessage    openai.ChatCompletionMessage
	GuidingMessage openai.ChatCompletionMessage
	Knowledge      string
	stuProfile     string
	aiTaskType     models.AITaskType
	TaskBase
}

func (at *AITask) finish() {
	userid := at.GetUserId()
	uSummaryService := service.NewUserSummaryService(userid)
	UNodeKV := []models.TagCount{{
		Tag:   at.GetTaskTopic(),
		Count: 1,
	}}
	if at.aiTaskType == models.STUDYTASK {
		// 学完一个知识点增加五个经验
		uSummaryService.UpdateUserNodeSummary(true, UNodeKV)
		uSummaryService.AddUserExperiencePoint(5)
	}
}

func (at *AITask) HandleTimeOut() {
	// TODO 发送提示消息
	var serverResponse models.ServerResponse
	serverResponse.TaskID = at.GetTaskID()
	serverResponse.MessageID = utils.NewUUIDStr()
	serverResponse.Contents = []openai.ChatMessagePart{
		{
			Type: openai.ChatMessagePartTypeText,
			Text: "你已经好久没回我消息了，能告诉我你在想什么吗？",
		},
	}
	serverResponse.Role = models.AssistantRole
	at.Conversation.SendToClientChan <- utils.NewWsResp(serverResponse, "ok", 0, "aiSaid")
}

func (at *AITask) Run(doneChan chan<- models.TaskRunResult, input models.UserPost) {
	taskStatus := at.GetStatus()
	var serverResponse models.ServerResponse

	if taskStatus < 1 {
		at.AppendMessage([]openai.ChatCompletionMessage{{
			Role:    openai.ChatMessageRoleUser,
			Content: input.Input.(string),
		}})
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
	defer cancel()
	message, err := at.Conversation.GetAIMsgResp(ctx)
	if err != nil {
		at.Conversation.SendToClientChan <- utils.WsResendResponse(at.GetTaskID())
		log.Println("服务器内部错误，ai 返回内容失败", message)
		doneChan <- models.CONTINUE
	}

	guidingRes := at.SetGuiding(message.Content[0].Text.Value)
	switch v := guidingRes.(type) {
	case error:
		at.Conversation.SendToClientChan <- utils.WsResendResponse(at.GetTaskID())
		doneChan <- models.CONTINUE
	case []openai.ChatCompletionMessage:
		// 任务正常进行
		serverResponse.Role = models.Role(v[0].Role)
		serverResponse.Contents = []openai.ChatMessagePart{
			{
				Type: openai.ChatMessagePartTypeText,
				Text: v[0].Content,
			},
		}
		latestMessage, _ := at.Conversation.LatestMsg(20)

		log.Println("下面输出历史记录：----------\n\n:")

		for _, lmsg := range latestMessage {
			for _, content := range lmsg.Content {
				log.Println("对话历史记录：", lmsg.Role, content.Text.Value)
			}
		}

		log.Println("输出thread id, 输出所有的run id, 检查是不是因为多发送了run 请求导致的-------\n\n:", at.Conversation.ThreadID)
		client := aiclient.NewOpenAIClient()
		limit := 100
		order := "desc"
		runs, err := client.ListRuns(context.Background(), at.Conversation.ThreadID, openai.Pagination{
			Limit:  &limit,
			Order:  &order,
			After:  nil,
			Before: nil,
		})
		if err != nil {
			log.Println("获取run id 失败", err)
		}
		for _, run := range runs.Runs {
			log.Println("run id: ", run.ID)
		}

		serverResponse.Followups = getRelatedTopics(utils.ClientMsg2CompletionMsg(latestMessage[0:3]))
		serverResponse.TaskID = at.GetTaskID()
		// 下面的回答都依赖于上面解析成功
		if at.GetStatus() != 1 {
			at.Conversation.SendToClientChan <- utils.NewWsResp(serverResponse, "ok", 0, "aiSaid")
			doneChan <- models.CONTINUE
		} else {
			// 在对话中标记当前知识点学习完成了
			at.SetPost("当前学习的Task已经完成，下一个知识点的内容会在下面告诉你")
			at.AppendMessage([]openai.ChatCompletionMessage{at.PostMessage})
			doneChan <- models.DONE
			// AI Task finish
			at.finish()
		}
		// TODO user loss conversation for too long
	}
}
func (kt *AITask) SetPre(payload interface{}) interface{} {
	if kt.aiTaskType == models.CHITCHATTASK {
		kt.PreMessage = openai.ChatCompletionMessage{
			Role:    "system",
			Content: taskPrompts.GetAI().GetAITask(kt.aiTaskType).PrePrompt,
		}
	} else {
		kt.PreMessage = openai.ChatCompletionMessage{
			Role:    "system",
			Content: fmt.Sprintf(taskPrompts.GetAI().GetAITask(kt.aiTaskType).PrePrompt, payload),
		}
	}
	return kt.PreMessage
}

func (kt *AITask) SetPost(payload interface{}) interface{} {
	if kt.aiTaskType == models.CHITCHATTASK {
		kt.PostMessage = openai.ChatCompletionMessage{
			Role:    "system",
			Content: taskPrompts.GetAI().GetAITask(kt.aiTaskType).PostPrompt,
		}
	} else {
		kt.PostMessage = openai.ChatCompletionMessage{
			Role:    "system",
			Content: fmt.Sprintf(taskPrompts.GetAI().GetAITask(kt.aiTaskType).PostPrompt, payload),
		}
	}
	return kt.PostMessage
}

func (kt *AITask) SetGuiding(guiding string) interface{} {
	var structRes models.AIResponse
	err := json.Unmarshal([]byte(guiding), &structRes)
	if err != nil {
		log.Println("AI 返回的内容不符合Json格式", guiding, err)
		return errors.New("AI 返回的内容不符合Json格式")
	}
	process, err := strconv.ParseFloat(structRes.Process, 64)
	if err != nil {
		log.Println("AI 返回的内容process不是float", guiding, err)
		return errors.New("AI 返回的内容不符合Json格式")
	}
	kt.SetTaskStatus(process)
	kt.AppendMessage([]openai.ChatCompletionMessage{{
		Role:    openai.ChatMessageRoleSystem,
		Content: taskPrompts.GetAI().GetAITask(kt.aiTaskType).GuidingPrompt,
	}})
	return []openai.ChatCompletionMessage{{
		Role:    openai.ChatMessageRoleAssistant,
		Content: structRes.Msg,
	}}
}

// Init 对于AI Task 初始化，开始获取这个学生的基本信息
// TODO 我觉得可以把这个Init 整合到Run 函数中
//
//	@receiver at 整个AITask对象
func (at *AITask) Init() {
	at.InitMessage = openai.ChatCompletionMessage{
		Role:    openai.ChatMessageRoleSystem,
		Content: taskPrompts.GetAI().GetAITask(at.aiTaskType).InitPrompt + "这里是这个学生的一些基本情况，请你根据他的基本情况在后续的对话中采取合适的回答: " + at.stuProfile,
	}
	var serverResponse models.ServerResponse
	at.AppendMessage([]openai.ChatCompletionMessage{at.InitMessage, at.PreMessage, {
		Role:    openai.ChatMessageRoleSystem,
		Content: "根据上面的情况主动和学生说点什么吧",
	}})

	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
	defer cancel()

	message, err := at.Conversation.GetAIMsgResp(ctx)
	if err != nil {
		at.Conversation.SendToClientChan <- utils.WsResendResponse(at.GetTaskID())
		log.Println("服务器内部错误，ai 返回内容失败", err)
		return
	}

	guidingRes := at.SetGuiding(message.Content[0].Text.Value)
	switch v := guidingRes.(type) {
	case error:
		log.Println("服务器内部错误", v)
		at.Conversation.SendToClientChan <- utils.WsResendResponse(at.GetTaskID())
	case []openai.ChatCompletionMessage:
		// 任务正常进行
		serverResponse.Role = models.Role(v[0].Role)
		serverResponse.Contents = []openai.ChatMessagePart{
			{
				Type: openai.ChatMessagePartTypeText,
				Text: v[0].Content,
			},
		}
	}
	latestMessage, _ := at.Conversation.LatestMsg(3)
	serverResponse.Followups = getRelatedTopics(utils.ClientMsg2CompletionMsg(latestMessage))
	serverResponse.TaskID = at.GetTaskID()
	serverResponse.MessageID = utils.NewUUIDStr()
	at.Conversation.SendToClientChan <- utils.NewWsResp(serverResponse, "ok", 0, "aiSaid")
}

func (at *AITask) SummarizeTask() []openai.ChatCompletionMessage {
	return []openai.ChatCompletionMessage{}
}

func (at *AITask) GetTaskTopic() string {
	return at.Knowledge
}

func NewAITask(knowledge string, stuProfile string, timeout int, relatedTasks []Task, userid primitive.ObjectID, aiTaskType models.AITaskType, conv *Conversation) *AITask {
	uid, _ := uuid.NewUUID()
	taskDB := taskhistory.NewTaskHistoryDB(db.TaskHistoryColl)
	if taskDB == nil {
		log.Println("数据库连接失败")
		return nil
	}
	task := &AITask{
		TaskBase: TaskBase{
			Timeout:      timeout,
			Status:       0,
			RelatedTask:  relatedTasks,
			TaskType:     AI,
			taskID:       uid.String(),
			userID:       userid,
			Conversation: conv,
		},
		aiTaskType: aiTaskType,
		stuProfile: stuProfile,
	}

	// 随机选一个知识点
	knowledges := []string{"卜算子", "王安石", "标点符号"}
	knowledge = utils.GetRandomItem(knowledges)
	knowledgeDetail := ""
	// 创建一个以下面这个knowledge为主题的task,如果这个任务是闲聊任务就不设定knowledge
	if aiTaskType == models.CHITCHATTASK {
		task.Knowledge = ""
	} else {
		task.Knowledge = knowledge
	}

	// 根据knowledge title 获取详细的知识点
	switch knowledge {
	case "卜算子":
		knowledgeDetail = `卜算子·送鲍浩然之浙东`
	case "标点符号":
		knowledgeDetail = `
句号`
	}
	task.SetPre(knowledgeDetail)

	mu.Lock()
	tasks[uid.String()] = task
	mu.Unlock()
	return task
}

func getRelatedTopics(messages []openai.ChatCompletionMessage) []models.FollowupItem {
	var wg sync.WaitGroup
	topicChannel := make(chan []string, 1)

	// create a new go routine to send related topic to client
	wg.Add(1)
	go func(messages []openai.ChatCompletionMessage) {
		defer wg.Done()
		related := chat.NewRealtedTopic(messages, "gpt-3.5-turbo", 3)
		topics := related.GetRelatedTopics()
		topicChannel <- topics
	}(messages)

	// Wait for goroutine to finish
	wg.Wait()
	close(topicChannel)

	// Retrieve topics from channel
	topics := <-topicChannel

	// Convert topics to FollowupItem list
	var relatedTopic []models.FollowupItem
	for _, topic := range topics {
		relatedTopic = append(relatedTopic, models.FollowupItem{
			Type: "text",
			Text: topic,
		})
	}

	return relatedTopic
}
```
针对上面这个Task，请你理解我的代码需要实现的功能后，帮我优化一下上面代码的实现，希望能够更加具有可扩展性。最后我希望你给出的结构体的名称修改成ATask，不然会和我现有的AITask 这个结构体冲突掉。最重要的是我想让Init 和 Run 方法合并在一起，因为他们其实都是要调用GetAIMsgResp这个方法。下面是我的Task 需要实现的接口。
```
type Task interface {
	Init()
	SetPre(payload interface{}) interface{}
	SetPost(payload interface{}) interface{}
	SetGuiding(guiding string) interface{}
	SetTaskStatus(process float64)
	SummarizeTask() []openai.ChatCompletionMessage
	GetTimeout() int
	GetRelatedTask() []Task
	GetStatus() float64
	GetTaskType() TaskType
	GetTaskID() string
	GetDisableChat() bool
	GetTaskTopic() string
	Run(doneChan chan<- models.TaskRunResult, input models.UserPost)
	HandleTimeOut()
	UpdateTaskLastUserSaid()
	GetLastUserSaidTime() int64
}

type TaskBase struct {
	userID       primitive.ObjectID
	taskID       string
	Timeout      int
	RelatedTask  []Task
	Status       float64
	TaskType     TaskType
	disableChat  bool
	lastUserSaid int64
	Conversation *Conversation
}

func (tb *TaskBase) AppendMessage(messages []openai.ChatCompletionMessage) {
	for _, message := range messages {
		tb.Conversation.AddMessage(message.Role, message.Content)
	}
}

func (tb *TaskBase) UpdateTaskLastUserSaid() {
	tb.lastUserSaid = time.Now().UnixMicro()
}

func (tb *TaskBase) GetLastUserSaidTime() int64 {
	return tb.lastUserSaid
}

func (tb *TaskBase) GetUserId() primitive.ObjectID {
	return tb.userID
}

func (tb *TaskBase) GetDisableChat() bool {
	return tb.disableChat
}

// 实现 Task 接口的方法
func (tb *TaskBase) SetTaskStatus(process float64) {
	tb.Status = process
}

func (tb *TaskBase) GetTaskID() string {
	return tb.taskID
}

func (tb *TaskBase) GetTimeout() int {
	return tb.Timeout
}

func (tb *TaskBase) GetRelatedTask() []Task {
	return tb.RelatedTask
}

func (tb *TaskBase) GetStatus() float64 {
	return tb.Status
}

func (tb *TaskBase) GetTaskType() TaskType {
	return tb.TaskType
}
```