mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-06-03 19:17:10 +08:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2db4673392 | ||
|
|
38619db629 | ||
|
|
930fd436ea | ||
|
|
98b8ff2fc8 | ||
|
|
d0662683f9 | ||
|
|
957f2574a9 | ||
|
|
109b362ebd | ||
|
|
ff3fdfa738 | ||
|
|
e2636ed54a | ||
|
|
dbe2f17e1a | ||
|
|
4dc535673f | ||
|
|
f414b6408e | ||
|
|
3aa2e6a04d | ||
|
|
1963ff273f | ||
|
|
bb737a71d5 |
10
.github/workflows/deploy-image.yml
vendored
10
.github/workflows/deploy-image.yml
vendored
@@ -28,6 +28,12 @@ jobs:
|
|||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Log in to the Container registry
|
- name: Log in to the Container registry
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
@@ -39,7 +45,9 @@ jobs:
|
|||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v4
|
||||||
with:
|
with:
|
||||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
images: |
|
||||||
|
${{ env.IMAGE_NAME }}
|
||||||
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ class ChatGPTBot(Bot, OpenAIImage):
|
|||||||
if args is None:
|
if args is None:
|
||||||
args = self.args
|
args = self.args
|
||||||
response = openai.ChatCompletion.create(api_key=api_key, messages=session.messages, **args)
|
response = openai.ChatCompletion.create(api_key=api_key, messages=session.messages, **args)
|
||||||
|
# logger.debug("[CHATGPT] response={}".format(response))
|
||||||
# logger.info("[ChatGPT] reply={}, total_tokens={}".format(response.choices[0]['message']['content'], response["usage"]["total_tokens"]))
|
# logger.info("[ChatGPT] reply={}, total_tokens={}".format(response.choices[0]['message']['content'], response["usage"]["total_tokens"]))
|
||||||
return {
|
return {
|
||||||
"total_tokens": response["usage"]["total_tokens"],
|
"total_tokens": response["usage"]["total_tokens"],
|
||||||
|
|||||||
@@ -57,25 +57,25 @@ def num_tokens_from_messages(messages, model):
|
|||||||
"""Returns the number of tokens used by a list of messages."""
|
"""Returns the number of tokens used by a list of messages."""
|
||||||
import tiktoken
|
import tiktoken
|
||||||
|
|
||||||
if model == "gpt-3.5-turbo" or model == "gpt-35-turbo":
|
if model in ["gpt-3.5-turbo-0301", "gpt-35-turbo"]:
|
||||||
return num_tokens_from_messages(messages, model="gpt-3.5-turbo-0301")
|
return num_tokens_from_messages(messages, model="gpt-3.5-turbo")
|
||||||
elif model == "gpt-4":
|
elif model in ["gpt-4-0314", "gpt-4-0613", "gpt-4-32k", "gpt-4-32k-0613", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-16k-0613"]:
|
||||||
return num_tokens_from_messages(messages, model="gpt-4-0314")
|
return num_tokens_from_messages(messages, model="gpt-4")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
encoding = tiktoken.encoding_for_model(model)
|
encoding = tiktoken.encoding_for_model(model)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logger.debug("Warning: model not found. Using cl100k_base encoding.")
|
logger.debug("Warning: model not found. Using cl100k_base encoding.")
|
||||||
encoding = tiktoken.get_encoding("cl100k_base")
|
encoding = tiktoken.get_encoding("cl100k_base")
|
||||||
if model == "gpt-3.5-turbo-0301":
|
if model == "gpt-3.5-turbo":
|
||||||
tokens_per_message = 4 # every message follows <|start|>{role/name}\n{content}<|end|>\n
|
tokens_per_message = 4 # every message follows <|start|>{role/name}\n{content}<|end|>\n
|
||||||
tokens_per_name = -1 # if there's a name, the role is omitted
|
tokens_per_name = -1 # if there's a name, the role is omitted
|
||||||
elif model == "gpt-4-0314":
|
elif model == "gpt-4":
|
||||||
tokens_per_message = 3
|
tokens_per_message = 3
|
||||||
tokens_per_name = 1
|
tokens_per_name = 1
|
||||||
else:
|
else:
|
||||||
logger.warn(f"num_tokens_from_messages() is not implemented for model {model}. Returning num tokens assuming gpt-3.5-turbo-0301.")
|
logger.warn(f"num_tokens_from_messages() is not implemented for model {model}. Returning num tokens assuming gpt-3.5-turbo.")
|
||||||
return num_tokens_from_messages(messages, model="gpt-3.5-turbo-0301")
|
return num_tokens_from_messages(messages, model="gpt-3.5-turbo")
|
||||||
num_tokens = 0
|
num_tokens = 0
|
||||||
for message in messages:
|
for message in messages:
|
||||||
num_tokens += tokens_per_message
|
num_tokens += tokens_per_message
|
||||||
|
|||||||
@@ -223,9 +223,9 @@ class ChatChannel(Channel):
|
|||||||
return self._decorate_reply(context, reply)
|
return self._decorate_reply(context, reply)
|
||||||
if context.get("isgroup", False):
|
if context.get("isgroup", False):
|
||||||
reply_text = "@" + context["msg"].actual_user_nickname + "\n" + reply_text.strip()
|
reply_text = "@" + context["msg"].actual_user_nickname + "\n" + reply_text.strip()
|
||||||
reply_text = conf().get("group_chat_reply_prefix", "") + reply_text
|
reply_text = conf().get("group_chat_reply_prefix", "") + reply_text + conf().get("group_chat_reply_suffix", "")
|
||||||
else:
|
else:
|
||||||
reply_text = conf().get("single_chat_reply_prefix", "") + reply_text
|
reply_text = conf().get("single_chat_reply_prefix", "") + reply_text + conf().get("single_chat_reply_suffix", "")
|
||||||
reply.content = reply_text
|
reply.content = reply_text
|
||||||
elif reply.type == ReplyType.ERROR or reply.type == ReplyType.INFO:
|
elif reply.type == ReplyType.ERROR or reply.type == ReplyType.INFO:
|
||||||
reply.content = "[" + str(reply.type) + "]\n" + reply.content
|
reply.content = "[" + str(reply.type) + "]\n" + reply.content
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"open_ai_api_key": "YOUR API KEY",
|
"open_ai_api_key": "YOUR API KEY",
|
||||||
"model": "gpt-3.5-turbo",
|
"model": "gpt-3.5-turbo",
|
||||||
"proxy": "",
|
"proxy": "",
|
||||||
|
"hot_reload": false,
|
||||||
"single_chat_prefix": [
|
"single_chat_prefix": [
|
||||||
"bot",
|
"bot",
|
||||||
"@bot"
|
"@bot"
|
||||||
|
|||||||
@@ -22,8 +22,10 @@ available_setting = {
|
|||||||
# Bot触发配置
|
# Bot触发配置
|
||||||
"single_chat_prefix": ["bot", "@bot"], # 私聊时文本需要包含该前缀才能触发机器人回复
|
"single_chat_prefix": ["bot", "@bot"], # 私聊时文本需要包含该前缀才能触发机器人回复
|
||||||
"single_chat_reply_prefix": "[bot] ", # 私聊时自动回复的前缀,用于区分真人
|
"single_chat_reply_prefix": "[bot] ", # 私聊时自动回复的前缀,用于区分真人
|
||||||
"group_chat_prefix": ["@bot"], # 群聊时包含该前缀则会触发机器人回复
|
"single_chat_reply_suffix": "", # 私聊时自动回复的后缀,\n 可以换行
|
||||||
|
"group_chat_prefix": ["@bot"], # 群聊时包含该前缀则会触发机器人回复
|
||||||
"group_chat_reply_prefix": "", # 群聊时自动回复的前缀
|
"group_chat_reply_prefix": "", # 群聊时自动回复的前缀
|
||||||
|
"group_chat_reply_suffix": "", # 群聊时自动回复的后缀,\n 可以换行
|
||||||
"group_chat_keyword": [], # 群聊时包含该关键词则会触发机器人回复
|
"group_chat_keyword": [], # 群聊时包含该关键词则会触发机器人回复
|
||||||
"group_at_off": False, # 是否关闭群聊时@bot的触发
|
"group_at_off": False, # 是否关闭群聊时@bot的触发
|
||||||
"group_name_white_list": ["ChatGPT测试群", "ChatGPT测试群2"], # 开启自动回复的群名称列表
|
"group_name_white_list": ["ChatGPT测试群", "ChatGPT测试群2"], # 开启自动回复的群名称列表
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
version: '2.0'
|
version: '2.0'
|
||||||
services:
|
services:
|
||||||
chatgpt-on-wechat:
|
chatgpt-on-wechat:
|
||||||
build:
|
|
||||||
context: ./
|
|
||||||
dockerfile: Dockerfile.alpine
|
|
||||||
image: zhayujie/chatgpt-on-wechat
|
image: zhayujie/chatgpt-on-wechat
|
||||||
container_name: sample-chatgpt-on-wechat
|
container_name: chatgpt-on-wechat
|
||||||
environment:
|
environment:
|
||||||
OPEN_AI_API_KEY: 'YOUR API KEY'
|
OPEN_AI_API_KEY: 'YOUR API KEY'
|
||||||
|
MODEL: 'gpt-3.5-turbo'
|
||||||
OPEN_AI_PROXY: ''
|
OPEN_AI_PROXY: ''
|
||||||
SINGLE_CHAT_PREFIX: '["bot", "@bot"]'
|
SINGLE_CHAT_PREFIX: '["bot", "@bot"]'
|
||||||
SINGLE_CHAT_REPLY_PREFIX: '"[bot] "'
|
SINGLE_CHAT_REPLY_PREFIX: '"[bot] "'
|
||||||
@@ -15,6 +13,9 @@ services:
|
|||||||
GROUP_NAME_WHITE_LIST: '["ChatGPT测试群", "ChatGPT测试群2"]'
|
GROUP_NAME_WHITE_LIST: '["ChatGPT测试群", "ChatGPT测试群2"]'
|
||||||
IMAGE_CREATE_PREFIX: '["画", "看", "找"]'
|
IMAGE_CREATE_PREFIX: '["画", "看", "找"]'
|
||||||
CONVERSATION_MAX_TOKENS: 1000
|
CONVERSATION_MAX_TOKENS: 1000
|
||||||
SPEECH_RECOGNITION: "False"
|
SPEECH_RECOGNITION: 'False'
|
||||||
CHARACTER_DESC: '你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。'
|
CHARACTER_DESC: '你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。'
|
||||||
EXPIRES_IN_SECONDS: 3600
|
EXPIRES_IN_SECONDS: 3600
|
||||||
|
USE_LINKAI: 'False'
|
||||||
|
LINKAI_API_KEY: ''
|
||||||
|
LINKAI_APP_CODE: ''
|
||||||
@@ -34,14 +34,14 @@ class Hello(Plugin):
|
|||||||
e_context["context"].type = ContextType.TEXT
|
e_context["context"].type = ContextType.TEXT
|
||||||
msg: ChatMessage = e_context["context"]["msg"]
|
msg: ChatMessage = e_context["context"]["msg"]
|
||||||
e_context["context"].content = f'请你随机使用一种风格说一句问候语来欢迎新用户"{msg.actual_user_nickname}"加入群聊。'
|
e_context["context"].content = f'请你随机使用一种风格说一句问候语来欢迎新用户"{msg.actual_user_nickname}"加入群聊。'
|
||||||
e_context.action = EventAction.CONTINUE # 事件继续,交付给下个插件或默认逻辑
|
e_context.action = EventAction.BREAK # 事件结束,进入默认处理逻辑
|
||||||
return
|
return
|
||||||
|
|
||||||
if e_context["context"].type == ContextType.PATPAT:
|
if e_context["context"].type == ContextType.PATPAT:
|
||||||
e_context["context"].type = ContextType.TEXT
|
e_context["context"].type = ContextType.TEXT
|
||||||
msg: ChatMessage = e_context["context"]["msg"]
|
msg: ChatMessage = e_context["context"]["msg"]
|
||||||
e_context["context"].content = f"请你随机使用一种风格介绍你自己,并告诉用户输入#help可以查看帮助信息。"
|
e_context["context"].content = f"请你随机使用一种风格介绍你自己,并告诉用户输入#help可以查看帮助信息。"
|
||||||
e_context.action = EventAction.CONTINUE # 事件继续,交付给下个插件或默认逻辑
|
e_context.action = EventAction.BREAK # 事件结束,进入默认处理逻辑
|
||||||
return
|
return
|
||||||
|
|
||||||
content = e_context["context"].content
|
content = e_context["context"].content
|
||||||
|
|||||||
@@ -114,18 +114,19 @@ $tool reset: 重置工具。
|
|||||||
---
|
---
|
||||||
|
|
||||||
###### 注1:带*工具需要获取api-key才能使用(在config.json内的kwargs添加项),部分工具需要外网支持
|
###### 注1:带*工具需要获取api-key才能使用(在config.json内的kwargs添加项),部分工具需要外网支持
|
||||||
#### [申请方法](https://github.com/goldfishh/chatgpt-tool-hub/blob/master/docs/apply_optional_tool.md)
|
## [工具的api申请方法](https://github.com/goldfishh/chatgpt-tool-hub/blob/master/docs/apply_optional_tool.md)
|
||||||
|
|
||||||
## config.json 配置说明
|
## config.json 配置说明
|
||||||
###### 默认工具无需配置,其它工具需手动配置,一个例子:
|
###### 默认工具无需配置,其它工具需手动配置,以增加morning-news和bing-search两个工具为例:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"tools": ["wikipedia", "你想要添加的其他工具"], // 填入你想用到的额外工具名
|
"tools": ["bing-search", "news", "你想要添加的其他工具"], // 填入你想用到的额外工具名,这里加入了工具"bing-search"和工具"news"(news工具会自动加载morning-news、finance-news等子工具)
|
||||||
"kwargs": {
|
"kwargs": {
|
||||||
"debug": true, // 当你遇到问题求助时,需要配置
|
"debug": true, // 当你遇到问题求助时,需要配置
|
||||||
"request_timeout": 120, // openai接口超时时间
|
"request_timeout": 120, // openai接口超时时间
|
||||||
"no_default": false, // 是否不使用默认的4个工具
|
"no_default": false, // 是否不使用默认的4个工具
|
||||||
// 带*工具需要申请api-key,在这里填入,api_name参考前述`申请方法`
|
"bing_subscription_key": "4871f273a4804743",//带*工具需要申请api-key,这里填入了工具bing-search对应的api,api_name参考前述`工具的api申请方法`
|
||||||
|
"morning_news_api_key": "5w1kjNh9VQlUc",// 这里填入了morning-news对应的api,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
openai==0.27.2
|
openai>=0.27.8
|
||||||
HTMLParser>=0.0.2
|
HTMLParser>=0.0.2
|
||||||
PyQRCode>=1.2.1
|
PyQRCode>=1.2.1
|
||||||
qrcode>=7.4.2
|
qrcode>=7.4.2
|
||||||
requests>=2.28.2
|
requests>=2.28.2
|
||||||
chardet>=5.1.0
|
chardet>=5.1.0
|
||||||
Pillow
|
Pillow
|
||||||
pre-commit
|
pre-commit
|
||||||
|
|||||||
Reference in New Issue
Block a user