长安链智能合约助手制作

首先新建一个Go项目

接着新建一个index文件,用于编写网页样式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web App</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.26.0/themes/prism.min.css" rel="stylesheet" />
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            height: 100vh;
            display: flex;
            flex-direction: column;
        }
        .container {
            width: 90%;
            margin: 0 auto;
            padding: 20px;
            flex-grow: 1;
            display: flex;
            flex-direction: column;
        }
        input[type="text"] {
            width: 100%;
            padding: 10px;
            box-sizing: border-box;
            margin-bottom: 20px;
        }
        pre {
            width: 100%;
            padding: 10px;
            box-sizing: border-box;
            overflow: auto;
            flex-grow: 1;
            white-space: pre;
        }
        .copy-button {
            position: absolute;
            top: 0;
            right: 0;
            background-color: #4CAF50;
            border: none;
            color: white;
            padding: 5px 10px;
            text-align: center;
            text-decoration: none;
            display: inline-block;
            font-size: 14px;
            cursor: pointer;
        }
    </style>
</head>
<body>
<div class="container">
    欢迎使用碳链记智能合约生成助手。请问您有什么合约需求?
    <input type="text" id="inputText" placeholder="请输入内容并按回车键">
    <pre id="outputText" class="language-go" style="position: relative;">
        <code contenteditable="true"></code>
        <button class="copy-button" id="copyButton">复制</button>
    </pre>

</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.26.0/prism.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.26.0/components/prism-go.min.js"></script>
<script>
    const inputText = document.getElementById("inputText");
    const outputText = document.getElementById("outputText");
    const copyButton = document.getElementById("copyButton");
    inputText.addEventListener("keydown", function (event) {
        if (event.key === "Enter") {
            event.preventDefault();
            sendDataToServer(inputText.value);
            outputText.querySelector('code').textContent = ""; // 清空大文本框的内容
        }
    });
    copyButton.addEventListener("click", function() {
        navigator.clipboard.writeText(outputText.querySelector('code').textContent).then(function() {
            console.log("Copying to clipboard was successful!");
        }, function(err) {
            console.error("Could not copy text: ", err);
        });
    });

    function sendDataToServer(data) {
        // 获取当前页面的URL,然后将其更改为WebSocket URL并添加查询参数
        const baseUrl = new URL(window.location.href);
        baseUrl.protocol = baseUrl.protocol.replace("http", "ws");
        baseUrl.pathname = "/api";
        baseUrl.search = "?text=" + encodeURIComponent(data);

        const ws = new WebSocket(baseUrl.toString());

        ws.onmessage = function (event) {
            let formattedData = event.data;
            outputText.querySelector('code').textContent += formattedData;
            Prism.highlightElement(outputText.querySelector('code'));
            outputText.scrollTop = outputText.querySelector('code').scrollHeight;
        };

        ws.onerror = function (error) {
            console.error("Error:", error);
            ws.close();
        };
    }
</script>
</body>
</html>

然后在main.go中编写如下代码

package main

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"github.com/tmc/langchaingo/llms"
	"github.com/tmc/langchaingo/llms/openai"
	"github.com/tmc/langchaingo/schema"
	"log"
	"net/http"
)

var sysMessage = `你是一个Golang程序员,只输出代码,不要输出除代码以外的任何其他话。以下是已知的接口可被调用:
type SDKInterface interface {
	// GetArgs get arg from transaction parameters
	// @return: 参数map
	GetArgs() map[string][]byte
	// GetStateByte get [key, field] from chain
	// @param key: 获取的参数名
	// @param field: 获取的参数名
	// @return1: 获取结果,格式为[]byte, nil表示不存在
	// @return2: 获取错误信息
	GetStateByte(key, field string) ([]byte, error)
	// PutStateByte put [key, field, value] to chain
	// @param1 key: 参数名
	// @param1 field: 参数名
	// @param2 value: 参数值,类型为[]byte
	// @return1: 上传参数错误信息
	PutStateByte(key, field string, value []byte) error
	// DelState delete [key, field] to chain
	// @param1 key: 删除的参数名
	// @param1 field: 删除的参数名
	// @return1:删除参数的错误信息
	DelState(key, field string) error
	// EmitEvent emit event, you can subscribe to the event using the SDK
	// @param1 topic: 合约事件的主题
	// @param2 data: 合约事件的数据
	EmitEvent(topic string, data []string)
	// GetTxTimeStamp 获得交易的时间戳
	GetTxTimeStamp() (string, error)
	// CallContract 跨合约调用另一个合约
	CallContract(contractName, method string, args map[string][]byte) protogo.Response
	// Sender 获得交易发送者的地址
	Sender() (string, error)
}
通过sdk.Instance可以使用上述接口的函数,另外还有sdk.Success(payload []byte) protogo.Response表示成功的返回,sdk.Error(msg string) protogo.Response表示失败的返回,sdk包下没有其他方法了。
我们就可以编写类似Fabric ChainCode的合约,只是合约格式有所不同,另外一定要注意:在代码中绝对不能出现time.Now(),随机数等不确定性的函数,获取时间用sdk.Instance.GetTxTimeStamp()函数。以下是一个最简单的存证数据的合约代码:

package main

import (
	"crypto/sha256"
	"encoding/hex"

	"chainmaker.org/chainmaker/contract-sdk-go/v2/pb/protogo"
	"chainmaker.org/chainmaker/contract-sdk-go/v2/sandbox"
	"chainmaker.org/chainmaker/contract-sdk-go/v2/sdk"
)

// EvidenceContract 存证合约实现
type EvidenceContract struct {
}

// InitContract 初始化合约,必须实现的接口
func (e *EvidenceContract) InitContract() protogo.Response {
	return sdk.SuccessResponse
}

// UpgradeContract 升级合约,必须实现的接口
func (e *EvidenceContract) UpgradeContract() protogo.Response {
	return sdk.SuccessResponse
}

// InvokeContract 调用合约,必须实现的接口
func (e *EvidenceContract) InvokeContract(method string) (result protogo.Response) {
	// 记录异常结果日志
	defer func() {
		if result.Status != 0 {
			sdk.Instance.Warnf(result.Message)
		}
	}()

	switch method {
	case "PutEvidence":
		return e.PutEvidence()
	//其他case ...
	
	default:
		return sdk.Error("invalid method")
	}
}

func (e *EvidenceContract) PutEvidence() protogo.Response {
	params := sdk.Instance.GetArgs()
	// 获取参数
	data := params["data"]
	hash:=sha256.Sum256(data)
	err := sdk.Instance.PutStateByte(hex.EncodeToString( hash[:]), "data",data)
	if err != nil {
		return sdk.Error(err.Error())
	}
	// 返回OK
	return sdk.SuccessResponse
}

func main() {
	err := sandbox.Start(new(EvidenceContract))
	if err != nil {
		sdk.Instance.Errorf(err.Error())
	}
}
根据以上内容,请仅提供Go代码,不要包含任何Markdown标记,也不要有任何其他文字,只要代码,满足用户的要求:`

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func main() {
	router := gin.Default()
	router.GET("/", func(c *gin.Context) {
		http.ServeFile(c.Writer, c.Request, "index.html")
	})
	router.GET("/api", func(c *gin.Context) {
		conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
		if err != nil {
			fmt.Println("Failed to upgrade connection:", err)
			return
		}
		defer conn.Close()

		// Get the "text" parameter from the query string
		inputText := c.Query("text")
		fmt.Println("Received text:", inputText)

		// 将这里的OPENAI_API_BASE和OPENAI_API_KEY替换为你的实际值
		llm, err := openai.NewChat(
			openai.WithEmbeddingModel("text-embedding-ada-002"),
			openai.WithAPIVersion("2023-07-01-preview"),
			openai.WithAPIType(openai.APITypeAzure),
			openai.WithBaseURL("API地址"), // 你的API基础URL
			openai.WithToken("API密钥"),      // 你的API密钥
			openai.WithModel("API调用的名字,由AZURE新建Model时创建"))
		if err != nil {
			log.Fatal(err)
		}
		var humanMessage = c.Query("text")

		ctx := context.Background()

		_, err = llm.Call(ctx, []schema.ChatMessage{
			schema.SystemChatMessage{Content: sysMessage},
			schema.HumanChatMessage{Content: humanMessage},
		}, llms.WithStreamingFunc(func(ctx context.Context, chunk []byte) error {
			err = conn.WriteMessage(websocket.TextMessage, chunk)
			if err != nil {
				fmt.Println("Failed to write message:", err)
				return err
			}
			return nil
		}),
		)
		if err != nil {
			log.Fatal(err)
		}
	})

	router.Run(":8085")
}

对于go代码中的

// 将这里的OPENAI_API_BASE和OPENAI_API_KEY替换为你的实际值
        llm, err := openai.NewChat(
            openai.WithEmbeddingModel("text-embedding-ada-002"),
            openai.WithAPIVersion("2023-07-01-preview"),
            openai.WithAPIType(openai.APITypeAzure),
            openai.WithBaseURL("API地址"), // 你的API基础URL
            openai.WithToken("API密钥"),      // 你的API密钥
            openai.WithModel("API调用的名字,由AZURE新建Model时创建"))
        if err != nil {
            log.Fatal(err)
        }

这里需要重点注意,使用的AZURE链接如下:

https://azure.microsoft.com/zh-cn/

需要在Azure里获取API地址,API密钥,API名放入代码中,即可实现效果

最后运行可实现如下效果,极大增加了代码编写效率

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值