实战入门Tauri-1-AI/IM

237 阅读2分钟

第一次接触Rust,决定用实战的形式学习,挑选了Tarui。 第一次写rust 可能很多错误,先做个记录,有错误以后会更正,以免误导人。

描述

用tauri做一个客户端程序,实现调用CHATGLM模型的官方API,大概流程如下

image.png

步骤

0.准备

首先,安装rust和tauri,这里就不阐述了。

1.初始化

其次,初始化一个tauri项目,这里采用的是官方的nextJS框架,目录结构(主要文件)

public //资源文件
src    //前端代码(不过多赘述)
    Chat.js   //聊天组件
src-tauri //rust代码
    src
        glm     //模块目录
            mod.rs  //模块主文件
            sse_invoke.rs //消息类
            jwt.rs //加签名类
            openapi.rs //调用平台方法类
        main.rs //rust主文件
package.json

2.主要功能编写

前端

要点:

  • 使用某厂的CHAT组件,直接生成聊天框
  • 前端调用tauri的方法
 import { invoke } from '@tauri-apps/api/tauri'//引入 
 invoke('my_custom_command'); //无参数
 invoke('my_custom_command',{ name: val.trim() }); //有参数调用

```js
'use client'
import React from 'react';
// 引入组件
import Chat,{ Bubble, useMessages } from '@chatui/core';
import { invoke } from '@tauri-apps/api/tauri'

const ChatCom = () => {
  const { messages, appendMsg, setTyping } = useMessages([]);
  async function handleSend(type, val) {
    if (type === 'text' && val.trim()) {
      appendMsg({
        type: 'text',
        content: { text: val },
        position: 'right',
      });

      setTyping(true);
      invoke('my_custom_command',{ name: val.trim() }).then((m) => {
        appendMsg({
          type: 'text',
          content: { text: m},
        });
      })
    }
  }

  function renderMessageContent(msg) {
    const { content } = msg;
    return <Bubble content={content.text} />;
  }

  return (
    <Chat
      navbar={{ title: '智能助理' }}
      messages={messages}
      renderMessageContent={renderMessageContent}
      onSend={handleSend}
    />
  );
}
export default ChatCom;

rust

主函数

// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
// 引用自定义类
mod glm;
use glm::GLM;

//定义为tauri的命令,可供前端调用
#[tauri::command]
async fn my_custom_command(name: &str) -> Result<String, String>{
  //使用连接类初始化 
  // let 声明变量
  // mut 可变变量(rust中默认不可变)
  // :冒号声明类型
  // ::引用成员类型或者方法
  // await 同步执行
  let mut rust_glm: GLM = GLM::new();
  //调用类的方法
  rust_glm.chat_init("Constants.toml",name).await;
  //返回方法
  // Ok()成功返回
  // Err()失败返回
  return Ok(rust_glm.response());
}

fn main() {
  // 创建 Tauri builder
  tauri::Builder::default()
    //注册自定义方法
    .invoke_handler(tauri::generate_handler![my_custom_command])
    // 使用上下文启动应用
    .run(tauri::generate_context!())
    // 异常情况
    .expect("error while running tauri application");
}

自定义类glm mod.rs

//引用模块
mod jwt;
mod openapi;
mod completions_invoke;

use std::io;


#[derive(Debug)]
pub struct GLM {
    res: String,
}

impl GLM {
    pub fn new() -> GLM {
        GLM {
            res: String::new(),
        }
    }
    //构造对话
    pub async fn chat_init(&mut self, config: &str,ask:&str) -> String {
        let mut api_key: Option<String>  = "xxx";
        let mut _message: String = String::new();
        if let Some(api_key:&str) = api_key {
            let api_instace: &openapi::APIKeys = openapi::APIKeys::get_instance(&*api_key);
            //构造请求chatGLM的token
            //初始化jwt类
            //生成jwt的token
            let jwt_init: jwt::Jwt = custom_jwt::CustomJwt::new(api_instace.get_user_id(), api_instace.get_user_secret());
            let jwt = jwt_init.create_jwt();
            //发送请求
            _message = completions_invoke::ReceiveInvoke::new(jwt_token, config).await.get_response_message().to_string()
            self.chatglm_response = _message.clone();
            return _message;
        } else {
            println!("API err");
        }
        String::new()
    }
    pub fn response(&self) -> String {
        self.res.clone()
    }
}


效果

image.png