chat.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package chat
  2. import (
  3. "fmt"
  4. "os"
  5. "strings"
  6. "sync"
  7. "time"
  8. "trial/chat/api"
  9. "github.com/wecisecode/util/merrs"
  10. "github.com/wecisecode/util/mfmt"
  11. )
  12. type Chat struct {
  13. }
  14. func NewChat() *Chat {
  15. return &Chat{}
  16. }
  17. var questions = []string{
  18. // `基于以下上下文,精确回答问题。如果上下文不包含答案,回答'未知'。\n上下文:{context}\n问题:{question}"`,
  19. `基于以下信息,回答稍后的问题:
  20. 昵称 姓名 M N K
  21. 班长 王敏 01065500556 13612345678 110123197012121234
  22. 博士 李志刚 01065436543 13387654321 120123197002020202
  23. `,
  24. // `syslog sys/5/linkupdown 告警具有什么样的含义,提供一下解决方案`,
  25. // `设备xxx的端口的对端链接端口是什么?`,
  26. // `设备xxx与设备xxx的连接关系是什么?`,
  27. // `设备xxx的最新配置是什么?`,
  28. // `设备xxx最近一年都有哪些变更?`,
  29. // `设备xxx如果希望通过ospf协议,通过xxx端口,对端设备xxx 对端端口xxx,给我生成一下配置`,
  30. // `由xxx变更的设备有哪些`,
  31. // `xxx最近1个月有哪些告警`,
  32. // `xxx设备和yyy设备的配置有哪些不同`,
  33. // `设备xxx最近一次ping不通是什么时候`,
  34. }
  35. func (chat *Chat) Run() error {
  36. question := ""
  37. for i := 1; i < len(os.Args); i++ {
  38. arg := os.Args[i]
  39. if !strings.HasPrefix(arg, "-") {
  40. question = arg
  41. }
  42. }
  43. if question != "" {
  44. questions = append([]string{question}, questions...)
  45. }
  46. response := ""
  47. var mutex sync.Mutex
  48. waiting := false
  49. senttime := time.Now()
  50. swaitingloopcount := ""
  51. go func() {
  52. for {
  53. mutex.Lock()
  54. if waiting {
  55. fmt.Print("\r", strings.Repeat(" ", len(swaitingloopcount)), "\r")
  56. swaitingloopcount = "等待服务响应 " + mfmt.FormatDuration(time.Since(senttime))
  57. fmt.Print(swaitingloopcount)
  58. }
  59. mutex.Unlock()
  60. time.Sleep(1 * time.Second)
  61. }
  62. }()
  63. context := []int64{}
  64. for {
  65. if len(questions) > 0 {
  66. question = questions[0]
  67. questions = questions[1:]
  68. fmt.Println(":=>- " + question)
  69. } else {
  70. fmt.Print(":=>- ")
  71. _, e := fmt.Scan(&question)
  72. if e != nil {
  73. return merrs.New(e)
  74. }
  75. }
  76. mutex.Lock()
  77. waiting = true
  78. senttime = time.Now()
  79. swaitingloopcount = ""
  80. mutex.Unlock()
  81. // q := `你是一个专业网络管理AI助手,请根据以下规则响应:
  82. // 1、如果用户问题是关于网络管理相关数据请求的,那么将用户问题转换为JSON对象格式,否则直接回答用户问题即可
  83. // 2、如果无法确定数据请求的任何条件,那么不要输出JSON对象,而应该引导用户提出与数据请求相关的问题
  84. // 3、JSON对象的字段说明如下:
  85. // type:要请求的数据的节点类型,包括 1 代表服务器分区, 2 代表交换机,3 代表路由器,0 代表所有节点
  86. // node:明确相关服务器的名称或IP地址,可以包含通配符,*代表任意字符串
  87. // status:要请求的数据的相关状态,包括 1 正常,2 不正常,3已关机
  88. // time:要请求的数据的相关时间段,用中文描述
  89. // 用户问题:` + question + `
  90. // `
  91. q := question
  92. // 现在时间是 "` + time.Now().Format("2006-01-02 15:04:05") + `"
  93. var responsestarttime time.Time
  94. for ret := range api.Request(context, q) {
  95. if ret.Error != nil {
  96. return ret.Error
  97. }
  98. mutex.Lock()
  99. if waiting {
  100. responsestarttime = time.Now()
  101. waiting = false
  102. fmt.Println()
  103. }
  104. mutex.Unlock()
  105. response += strings.TrimSpace(ret.Response.Response)
  106. fmt.Print(ret.Response.Response)
  107. if ret.Response.Done {
  108. fmt.Println()
  109. // fmt.Println(ret.Response.Context)
  110. fmt.Println("context length:", len(ret.Response.Context), ", response duration:", mfmt.FormatDuration(time.Since(responsestarttime)))
  111. context = ret.Response.Context
  112. break
  113. }
  114. }
  115. }
  116. }