Skip to content
6 changes: 3 additions & 3 deletions llm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ The server integrates the Ollama model and uses Dubbo-go's RPC service for invoc
Run the server by executing:

```shell
$ go run llm/go-server/cmd/server.go
$ go run go-server/cmd/server.go
```

### **Run the Client**
Expand All @@ -58,15 +58,15 @@ The client invokes the server's RPC interface to retrieve the inference results
Run the cli client by executing:

```shell
$ go run llm/go-client/cmd/client.go
$ go run go-client/cmd/client.go
```

Cli client supports multi-turn conversations, command interact, context management.

We also support a frontend using Gin framework for users to interact. If you want run the frontend client you can executing the following command and open it in ```localhost:8080``` by default:

```shell
$ go run llm/go-client/frontend/main.go
$ go run go-client/frontend/main.go
```

Frontend client supports multi-turn conversations, binary file (image) support for LLM interactions.
6 changes: 3 additions & 3 deletions llm/README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ $ cd llm
在服务端目录下运行:

```shell
$ go run llm/go-server/cmd/server.go
$ go run go-server/cmd/server.go
```

### **客户端运行**
Expand All @@ -58,15 +58,15 @@ $ go run llm/go-server/cmd/server.go
在客户端目录下运行:

```shell
$ go run llm/go-client/cmd/client.go
$ go run go-client/cmd/client.go
```

命令行客户端支持多轮对话、命令交互、上下文管理功能。

我们也提供了包含前端页面的基于Gin框架的客户端进行交互,运行以下命令然后访问 ```localhost:8080``` 即可使用:

```shell
$ go run llm/go-client/frontend/main.go
$ go run go-client/frontend/main.go
```

包含前端页面的客户端支持多轮对话,支持进行二进制文件(图片)传输并与大模型进行交互.
Expand Down
17 changes: 14 additions & 3 deletions llm/go-client/frontend/handlers/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import (
"io"
"log"
"net/http"
"regexp"
"runtime/debug"
"strings"
"time"
)

Expand Down Expand Up @@ -82,13 +82,24 @@ func (h *ChatHandler) Chat(c *gin.Context) {
return
}

sepIndex := strings.Index(",", req.Bin)
var img string
if len(req.Bin) > 0 {
re := regexp.MustCompile(`^data:image/([a-zA-Z]+);base64,([^"]+)$`)
matches := re.FindStringSubmatch(req.Bin)

if len(matches) != 3 {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid base64 data format"})
return
}

img = matches[2]
}

messages := h.ctxManager.GetHistory(ctxID)
messages = append(messages, &chat.ChatMessage{
Role: "human",
Content: req.Message,
Bin: []byte(req.Bin[sepIndex+1:]),
Bin: []byte(img),
})

stream, err := h.svc.Chat(context.Background(), &chat.ChatRequest{
Expand Down
3 changes: 3 additions & 0 deletions llm/go-client/frontend/static/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const createChatLi = (message, className) => {

const handleChat = () => {
userMessage = chatInput.value.trim(); // Get user entered message and remove extra whitespace
userBin = null
if (fileBlobArr.length > 0) {
userBin = fileBlobArr[0]
}
Expand Down Expand Up @@ -204,6 +205,8 @@ function clear() {
document.getElementById("drop").style.display = "none";
addBtn.style.display = "flex";
fileInput.value = "";
fileBlobArr = [];
fileArr = [];
}

document.getElementById("drop").addEventListener('click', clear);
12 changes: 7 additions & 5 deletions llm/go-server/cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ package main

import (
"context"
"encoding/base64"
"fmt"
"log"
"net/http"
"runtime/debug"
)

Expand Down Expand Up @@ -81,13 +83,13 @@ func (s *ChatServer) Chat(ctx context.Context, req *chat.ChatRequest, stream cha
}

if msg.Bin != nil && len(msg.Bin) != 0 {
img := string(msg.Bin)
decodeByte, err := base64.StdEncoding.DecodeString(string(msg.Bin))
if err != nil {
log.Println("Decode image error:", err)
return fmt.Errorf("decode image error: %s", err)
log.Println("GenerateContent failed: %v", err)
return fmt.Errorf("GenerateContent failed")
}

messageContent.Parts = append(messageContent.Parts, llms.BinaryPart("image/png", img))
imgType := http.DetectContentType(decodeString)
messageContent.Parts = append(messageContent.Parts, llms.BinaryPart(imgType, decodeByte))
}

messages = append(messages, messageContent)
Expand Down
Loading