计划在Unity中写一个简单的功能调用远程服务器运行的大模型api,需要发送的json和接收json信息。
很重要的两点就是:
1. python服务器端必须是异步(下文中写的async)。
2. 他们之间的数据结构必须要一样,下文中的例子是都有message的键
以下是对应的python服务器端的代码:
from fastapi import FastAPI, Request
from pydantic import BaseModel
import uvicorn
app = FastAPI()
class ApiData(BaseModel):
message: str
@app.post("/")
async def process_message(request: Request):
data = await request.json()
api_data = ApiData(**data)
message = api_data.message
message = "在我律师来到之前,我是不会回答你的问题的"
return {"message": message}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
以下是C# 客户端代码:
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using static UnityEngine.UI.Image;
public class LLMClient : MonoBehaviour
{
public Transform contentParent;
public string ReadInputFieldText;
public string UrlInputFieldText;
public Button myButton;
public ScrollRect scrollView;
public Text contentText;
// Start is called before the first frame update
void Start()
{
myButton.onClick.AddListener(sendMessageButtonClick);
}
public void sendMessageButtonClick()
{
Debug.Log("sendMessageButtonClick");
string inputText = GameObject.Find(ReadInputFieldText).GetComponent<InputField>().text;
string urlText = GameObject.Find(UrlInputFieldText).GetComponent<InputField>().text;
Debug.Log("Input Field 内容: " + inputText);
// 将玩家消息显示到 Scroll View
AddMessageToScrollView("Player: " , inputText);
// 创建一个用于存储数据的对象
ApiData data = new ApiData();
data.message = inputText;
// 将数据序列化为 JSON 字符串
string bodyJson = JsonUtility.ToJson(data);
// 发送请求到远程 API
StartCoroutine(SendRequestToAPI(urlText,bodyJson));
}
private IEnumerator SendRequestToAPI(string urlText, string bodyJson)
{
// 发送 POST 请求
UnityWebRequest _request = new UnityWebRequest(urlText, "POST");
// 创建 UploadHandler 并设置 JSON 数据
byte[] bodyRaw = new System.Text.UTF8Encoding().GetBytes(bodyJson);
_request.uploadHandler = new UploadHandlerRaw(bodyRaw);
_request.SetRequestHeader("Content-Type", "application/json");
_request.downloadHandler = new DownloadHandlerBuffer();
yield return _request.SendWebRequest();
if (_request.result == UnityWebRequest.Result.Success)
{
Debug.Log("Pass! ");
var response = JsonUtility.FromJson<ApiData>(_request.downloadHandler.text);
Debug.Log(response);
// 将回答内容添加到 Scroll View
AddMessageToScrollView("LLM",response.message);
}
else
{
Debug.Log($"Requester Error: {_request.error}");
}
_request.Dispose();
LayoutRebuilder.ForceRebuildLayoutImmediate(contentParent.GetComponent<RectTransform>());
}
private void AddMessageToScrollView(string identity,string message)
{
// 将新消息追加到 contentText 的文本内容中
contentText.text += "\n";
contentText.text += identity + "\n";
contentText.text += message + "\n";
// 确保 ScrollView 中的内容更新
Canvas.ForceUpdateCanvases();
// 设置 ScrollView 的垂直滚动位置为 0,也就是滚动到最底部
// scrollView.verticalNormalizedPosition = 0f;
}
// Update is called once per frame
void Update()
{
}
[System.Serializable]
class ApiData
{
public string message;
}
}