Skip to content

Commit

Permalink
Merge pull request #2 from Ace-Radom/dev
Browse files Browse the repository at this point in the history
HTTP Response Code Parse; Input History Record; Slash Commands Update; Tokens Count
  • Loading branch information
Ace-Radom authored Apr 27, 2023
2 parents 6820759 + 98c22ea commit c33de4b
Show file tree
Hide file tree
Showing 28 changed files with 865 additions and 383 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ jobs:
- name: Install libjansson
run: sudo apt install libjansson-dev -y

- name: Install GNU libreadline
run: sudo apt install libreadline-dev -y

- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
Expand Down
9 changes: 4 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ cmake_minimum_required(VERSION 3.10)
project(cGPTerm VERSION 1.0)

set(CMAKE_C_FLAGS "-Wall -g")
set(CMAKE_CXX_FLAGS "-Wall -g")
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)
add_definitions(-D _DEFAULT_SOURCE)
add_definitions(-D _GNU_SOURCE)

set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin)
Expand All @@ -18,8 +17,8 @@ add_library(iniparser SHARED
include_directories(${CMAKE_SOURCE_DIR}/include)
add_subdirectory(${CMAKE_SOURCE_DIR}/src)

add_executable(main main.c ${UTILS})
target_link_libraries(main
add_executable(cgpterm main.c ${UTILS})
target_link_libraries(cgpterm
utils
# ncursesw
ezylog
Expand Down
58 changes: 41 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ Chat with GPT in Terminal

## 简介

这是一个将 @xiaoxx970 的使用Python实现的 [GPT-Term](https://github.com/xiaoxx970/chatgpt-in-terminal) 项目以C/C++实现的方式重构的计划
这是一个将 @xiaoxx970 的使用Python实现的 [GPT-Term](https://github.com/xiaoxx970/chatgpt-in-terminal) 项目以近乎纯C实现的方式重构的计划

目标为用C++实现CLI界面交互 C实现后端 尽可能还原原版界面和各项功能 但在遇到还原功能困难的时候会选择用其他的实现方法替代
目标为用近乎纯C实现CLI界面交互和后端 尽可能还原原版界面和各项功能 但在遇到还原功能困难的时候会选择用其他的实现方法替代【比如tokens计算使用了Rust现成的库 也因此编译需要Rust环境】

开发工作在Linux环境下进行 由于这个项目更多是出于好玩和C语言练习的目的而发起的 目前不会太考虑可移植性问题

~~不要问我为什么用C++做前端 问就是尝试用C做前端时候宽字符报错了一晚上~~

自现在起 main分支下是最近的功能实现版本 开发分支位于dev

### 项目进度
Expand All @@ -21,41 +19,67 @@ Chat with GPT in Terminal
- 自动创建 `config.ini` 配置文件
- 通过命令行对 `config.ini` 内的值进行更改
- 自建log库 支持 `DEBUG` `INFO` `ERROR` `FATAL` 层级
- 基本的API访问:可以正常与ChatGPT交流 但还没有任何错误特判
- 基本的API访问:可以正常与ChatGPT交流和解析错误
- 基本的交互界面
- 在等待GPT回复时显示 `ChatGPT is thinking...`
- 在等待回复时锁死终端 不回显并隐藏光标 在回复后解锁
- 历史记录功能 记录在本次运行中的每一次输入
- 已经实现的斜杠命令可以按Tab补全【此处的补全逻辑和原版不同 在有多项可能时不会补全而是显示所有可能命令】
- 基于 [tiktoken-rs](https://github.com/zurawiki/tiktoken-rs) 的tokens计算
- 部分斜杠命令 (`/tokens` `/timeout` `/help` `/exit`)

目前正在开发的功能:

- 进一步扩充API交互 增加错误返回解析
- 实现部分底层的斜杠命令:`/timeout` `/model` `/last` `/help` `/exit`
- tokens 统计 逐步实现 `/tokens` 命令
- credit 统计 逐步实现 `/usage` 命令
- `/copy` 命令 包括整个回答和代码段的拷贝
- 优化斜杠命令自动补全的界面
- 在输入未定义的斜杠命令时提示一个用户最有可能想输入的命令
- 自建/封装富文本库 以一种类似于python的rich库的方式输出富文本

已经计划实现 但在研究实现方法的功能:

- 多行模式
- 绑定Tabs 实现斜杠命令自动补全
- 在CLI上的斜杠命令匹配提示
- 在输入未定义的斜杠命令时提示一个用户最有可能想输入的命令
- 守护线程和自动标题生成
- 聊天记录保存和加载

目前计划中 但不清楚能力是否允许实现的功能:

- 自建/封装富文本库 以一种类似于python的rich库的方式输出富文本

目的是为了让界面更好看 ~~不然还能因为什么啊喂~~
- 自建段落式Markdown解析库 用于适配流式输出的文本解析【若找到更好的替代方法会取消】
- 流式输出
- 使用C/C++实现一套tiktoken分词库 替代目前使用的Rust分词库库

### 编译 项目依赖

编译需要GCC和Rust环境

首先 clone本仓库

### 项目依赖
```
git clone https://github.com/Ace-Radom/cGPTerm
```

| 依赖库名 | 开发用版本 | 库功能 | 安装命令
然后 安装所有C的依赖项

| 依赖库名 | 开发用版本 | 库功能 | 安装命令 (Debian, Ubuntu) |
| --- | --- | --- | --- |
| `argtable` | 2.13 | 命令行参数解析 | `sudo apt install libargtable2-dev` |
| `curl4-openssl` | 7.74.0 | API对接 | `sudo apt install libcurl4-openssl-dev` |
| `jansson` | 2.13.1 | json解析 | `sudo apt install libjansson-dev` |
| `jansson` | 2.13.1 | json解析 | `sudo apt install libjansson-dev` |
| `GNU readline` | 8.1 | 命令行输入 历史记录 Tab补全 | `sudo apt install libreadline-dev` |

随后 依次执行以下命令

```shell
mkdir build && cd build
cmake ..
make
```

如果一切正常 所有生成的文件都会被存放在项目根文件夹下的bin文件夹内

不过此处编译的是Debug版本 若需编译Release版本可以使用

```
cmake -DCMAKE_BUILD_TYPE=Release ..
make
```
27 changes: 27 additions & 0 deletions include/cli.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef _CLI_H_
#define _CLI_H_

#ifdef __cplusplus
extern "C" {
#endif

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>

#include<pthread.h>
#include<readline/readline.h>
#include<readline/history.h>

#include"openai_api.h"
#include"cli/toolkit.h"

int start_CLI();
// this is an api for main.c

#ifdef __cplusplus
}
#endif

#endif
24 changes: 0 additions & 24 deletions include/cli.hpp

This file was deleted.

28 changes: 28 additions & 0 deletions include/cli/slashcmd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef _SLASHCMD_H_
#define _SLASHCMD_H_

#ifdef __cplusplus
extern "C" {
#endif

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#include<readline/readline.h>

#include"openai_api.h"
#include"ezylog.h"
#include"utils.h"

extern const char* slash_commands[];

int handle_slash_command( const char* __slashcmd );

void print_slash_command_help();

#ifdef __cplusplus
}
#endif

#endif
48 changes: 48 additions & 0 deletions include/cli/toolkit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef _TOOLKIT_H_
#define _TOOLKIT_H_

#ifdef __cplusplus
extern "C" {
#endif

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<termios.h>

#include<readline/readline.h>

#include"slashcmd.h"

#define HIDE_CURSOR "\033[?25l"
#define SHOW_CURSOR "\033[?25h"

extern struct termios ori_attr;

// ===============================================
// ================== CLI Tools ==================
// ===============================================

void get_original_terattr();
void reset_terattr();
void turn_off_echo();

void write_ANSI( const char* __ANSI );

void print_wait_msg( const char* __msg );

char** rl_attempted_completion_callback( const char* text , int start , int end );
char* rl_completion_search( const char* text , int state );

// ===============================================
// ================== str Tools ==================
// ===============================================

char* trim( char* __str );

#ifdef __cplusplus
}
#endif

#endif
26 changes: 0 additions & 26 deletions include/cli/toolkit.hpp

This file was deleted.

37 changes: 0 additions & 37 deletions include/cvector.h

This file was deleted.

8 changes: 6 additions & 2 deletions include/openai_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ extern "C" {

#include"ezylog.h"
#include"utils.h"
#include"openai_api/tiktokens.h"

typedef struct {
char* endpoint;
struct curl_slist* headers;
json_t* messages;
char* model;
int tokens_limit;
long long total_tokens_spent;
long total_tokens_spent;
int current_tokens;
char* title;

Expand All @@ -40,11 +41,14 @@ typedef struct {

extern openai_t* openai;
extern bool request_working;
extern long HTTP_Response_code;

void openai_init();
void openai_send_chatrequest( openai_datatransfer_t* __data );
void openai_send_chatrequest( void* __data );
void openai_free();

void openai_msg_popback();

#ifdef __cplusplus
}
#endif
Expand Down
23 changes: 23 additions & 0 deletions include/openai_api/tiktokens.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef _TIKTOKENS_H_
#define _TIKTOKENS_H_

#ifdef __cplusplus
extern "C" {
#endif

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#include<jansson.h>

extern long count_tokens_cl100k_base( const char* ptr );
// this is a rust FFI used to count tokens of a message with cl100k_base

long count_tokens_message( const json_t* __msg );

#ifdef __cplusplus
}
#endif

#endif
Loading

0 comments on commit c33de4b

Please sign in to comment.