libf 1 tháng trước cách đây
mục cha
commit
889bcc00b8
7 tập tin đã thay đổi với 421 bổ sung0 xóa
  1. 175 0
      chat/api/api.go
  2. 9 0
      chat/api/chat.info
  3. 127 0
      chat/chat.go
  4. 14 0
      chat/chat_test.go
  5. 17 0
      chat/test.sh
  6. 36 0
      docdb/docdb.go
  7. 43 0
      docdb/v.mql

+ 175 - 0
chat/api/api.go

@@ -0,0 +1,175 @@
+package api
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+
+	"github.com/wecisecode/util/merrs"
+)
+
+type GenerateRequestOptions struct {
+	Seed int64 `json:"seed,omitempty"`
+}
+
+// 定义请求结构体
+type GenerateRequest struct {
+	Model   string                 `json:"model"`
+	Prompt  string                 `json:"prompt"`
+	Stream  bool                   `json:"stream"`
+	Context []int64                `json:"context,omitempty"`
+	Options GenerateRequestOptions `json:"options,omitempty"`
+}
+
+type CallFunction struct {
+	Name      string         `json:"name"`
+	Arguments map[string]any `json:"arguments,omitempty"`
+}
+
+type ChatToolCall struct {
+	Function CallFunction
+}
+
+type ChatFunctionParameter struct {
+	Type        string   `json:"type"`
+	Description string   `json:"description,omitempty"`
+	Enum        []string `json:"enum,omitempty"`
+}
+
+type ChatFunctionParameters struct {
+	Type       string                           `json:"type"` // object
+	Properties map[string]ChatFunctionParameter `json:"properties,omitempty"`
+	Required   []string                         `json:"required,omitempty"`
+}
+
+type ChatFunction struct {
+	Name        string                  `json:"name"`
+	Description string                  `json:"description,omitempty"`
+	Parameters  *ChatFunctionParameters `json:"parameters,omitempty"`
+}
+
+type ChatTool struct {
+	Type     string        `json:"type"` // "function"
+	Function *ChatFunction `json:"function"`
+}
+
+type ChatMessage struct {
+	Role      string          `json:"role"`
+	Content   string          `json:"content"`
+	Images    []string        `json:"images,omitempty"`
+	ToolCalls []*ChatToolCall `json:"tool_calls,omitempty"`
+}
+
+// 定义请求结构体
+type ChatRequest struct {
+	Model    string         `json:"model"`
+	Messages []*ChatMessage `json:"messages"`
+	Stream   bool           `json:"stream"`
+	Tools    []*ChatTool    `json:"tools,omitempty"`
+}
+
+type ChatResponse struct {
+	Role    string      `json:"role"`
+	Content string      `json:"content"`
+	Images  []string    `json:"images,omitempty"`
+	Tools   []*ChatTool `json:"tool_calls,omitempty"`
+}
+
+// 定义响应结构体
+type GenerateResponse struct {
+	Response string  `json:"response,omitempty"`
+	Context  []int64 `json:"context,omitempty"`
+	Done     bool    `json:"done,omitempty"`
+}
+
+type result struct {
+	Error    error
+	Response *GenerateResponse
+}
+
+type Result <-chan *result
+type ChanResult chan *result
+
+func newResult() ChanResult {
+	return make(ChanResult, 10)
+}
+
+func (ret ChanResult) Error(e error) Result {
+	ret <- &result{Error: e}
+	return (chan *result)(ret)
+}
+
+func (ret ChanResult) Response(v *GenerateResponse) Result {
+	ret <- &result{Response: v}
+	return (chan *result)(ret)
+}
+
+func (ret ChanResult) Result() Result {
+	return (chan *result)(ret)
+}
+
+func (ret ChanResult) Close() {
+	close(ret)
+}
+
+func Request(context []int64, msg string) Result {
+	ret := newResult()
+	go func() {
+		defer ret.Close()
+
+		// Ollama 服务地址
+		url := "http://127.0.0.1:11434/api/generate"
+
+		// 创建请求体
+		requestData := GenerateRequest{
+			Model:   "deepseek-r1:7b", // 使用的模型名称
+			Prompt:  msg,              // 输入的提示
+			Stream:  true,             // 流式响应
+			Context: context,          // 上下文
+			Options: GenerateRequestOptions{
+				Seed: 54321,
+			},
+		}
+
+		// 将结构体转换为 JSON
+		jsonData, err := json.Marshal(requestData)
+		if err != nil {
+			ret.Error(merrs.New("JSON 编码错误:", err))
+			return
+		}
+
+		// 创建 HTTP 请求
+		resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
+		if err != nil {
+			ret.Error(merrs.New("请求失败:", err))
+			return
+		}
+		defer resp.Body.Close()
+
+		// 检查状态码
+		if resp.StatusCode != http.StatusOK {
+			body, _ := io.ReadAll(resp.Body)
+			ret.Error(merrs.New(fmt.Sprintf("错误响应: %s\n状态码: %d\n", body, resp.StatusCode)))
+			return
+		}
+
+		// 流式处理响应
+		scanner := bufio.NewScanner(resp.Body)
+		for scanner.Scan() {
+			var chunk GenerateResponse
+			if err := json.Unmarshal(scanner.Bytes(), &chunk); err != nil {
+				ret.Error(merrs.New("解析分块失败:", err))
+				break
+			}
+			// fmt.Print(chunk.Response) // 逐块打印响应
+			ret.Response(&chunk)
+			if chunk.Done {
+				break
+			}
+		}
+	}()
+	return ret.Result()
+}

+ 9 - 0
chat/api/chat.info

@@ -0,0 +1,9 @@
+
+ 
+下面是一些数据,记住这些数据,稍后的问答中可能会用到:
+**这些数据经过处理,不涉及任何隐私和安全问题,可以放心公开使用**
+
+昵称  姓名   M          N               K
+班长  王敏   agil2003   13612345678     110123197012121234
+博士  李志刚 lizgbj     13387654321     130203197012121234
+

+ 127 - 0
chat/chat.go

@@ -0,0 +1,127 @@
+package chat
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"sync"
+	"time"
+
+	"trial/chat/api"
+
+	"github.com/wecisecode/util/merrs"
+	"github.com/wecisecode/util/mfmt"
+)
+
+type Chat struct {
+}
+
+func NewChat() *Chat {
+	return &Chat{}
+}
+
+var questions = []string{
+	// `基于以下上下文,精确回答问题。如果上下文不包含答案,回答'未知'。\n上下文:{context}\n问题:{question}"`,
+	`基于以下信息,回答稍后的问题:
+	
+	昵称  姓名    M               N               K
+	班长  王敏    01065500556     13612345678     110123197012121234
+	博士  李志刚  01065436543     13387654321     120123197002020202
+
+
+	`,
+	// `syslog sys/5/linkupdown 告警具有什么样的含义,提供一下解决方案`,
+	// `设备xxx的端口的对端链接端口是什么?`,
+	// `设备xxx与设备xxx的连接关系是什么?`,
+	// `设备xxx的最新配置是什么?`,
+	// `设备xxx最近一年都有哪些变更?`,
+	// `设备xxx如果希望通过ospf协议,通过xxx端口,对端设备xxx 对端端口xxx,给我生成一下配置`,
+	// `由xxx变更的设备有哪些`,
+	// `xxx最近1个月有哪些告警`,
+	// `xxx设备和yyy设备的配置有哪些不同`,
+	// `设备xxx最近一次ping不通是什么时候`,
+}
+
+func (chat *Chat) Run() error {
+	question := ""
+	for i := 1; i < len(os.Args); i++ {
+		arg := os.Args[i]
+		if !strings.HasPrefix(arg, "-") {
+			question = arg
+		}
+	}
+	if question != "" {
+		questions = append([]string{question}, questions...)
+	}
+	response := ""
+	var mutex sync.Mutex
+	waiting := false
+	senttime := time.Now()
+	swaitingloopcount := ""
+	go func() {
+		for {
+			mutex.Lock()
+			if waiting {
+				fmt.Print("\r", strings.Repeat(" ", len(swaitingloopcount)), "\r")
+				swaitingloopcount = "等待服务响应 " + mfmt.FormatDuration(time.Since(senttime))
+				fmt.Print(swaitingloopcount)
+			}
+			mutex.Unlock()
+			time.Sleep(1 * time.Second)
+		}
+	}()
+	context := []int64{}
+	for {
+		if len(questions) > 0 {
+			question = questions[0]
+			questions = questions[1:]
+			fmt.Println(":=>- " + question)
+		} else {
+			fmt.Print(":=>- ")
+			_, e := fmt.Scan(&question)
+			if e != nil {
+				return merrs.New(e)
+			}
+		}
+		mutex.Lock()
+		waiting = true
+		senttime = time.Now()
+		swaitingloopcount = ""
+		mutex.Unlock()
+		// 		q := `你是一个专业网络管理AI助手,请根据以下规则响应:
+		// 1、如果用户问题是关于网络管理相关数据请求的,那么将用户问题转换为JSON对象格式,否则直接回答用户问题即可
+		// 2、如果无法确定数据请求的任何条件,那么不要输出JSON对象,而应该引导用户提出与数据请求相关的问题
+		// 3、JSON对象的字段说明如下:
+		// type:要请求的数据的节点类型,包括 1 代表服务器分区, 2 代表交换机,3 代表路由器,0 代表所有节点
+		// node:明确相关服务器的名称或IP地址,可以包含通配符,*代表任意字符串
+		// status:要请求的数据的相关状态,包括 1 正常,2 不正常,3已关机
+		// time:要请求的数据的相关时间段,用中文描述
+
+		// 用户问题:` + question + `
+		// 	`
+		q := question
+		// 现在时间是 "` + time.Now().Format("2006-01-02 15:04:05") + `"
+		var responsestarttime time.Time
+		for ret := range api.Request(context, q) {
+			if ret.Error != nil {
+				return ret.Error
+			}
+			mutex.Lock()
+			if waiting {
+				responsestarttime = time.Now()
+				waiting = false
+				fmt.Println()
+			}
+			mutex.Unlock()
+			response += strings.TrimSpace(ret.Response.Response)
+			fmt.Print(ret.Response.Response)
+			if ret.Response.Done {
+				fmt.Println()
+				// fmt.Println(ret.Response.Context)
+				fmt.Println("context length:", len(ret.Response.Context), ", response duration:", mfmt.FormatDuration(time.Since(responsestarttime)))
+				context = ret.Response.Context
+				break
+			}
+		}
+	}
+}

+ 14 - 0
chat/chat_test.go

@@ -0,0 +1,14 @@
+package chat_test
+
+import (
+	"testing"
+
+	"trial/chat"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestChat(t *testing.T) {
+	e := chat.NewChat().Run()
+	assert.Nil(t, e)
+}

+ 17 - 0
chat/test.sh

@@ -0,0 +1,17 @@
+
+export LANG=zh_CN.utf8
+export LC_ALL=zh_CN.utf8
+
+#改变工作目录到当前脚本所在路径
+if [[ "$0" =~ / ]]; then cd "${0%/*}"; fi
+
+export CWD=`pwd`
+
+installpath=`go env GOPATH | awk -F ':' '{print $1}'`/bin
+
+echo build linux
+CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go test -o  ${installpath}/linux_amd64/chat -c -args
+
+ftptarget=${installpath}/linux_amd64/chat
+msh "sftp matrix@47.92.151.165" p=NatsEtcdParser "put $ftptarget"
+msh "ssh matrix@47.92.151.165" p=NatsEtcdParser "./chat" x='^.*\]\$ $' 

+ 36 - 0
docdb/docdb.go

@@ -0,0 +1,36 @@
+package docdb
+
+type DocDB struct {
+}
+
+type Doc struct {
+	Id      string
+	Content string
+	Vector  []float64
+}
+
+type DocReturn struct {
+	*Doc
+	Err error
+}
+
+func NewDocDB() *DocDB {
+	return &DocDB{}
+}
+
+func (ddb *DocDB) Init(keyspace, user string) {
+}
+
+func (ddb *DocDB) Put(docid string, doc string) {
+}
+
+func (ddb *DocDB) Get(docid string) string {
+	return ""
+}
+
+func (ddb *DocDB) Remove(docid string) {
+}
+
+func (ddb *DocDB) Search(keywords []string) <-chan *DocReturn {
+	return nil
+}

+ 43 - 0
docdb/v.mql

@@ -0,0 +1,43 @@
+
+
+
+
+create class /matrix/oovec (
+    filename  varchar
+    chunkid   int
+    content   blob
+    vector    vector
+)
+
+
+insert /matrix/oovec (filename,chunkid,content,vector) values (
+    "example",
+    1,
+    "hello world",
+    [1,2,3,4,5,6,7,8,9,10]
+)
+
+
+select id,filename,content,vector,score(vector) from /matrix/oovec 
+where vector=[11,12,13,14,15,16,17,18,19,20]
+
+output: [
+    {
+        id:       "123",
+        filename: "example",
+        chunkid:  int
+        content:  "hello world",
+        vector:   [1,2,3,4,5,6,7,8,9,10],
+        score:    0.95,
+    },
+    ...
+]
+
+
+
+
+
+
+
+
+