Giter VIP home page Giter VIP logo

chatgpt-in-terminal's People

Contributors

ace-radom avatar lemon-2333 avatar xiaoxx970 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

chatgpt-in-terminal's Issues

feat: API Host代理配置

这是一个在别的一些chatgpt项目里普遍存在的一个功能 我觉得也可以加到这里来

https://github.com/justjavac/openai-proxy

因为这个项目以及其他一些代理项目的存在 有一些处在国外的服务器在为国内的用户提供无需全局代理的API转接服务
也就是更改API的Host到他们提供的域名上 这些网站会把所有请求原封不动转发给openai官方api 随后收到回复后再转回用户
这样的好处是这些服务器是位于国外的而且不会被GFW影响 同时也不会被openai封锁账户停用

我在隔壁也实现了这样的功能:

openai -> host = OPENAI_HOST;
openai -> endpoint = ( char* ) malloc( 256 );
sprintf( openai -> endpoint , "%s/v1/chat/completions" , openai -> host );
openai -> subscription_endpoint = ( char* ) malloc( 256 );
sprintf( openai -> subscription_endpoint , "%s/dashboard/billing/subscription" , openai -> host );
openai -> usage_endpoint = ( char* ) malloc( 256 );
sprintf( openai -> usage_endpoint , "%s/dashboard/billing/usage" , openai -> host );

实现方法也很简单 在 ChatGPT 类内新增一个成员变量存放使用的Host 然后基于这个Host在后面加上类似于 /v1/chat/completions 之类的endpoint来得到API地址

你可以考虑一下

请教一下,怎么使用这个软件作为API?

这个软件很好用,不用需要每次进入软件的界面。能不能实现在别的地方输入或者选中一句话,作为变量,在这个软件里面问chatgpt,再把答案输出返回到剪贴板或者某个变量里面。谢谢

pip 安装后直接运行gpt-term是运行的哪个py程序?

pip show gpt-term 显示gpt-term 文件夹如下
/opt/homebrew/Caskroom/miniconda/base/lib/python3.10/site-packages/gpt_term
这个文件夹下面没有chat.py这个文件
我进入这个文件夹 运行python main.py 报错

Traceback (most recent call last):
File "/opt/homebrew/Caskroom/miniconda/base/lib/python3.10/site-packages/gpt_term/main.py", line 23, in
import tiktoken
File "/opt/homebrew/Caskroom/miniconda/base/lib/python3.10/site-packages/tiktoken/init.py", line 1, in
from .core import Encoding as Encoding
File "/opt/homebrew/Caskroom/miniconda/base/lib/python3.10/site-packages/tiktoken/core.py", line 7, in
import regex
File "/opt/homebrew/Caskroom/miniconda/base/lib/python3.10/site-packages/regex/init.py", line 1, in
from .regex import *
File "/opt/homebrew/Caskroom/miniconda/base/lib/python3.10/site-packages/regex/regex.py", line 424, in
from locale import getpreferredencoding as _getpreferredencoding
ImportError: cannot import name 'getpreferredencoding' from 'locale' (/opt/homebrew/Caskroom/miniconda/base/lib/python3.10/site-packages/gpt_term/locale.py)

=======================
但是直接用pip安装后,运行gpt-term 没问题

Bug: 在配置默认lang之后每次启动都会显示switch信息

如题 我的config现在如下

[DEFAULT]
openai_api_key = sk-xxxx
openai_api_timeout = 30
auto_generate_title = True
chat_save_perfix = ./chat_history_
log_level = INFO
language = en

随后在每一次启动时 都会出现这样的情况

image

bug产生的原因是目前的逻辑是先按照locale信息初始化i18n 再读取config 但其实应该反过来 换句话说我觉得这是一个逻辑问题

global _, supported_langs
supported_langs = ["en","zh_CN","jp","de"]
local_lang = locale.getdefaultlocale()[0]
if local_lang not in supported_langs:
local_lang = "en"
_=set_lang(local_lang)

config_lang = config.get("language")
if config_lang:
if config_lang in supported_langs:
_=set_lang(config_lang)
console.print(_("gpt_term.lang_switch"))
else:
console.print(_("gpt_term.lang_config_unsupport", config_lang=config_lang))

我觉得config里的language设置的优先级应该是比读取的locale信息要高的 毕竟人家都去改config了肯定是想用自己设置的语言了 那么再输出一句switch就显得有些奇怪了
我一会儿开一个pr写一下修改后的逻辑 你可以到时候看一下

在输入未被定义的斜杠命令时的处理逻辑

在隔壁实现的一个新功能 你可以考虑一下要不要加到这来

现在输入未定义的斜杠命令的时候都是直接输出help page 但我加上一点提示会更好……?你可以考虑一下

image

我写了一套逻辑 在出现未识别的命令时判断哪一个命令和他最像 如果找到了就提示用户 没有就不提示

size_t min_levenshtein_distance = strlen( __slashcmd );
int most_similar_cmd_index = -1;
for ( int i = 0 ; i < sizeof( slash_commands ) / sizeof( char* ) - 1 ; i++ )
{
    size_t this_levenshtein_distance = get_levenshtein_distance( __slashcmd , slash_commands[i] );
    // levenshtein distance between __slashcmd and this slash command
    if ( minn( min_levenshtein_distance , this_levenshtein_distance ) < min_levenshtein_distance )
    {
        if ( get_jaccard_similarity( __slashcmd , slash_commands[i] ) >= 0.75 )
        {
            min_levenshtein_distance = this_levenshtein_distance;
            most_similar_cmd_index = i;
        } // update most similar index only if the jaccard similarity of these two greater than 75%
    }
}

原理也比较简单 比较这个未识别的命令和所有命令并判断他们是否是目前最相似的【levenshtein距离最短 jaccard相似度大于75%】如果是就把索引存下来之后输出 levenshtein和jaccard算法我记得python里有现成的实现

你可以考虑一下

/usage 命令的重写方案

repo: LaoYutang/openai-balance

这是一个用go写的程序 已经个人测试可行

参考网上大佬的方案,暂时只能使用subscription接口获取总额度,然后使用usage接口获取使用量,相减来得到余额。

最近查到的资料也基本表示这可能是目前唯一可行的方法 我在尝试怎么把这一套移植到python里 估计要一两天时间【go懂的不多】

国内大学镜像已经停止同步gpt-term的更新!

国内大学源

经过测试,大学镜像源可能都停止收录 gpt-term 的更新了,最新版本停止在 1.0.4:
清华源:https://pypi.tuna.tsinghua.edu.cn/simple/gpt-term/
中科大:https://mirrors.ustc.edu.cn/pypi/web/simple/gpt-term/
南京大学:https://mirror.nju.edu.cn/pypi/web/simple/gpt-term/
image

国内非大学源

但是以下非大学的国内源有收录最新版本,和 https://pypi.org/simple/gpt-term/ 匹配:
阿里:https://mirrors.aliyun.com/pypi/simple/gpt-term/
豆瓣:https://pypi.doubanio.com/simple/gpt-term/
image

解决方法

不知道未来阿里和豆瓣会不会也停止收录,建议就是能用官方源就用官方源,用国内源的话尽量用非大学的源。
pip可以设置多个源,如果你已经设置了国内大学源,可以增加额外源(以阿里源为例):

pip config set global.extra-index-url https://mirrors.aliyun.com/pypi/simple

经过测试,我之前的清华源没改,添加了阿里云的源作额外源后可以正常更新 gpt-term 了。

其他命令

查看当前主源:

pip config get global.index-url

查看当前额外源:

pip config get global.extra-index-url

配置多个额外源:

pip config set global.extra-index-url "<url1> <url2>..."

请问如何在terminal中直接返回答案?

临时要问gpt一个问题,而不是连续对话,希望能在shell中直接问一个问题,gpt返回答案,后面可以接着在shell中工作,不用先进入gpt-term的python 程序,问完问题再退出。谢谢

/usage命令返回错误

已在 #60 中做过描述

image

这个值显然是有问题的

image

我还没有详细测试到底是哪里出了问题 也没有别的api account用于测试 你能不能关注一下这个问题

这个问题在重构计划上一样存在

image

按照这次log 可以看到没有办法取得1.1-4.10的用量 原因不明

image

有可能这个usage get方法又失效了 不是非常清楚 还需要观察一下 你要不考虑一下也在这个pr里解决掉(解决问题/暂时关闭功能)

国内忘记使用代理,直接访问api导致账号被停用

简单提一下目前自己踩的坑,第一次用忘记加代理参数到环境变量里,等了半天gpt没回复,结果不一会就收到邮件说账号已被停用,现在风控也太严了,希望能在启动时做一个地区检测(例如检测能不能访问谷歌之类的),或者在中文说明里加个显眼提示。

20230317211323
20230317211328

标题生成prompt更新

刚刚发现目前的标题生成prompt无法保证输出的字符不是文件命名保留符
image
在这种情况下 虽然会在前台抛出error 但是仍然会显示保存成功
不知道是不是应该在prompt里加上类似于不允许使用无法用来命名的字符 (正反斜杠等) 或者在 /save 中加特殊处理

超时

返回这个提示Error: API read timed out (20s). You can retry or increase the timeout.

tokens限制输出的配色问题

在代码中 (chat.py: 233-235):

console.print(Panel(f"[dim blue]Total Tokens:[/]\t{chatGPT.total_tokens}\n"
                    f"[dim green]Current Tokens:[/]\t{chatGPT.current_tokens}/[black]{tokens_limit}",
                    title='token_summary', title_align='left', width=35, style='dim'))

tokens_limit 的输出设为了纯黑 但这个配色在深色终端配色内是处于基本不可见的状态
不知道改为无指定配色或红色是否会更合适

结果中的代码复制,每一行都有一个空格在前面

非常好的项目,一直在用,但是有一个小问题一直困扰我

结果中的代码复制粘贴后,每一行都有一个空格在行首,希望能改进一下。或者有没有快捷方式能一键复制答案中的代码,而不复制答案中的描述。

CleanShot_2024_01_29_203555

ps:另外gpt-4-vision-preview这个模型每次回答只有一句话就断了

祝好

pip3 安装后如何启动

在zsh终端中pip3下载安装好后,找不到gpt-term这个命令。或者还要配下环境变量?

关于改进添加功能提议

我把这个项目folk了
并且把其中的代码重新整理了一下,而且还初步支持了Poe.com的API
就是不知道作者对于这个项目目录结构这些能否接受合并(毕竟改的却是很大)
其中Poe的Api已经是初步可用状态,但是其他的附加项我暂时还没加入,例如配置文件,命令行参数
我未来预计还会再加上i8n本地化
我的folk地址

feat: 用于列出目前各个设置的值的命令

隔壁重构计划基本功能achieve啦 虽然没能用纯C完成 但也没有像刚开始想的那样自己造一堆轮子 只自己写了个富文本库和markdown解析器 SSE事件用libcurl也直接解决了 总之还是挺顺利的 你有兴趣可以去看下ww


这也是一个我加在重构计划里的新功能
image
总之就是用一个命令直接打印出目前所有设置项的值 我用的是 /list 感觉在有人忘了目前比如说timeout设的多少或者temperature设的多少直接用这个命令就能看 你可以考虑一下【考虑到i18n也在写所以就没直接开pr 这个实现起来也应该很简单】

POST地址错误

运行chat.py输入问题后,会遇到错误:

openai.error.InvalidRequestError: Invalid URL (POST /v1/chat/completions)

我用的openai版本是0.27.2

FEAT: 清屏功能

C写破防了来提个小建议

慢慢发现如果聊天过多中间又delete过的话 翻聊天记录真的很烦 如果加一个清屏的命令可能会更好
比如加一个类似于 /clear 之类的命令

实现方法也很简单 在各个平台上都有原生的清屏命令 win下是 cls linux下是 clear mac下应该也是 但我不知道这样清屏是不是会对prompt_toolkit产生影响 可能要测试一下

Error count token when using 16k model

Hi, welcome to chat with GPT. Type `/help` to display available commands.
Traceback (most recent call last):
  File "/Users/xxx/.local/bin/chat", line 7, in <module>
    main()
  File "/Users/xxx/Repos/chatgpt-in-terminal/gpt_term/main.py", line 1125, in main
    chat_gpt = ChatGPT(api_key, api_timeout)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/xxx/Repos/chatgpt-in-terminal/gpt_term/main.py", line 117, in __init__
    self.current_tokens = count_token(self.messages)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/xxx/Repos/chatgpt-in-terminal/gpt_term/main.py", line 616, in count_token
    encoding = tiktoken.get_encoding("cl100k_base")
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/xxx/Repos/chatgpt-in-terminal/.venv/lib/python3.11/site-packages/tiktoken/registry.py", line 63, in get_encoding
    enc = Encoding(**constructor())
                     ^^^^^^^^^^^^^
  File "/Users/xxx/Repos/chatgpt-in-terminal/.venv/lib/python3.11/site-packages/tiktoken_ext/openai_public.py", line 64, in cl100k_base
    mergeable_ranks = load_tiktoken_bpe(
                      ^^^^^^^^^^^^^^^^^^
  File "/Users/xxx/Repos/chatgpt-in-terminal/.venv/lib/python3.11/site-packages/tiktoken/load.py", line 117, in load_tiktoken_bpe
    return {
           ^
  File "/Users/xxx/Repos/chatgpt-in-terminal/.venv/lib/python3.11/site-packages/tiktoken/load.py", line 119, in <dictcomp>
    for token, rank in (line.split() for line in contents.splitlines() if line)
        ^^^^^^^^^^^
ValueError: not enough values to unpack (expected 2, got 1)

在stream模式下让用户选择显示模式

https://rich.readthedocs.io/en/latest/live.html#vertical-overflow

当前是使用默认的ellipsis模式,当生成内容超出屏幕的时候,会在最下方显示三个小点,等所有内容生成完成的时候会一次性显示出剩余内容。这个模式在内容少的时候还好,如果内容很多,那内容超出屏幕后用户又只剩下了等待,内容越长等待越久。

当时考虑使用另一种模式:visible,这个模式能持续的flow输出答案,内容超过窗口高度的时候就向下滚动输出。这个模式能很好的解决用户的等待问题,但是缺点就是,不能在这个时候滚动屏幕,否则屏幕将快速刷新,导致屏幕外的内容彻底失控,最后只能正确显示当前屏幕的内容。

但是现在我实际使用下来,发现如果内容太长,我还是愿意不滚动屏幕,然后选择visible模式,看着所有回答慢慢出现。所以稍后打算把这个模式的选择做成/stream的子命令

gen_title函数的linux兼容性错误;title自动生成和CLI标题更改

gen_title 函数加入后在个人windows端上可以正常使用 但在WSL内的linux环境中却在启动时报错

Traceback (most recent call last):
  File "/mnt/e/forks/chatgpt-in-terminal/chat.py", line 74, in <module>
    class ChatGPT:
  File "/mnt/e/forks/chatgpt-in-terminal/chat.py", line 210, in ChatGPT
    def gen_title(self) -> str | None:
TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'

尚不清楚这种错误是因为python版本导致还是linux环境导致 mac的话因为我手头没有mac设备所以没法测试

个人系统环境:

  • Windows 11
    • cPython 3.10.8
  • Windows Subsystem for Linux
    • Debian 11.6 (Subsystem v1.14.0.0)
      • cPython 3.9.2

另外我在尝试在一次chat中的第一次conversation完成后分离一个线程出来生成标题 生成成功后更改终端的标题
目前更改标题的函数在windows和WSL上测试过了 但我还没写太多 你看到了之后要不考虑一下要不要加入这个功能

Tokens统计

这不一定是一个错误 更多是一个疑问

在调用 /tokens 命令后一直会输出两个值 total tokenscurrent tokens 但根据重构的代码看 current tokens 就已经是上下文的总tokens数量 那么 total tokens 代表的是什么值呢
在源码中 (chat.py: 165-166) 可以看到每一次消息回复后都会重新统计一次上下文总tokens数量 但又将这个数量直接加到 total_tokens 里:

self.current_tokens = count_token(self.messages)
self.total_tokens += self.current_tokens

这样统计出的 total_tokens 是否是在重复统计上下文长度?不知道这样计算出来的总tokens是不是错的

重构代码以适用于外部调用模块

使用效果(以 claude API 为例):

import anthropic
from gpt_term import Term

api_key = "xxx"

class ClaudeTerm(Term):
    def __init__(self, api_key):
        super().__init__(api_key) 
        self.model = 'claude-v1.3-100k'
        self.c = anthropic.Client(api_key)
        self.count_tokens = anthropic.count_tokens

    def get_claude_prompt(self):
        # 转换 {"role": "user|assistant", "content": message} 到 user: message assistant: message
        claude_prompt = ""
        for message in self.messages:
            claude_prompt += (": ").join(message.values()) + '\n'
        return claude_prompt

    def send_request(self, data):
        # 重构send_request函数来返回claude的response
        response = self.c.completion_stream(
            prompt=self.get_claude_prompt(),
            stop_sequences=[anthropic.HUMAN_PROMPT],
            max_tokens_to_sample=200,
            model=data["model"],
            stream=data["stream"],
        )
        return response

    def process_stream_response(self, response):
        for data in response:
            yield data
    
claude_term = ClaudeTerm(api_key)
claude_term.run()

不知不觉写了好多,原则就是通过重构 gpt_term 中负责终端交互的类能复用这个终端。

至于“负责终端交互的类(Term)”,就需要从现有的代码抽取出来,保证最小功能,包括最小的斜杠命令。

配置文件新增大部分可以用斜杠命令配置的项目

现在的结构是配置文件和斜杠命令互不干扰,除了timeout可以在配置文件里永久配置,也可以在斜杠命令中临时更改。
但是其实很多斜杠命令的操作也应该放到配置文件里永久配置,比如model、temperature、system prompt,包括 raw, multi, stream。它们可以像timeout一样以参数的形式在class初始化的时候传入,也不影响后续运行中用斜杠命令修改

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.