fix odoo 13 gpt
@@ -1,5 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020-Present InTechual Solutions. (<https://intechualsolutions.com/>)
|
||||
|
||||
# from . import controllers
|
||||
from . import models
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
# Copyright (c) 2020-Present InTechual Solutions. (<https://intechualsolutions.com/>)
|
||||
|
||||
{
|
||||
'name': 'Latest ChatGPT AI Center. GPT 3.5 Turbo, Dall-E Image.Multi Robot Support. Chat and Training',
|
||||
'version': '13.23.03.05',
|
||||
'name': 'Latest ChatGPT4 AI Center. GPT 4 for image, Dall-E Image.Multi Robot Support. Chat and Training',
|
||||
'version': '13.23.03.31',
|
||||
'author': 'Sunpop.cn',
|
||||
'company': 'Sunpop.cn',
|
||||
'maintainer': 'Sunpop.cn',
|
||||
@@ -21,7 +21,7 @@
|
||||
'license': 'AGPL-3',
|
||||
'images': ['static/description/banner.gif'],
|
||||
'summary': '''
|
||||
ChatGpt Odoo AI Center. Multi Odoo ChatGPT Robot. Support chatgpt 3.5 turbo, text-davinci, DALL·E, Integration All ChatGpt Api.
|
||||
ChatGpt Odoo AI Center. Multi Odoo ChatGPT Robot. Support chatgpt 4 image. 3.5 turbo, text-davinci, DALL·E, Integration All ChatGpt Api and Azure OpenAI Service.
|
||||
Easy Chat channel with several ChatGPT Robots and train.
|
||||
Whitelist and blacklist for Users or IP.
|
||||
''',
|
||||
@@ -30,17 +30,24 @@
|
||||
providing a more natural and intuitive user experience.
|
||||
Base on is_chatgpt_integration from InTechual Solutions.
|
||||
1. Multi ChatGpt openAI robot Connector. Chat and train.
|
||||
2. Multi Api support, Chatgpt 3.5 Turbo, Chatgpt 3 Davinci, Chatgpt 2 Code Optimized, 'Dall-E Image.
|
||||
2. Multi Api support, Chatgpt 4, Chatgpt 3.5 Turbo, Chatgpt 3 Davinci, Chatgpt 2 Code Optimized, 'Dall-E Image.
|
||||
3. Bind ChatGpt Api to user. So we can chat to robot user or use ChatGpt Channel for Group Chat.
|
||||
4. White and black List for ChatGpt.
|
||||
5. Setup Demo Chat time for every new user.
|
||||
6. Easy Start and Stop ChatGpt.
|
||||
7. Evaluation the ai robot to make better response. This training.
|
||||
8. Add api support Connect the Microsoft Azure OpenAI Service.
|
||||
9. Can set Synchronous or Asynchronous mode for Ai response.
|
||||
11. Multi-language Support. Multi-Company Support.
|
||||
12. Support Odoo 16,15,14,13,12, Enterprise and Community and odoo.sh Edition.
|
||||
13. Full Open Source.
|
||||
''',
|
||||
'depends': ['base', 'base_setup', 'mail'],
|
||||
'depends': [
|
||||
'base',
|
||||
'base_setup',
|
||||
'mail',
|
||||
'queue_job',
|
||||
],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'data/mail_channel_data.xml',
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020-Present InTechual Solutions. (<https://intechualsolutions.com/>)
|
||||
|
||||
|
||||
from . import main
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020-Present InTechual Solutions. (<https://intechualsolutions.com/>)
|
||||
|
||||
from odoo import http
|
||||
|
||||
|
||||
@@ -2,14 +2,22 @@
|
||||
<odoo>
|
||||
<record id="chatgpt_robot" model="ai.robot">
|
||||
<field name="name">ChatGPT odoo</field>
|
||||
<field name="provider">openai</field>
|
||||
<field name="sequence">1</field>
|
||||
</record>
|
||||
<record id="chatgpt_robot1" model="ai.robot">
|
||||
<field name="name">ChatGPT Coding</field>
|
||||
<field name="provider">openai</field>
|
||||
<field name="sequence">6</field>
|
||||
</record>
|
||||
<record id="chatgpt_robot2" model="ai.robot">
|
||||
<field name="name">ChatGPT Finance</field>
|
||||
<field name="provider">openai</field>
|
||||
<field name="sequence">7</field>
|
||||
</record>
|
||||
<record id="chatgpt_robot3" model="ai.robot">
|
||||
<field name="name">ChatGPT Azure</field>
|
||||
<field name="provider">azure</field>
|
||||
<field name="sequence">8</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -7,5 +7,10 @@
|
||||
<field name="value">300</field>
|
||||
</record>
|
||||
|
||||
<record id="openai_sync_config" model="ir.config_parameter">
|
||||
<field name="key">app_chatgpt.openai_sync_config</field>
|
||||
<field name="value">sync</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -17,7 +17,7 @@
|
||||
<p>Pleas answer me any question.</p>]]></field>
|
||||
</record>
|
||||
|
||||
<record model="mail.channel.member" id="channel_member_chatgtp_channel_for_admin">
|
||||
<record model="mail.channel.partner" id="channel_member_chatgtp_channel_for_admin">
|
||||
<field name="partner_id" ref="base.partner_admin"/>
|
||||
<field name="channel_id" ref="app_chatgpt.channel_chatgpt"/>
|
||||
<field name="fetched_message_id" ref="app_chatgpt.module_install_notification"/>
|
||||
@@ -25,7 +25,7 @@
|
||||
</record>
|
||||
|
||||
<record model="mail.channel" id="app_chatgpt.channel_chatgpt">
|
||||
<field name="group_ids" eval="[Command.link(ref('base.group_user'))]"/>
|
||||
<field name="group_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
<field name="image_1920" type="base64" file="app_chatgpt/static/description/chatgpt.png"/>
|
||||
</record>
|
||||
<record id="user_chatgpt" model="res.users">
|
||||
<field name="login">chatgpt@sunpop.cn</field>
|
||||
<field name="login">chatgpt@example.com</field>
|
||||
<field name="email">chatgpt@example.com</field>
|
||||
<field name="password">chatgpt</field>
|
||||
<field name="partner_id" ref="app_chatgpt.partner_chatgpt"/>
|
||||
<field name="gpt_id" ref="app_chatgpt.chatgpt_robot"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="company_ids" eval="[Command.link(ref('base.main_company'))]"/>
|
||||
<field name="groups_id" eval="[Command.link(ref('base.group_user'))]"/>
|
||||
<field name="company_ids" eval="[(4, ref('base.main_company'))]"/>
|
||||
<field name="groups_id" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="partner_chatgpt1" model="res.partner">
|
||||
@@ -21,14 +22,14 @@
|
||||
</record>
|
||||
|
||||
<record id="user_chatgpt1" model="res.users">
|
||||
<field name="login">chatgpt1@sunpop.cn</field>
|
||||
<field name="email">chatgpt1@sunpop.cn</field>
|
||||
<field name="email">chatgpt1@example.com</field>
|
||||
<field name="login">chatgpt1@example.com</field>
|
||||
<field name="password">chatgpt</field>
|
||||
<field name="partner_id" ref="app_chatgpt.partner_chatgpt1"/>
|
||||
<field name="gpt_id" ref="app_chatgpt.chatgpt_robot1"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="company_ids" eval="[Command.link(ref('base.main_company'))]"/>
|
||||
<field name="groups_id" eval="[Command.link(ref('base.group_user'))]"/>
|
||||
<field name="company_ids" eval="[(4, ref('base.main_company'))]"/>
|
||||
<field name="groups_id" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="partner_chatgpt2" model="res.partner">
|
||||
@@ -37,14 +38,30 @@
|
||||
</record>
|
||||
|
||||
<record id="user_chatgpt2" model="res.users">
|
||||
<field name="login">chatgpt2@sunpop.cn</field>
|
||||
<field name="email">chatgpt2@sunpop.cn</field>
|
||||
<field name="login">chatgpt2@example.com</field>
|
||||
<field name="email">chatgpt2@example.com</field>
|
||||
<field name="password">chatgpt</field>
|
||||
<field name="partner_id" ref="app_chatgpt.partner_chatgpt2"/>
|
||||
<field name="gpt_id" ref="app_chatgpt.chatgpt_robot2"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="company_ids" eval="[Command.link(ref('base.main_company'))]"/>
|
||||
<field name="groups_id" eval="[Command.link(ref('base.group_user'))]"/>
|
||||
<field name="company_ids" eval="[(4, ref('base.main_company'))]"/>
|
||||
<field name="groups_id" eval="[(4,ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="partner_chatgpt3" model="res.partner">
|
||||
<field name="name">ChatGPT Azure</field>
|
||||
<field name="image_1920" type="base64" file="app_chatgpt/static/description/chatgpt.png"/>
|
||||
</record>
|
||||
|
||||
<record id="user_chatgpt3" model="res.users">
|
||||
<field name="login">chatgpt3@example.com</field>
|
||||
<field name="email">chatgpt3@example.com</field>
|
||||
<field name="password">chatgpt</field>
|
||||
<field name="partner_id" ref="app_chatgpt.partner_chatgpt3"/>
|
||||
<field name="gpt_id" ref="app_chatgpt.chatgpt_robot3"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="company_ids" eval="[(4, ref('base.main_company'))]"/>
|
||||
<field name="groups_id" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0+e-20230213\n"
|
||||
"Project-Id-Version: Odoo Server 16.0+e-20230320\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-02 10:08+0000\n"
|
||||
"PO-Revision-Date: 2023-03-02 10:08+0000\n"
|
||||
"POT-Creation-Date: 2023-03-30 10:30+0000\n"
|
||||
"PO-Revision-Date: 2023-03-30 10:30+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -15,6 +15,21 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,help:app_chatgpt.field_ai_robot__ai_model
|
||||
msgid ""
|
||||
"\n"
|
||||
"GPT-4: Can understand Image, generate natural language or code.\n"
|
||||
"GPT-3.5: A set of models that improve on GPT-3 and can understand as well as generate natural language or code\n"
|
||||
"DALL·E: A model that can generate and edit images given a natural language prompt\n"
|
||||
"Whisper: A model that can convert audio into text\n"
|
||||
"Embeddings:\tA set of models that can convert text into a numerical form\n"
|
||||
"CodexLimited: A set of models that can understand and generate code, including translating natural language to code\n"
|
||||
"Moderation: A fine-tuned model that can detect whether text may be sensitive or unsafe\n"
|
||||
"GPT-3\tA set of models that can understand and generate natural language\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
#: code:addons/app_chatgpt/static/src/models_data/emoji_data.js:0
|
||||
@@ -405,6 +420,16 @@ msgstr ""
|
||||
msgid "ABCD"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_ai_robot__ai_model
|
||||
msgid "AI Model"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_ai_robot__provider
|
||||
msgid "AI Provider"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
#: code:addons/app_chatgpt/static/src/models_data/emoji_data.js:0
|
||||
@@ -414,11 +439,14 @@ msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_ai_robot__openapi_api_key
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_res_config_settings__openapi_api_key
|
||||
#: model_terms:ir.ui.view,arch_db:app_chatgpt.is_res_config_settings_view
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_ai_robot__api_version
|
||||
msgid "API Version"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
#: code:addons/app_chatgpt/static/src/models_data/emoji_data.js:0
|
||||
@@ -448,10 +476,20 @@ msgstr ""
|
||||
msgid "Africa"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model_terms:ir.ui.view,arch_db:app_chatgpt.is_res_config_settings_view
|
||||
msgid "Ai Center(Chatgpt)"
|
||||
msgstr "Ai服务中心(Chatgpt)"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model_terms:ir.ui.view,arch_db:app_chatgpt.is_res_config_settings_view
|
||||
msgid "Seconds"
|
||||
msgstr "秒"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields.selection,name:app_chatgpt.selection__res_users__gpt_policy__all
|
||||
msgid "All Users"
|
||||
msgstr ""
|
||||
msgstr "所有用户"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_res_users__gpt_policy
|
||||
@@ -502,6 +540,11 @@ msgstr ""
|
||||
msgid "Asia"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields.selection,name:app_chatgpt.selection__res_config_settings__openai_sync_config__async
|
||||
msgid "Asynchronous"
|
||||
msgstr "异步响应"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
#: code:addons/app_chatgpt/static/src/models_data/emoji_data.js:0
|
||||
@@ -510,6 +553,11 @@ msgstr ""
|
||||
msgid "Australia"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields.selection,name:app_chatgpt.selection__ai_robot__provider__azure
|
||||
msgid "Azure"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
#: code:addons/app_chatgpt/static/src/models_data/emoji_data.js:0
|
||||
@@ -615,10 +663,14 @@ msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model_terms:ir.ui.view,arch_db:app_chatgpt.app_chatgpt_res_users_form
|
||||
#: model_terms:ir.ui.view,arch_db:app_chatgpt.is_res_config_settings_view
|
||||
msgid "ChatGPT"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ai.robot,name:app_chatgpt.chatgpt_robot3
|
||||
msgid "ChatGPT Azure"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ai.robot,name:app_chatgpt.chatgpt_robot1
|
||||
msgid "ChatGPT Coding"
|
||||
@@ -648,6 +700,36 @@ msgstr ""
|
||||
msgid "ChatGpt Training"
|
||||
msgstr "ChatGpt训练"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields.selection,name:app_chatgpt.selection__ai_robot__ai_model__code-davinci-002
|
||||
msgid "Chatgpt 2 Code Optimized"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields.selection,name:app_chatgpt.selection__ai_robot__ai_model__text-davinci-002
|
||||
msgid "Chatgpt 2 Davinci"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields.selection,name:app_chatgpt.selection__ai_robot__ai_model__text-davinci-003
|
||||
msgid "Chatgpt 3 Davinci"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields.selection,name:app_chatgpt.selection__ai_robot__ai_model__gpt-3_5-turbo
|
||||
msgid "Chatgpt 3.5 Turbo"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields.selection,name:app_chatgpt.selection__ai_robot__ai_model__gpt-3_5-turbo-0301
|
||||
msgid "Chatgpt 3.5 Turbo on 20230301"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields.selection,name:app_chatgpt.selection__ai_robot__ai_model__gpt-4
|
||||
msgid "Chatgpt 4"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
#: code:addons/app_chatgpt/static/src/models_data/emoji_data.js:0
|
||||
@@ -710,6 +792,11 @@ msgstr ""
|
||||
msgid "DVD"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields.selection,name:app_chatgpt.selection__ai_robot__ai_model__dall-e2
|
||||
msgid "Dall-E Image"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
#: code:addons/app_chatgpt/static/src/models_data/emoji_data.js:0
|
||||
@@ -764,6 +851,16 @@ msgstr ""
|
||||
msgid "END arrow"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_ai_robot__endpoint
|
||||
msgid "End Point"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_ai_robot__engine
|
||||
msgid "Engine"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
#: code:addons/app_chatgpt/static/src/models_data/emoji_data.js:0
|
||||
@@ -822,6 +919,11 @@ msgstr ""
|
||||
msgid "Ferris"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_ai_robot__is_filtering
|
||||
msgid "Filter Sensitive Words"
|
||||
msgstr "是否启用敏感词过滤"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
#: code:addons/app_chatgpt/static/src/models_data/emoji_data.js:0
|
||||
@@ -917,6 +1019,11 @@ msgstr ""
|
||||
msgid "ILY"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,help:app_chatgpt.field_ai_robot__engine
|
||||
msgid "If use Azure, Please input the Model deployment name."
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
#: code:addons/app_chatgpt/static/src/models_data/emoji_data.js:0
|
||||
@@ -1244,6 +1351,11 @@ msgstr ""
|
||||
msgid "Mahjong red dragon"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_ai_robot__max_length
|
||||
msgid "Max Length"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model,name:app_chatgpt.model_mail_message
|
||||
msgid "Message"
|
||||
@@ -1365,6 +1477,13 @@ msgstr ""
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-python
|
||||
#: code:addons/app_chatgpt/models/ai_robot.py:0
|
||||
#, python-format
|
||||
msgid "No robot provider found"
|
||||
msgstr "没有设置Ai接口供应方"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
#: code:addons/app_chatgpt/static/src/models_data/emoji_data.js:0
|
||||
@@ -1436,8 +1555,13 @@ msgid "Objects"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model_terms:ir.ui.view,arch_db:app_chatgpt.is_res_config_settings_view
|
||||
msgid "OpenAPI API Key"
|
||||
#: model:ir.model.fields.selection,name:app_chatgpt.selection__ai_robot__provider__openai
|
||||
msgid "OpenAI"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model_terms:ir.ui.view,arch_db:app_chatgpt.ai_robot_form_view
|
||||
msgid "OpenAI Document"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
@@ -1487,9 +1611,22 @@ msgstr ""
|
||||
msgid "Pisces"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-python
|
||||
#: code:addons/app_chatgpt/models/ai_robot.py:0
|
||||
#, python-format
|
||||
msgid "Please Set your AI robot's API Version first."
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-python
|
||||
#: code:addons/app_chatgpt/models/ai_robot.py:0
|
||||
#, python-format
|
||||
msgid "Please Set your AI robot's endpoint first."
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,help:app_chatgpt.field_ai_robot__openapi_api_key
|
||||
#: model:ir.model.fields,help:app_chatgpt.field_res_config_settings__openapi_api_key
|
||||
msgid "Provide the API key here"
|
||||
msgstr ""
|
||||
|
||||
@@ -1582,6 +1719,16 @@ msgstr ""
|
||||
msgid "Selected Users"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_ai_robot__sensitive_words
|
||||
msgid "Sensitive Words Plus"
|
||||
msgstr "额外敏感词"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,help:app_chatgpt.field_ai_robot__sensitive_words
|
||||
msgid "Sensitive word filtering. Separate keywords with a carriage return."
|
||||
msgstr "敏感词过滤。请用回车符分隔关键词。"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_ai_robot__sequence
|
||||
msgid "Sequence"
|
||||
@@ -1645,6 +1792,16 @@ msgstr ""
|
||||
msgid "Symbols"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_res_config_settings__openai_sync_config
|
||||
msgid "Sync Config"
|
||||
msgstr "同步配置"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields.selection,name:app_chatgpt.selection__res_config_settings__openai_sync_config__sync
|
||||
msgid "Synchronous"
|
||||
msgstr "同步响应"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
#: code:addons/app_chatgpt/static/src/models_data/emoji_data.js:0
|
||||
@@ -1805,7 +1962,7 @@ msgstr ""
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model,name:app_chatgpt.model_res_users
|
||||
msgid "User"
|
||||
msgstr "用户"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
@@ -24792,6 +24949,11 @@ msgstr ""
|
||||
msgid "upwards button"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,help:app_chatgpt.field_ai_robot__sensitive_words
|
||||
msgid "Use base Filter in dir models/lib/sensi_words.txt"
|
||||
msgstr "使用此文件进行基础过滤 models/lib/sensi_words.txt"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#. odoo-javascript
|
||||
#: code:addons/app_chatgpt/static/src/models_data/emoji_data.js:0
|
||||
@@ -27000,12 +27162,17 @@ msgstr ""
|
||||
#. module: app_chatgpt
|
||||
#: model:ir.model.fields,field_description:app_chatgpt.field_res_config_settings__openapi_context_timeout
|
||||
#: model_terms:ir.ui.view,arch_db:app_chatgpt.is_res_config_settings_view
|
||||
msgid "上下文连接超时"
|
||||
msgstr ""
|
||||
msgid "Connect Timout"
|
||||
msgstr "上下文连接超时"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model_terms:ir.ui.view,arch_db:app_chatgpt.is_res_config_settings_view
|
||||
msgid "上下文连接超时 秒数"
|
||||
msgid "After timeout seconds then Disconnect"
|
||||
msgstr "上下文连接超时(秒)"
|
||||
|
||||
#. module: app_chatgpt
|
||||
#: model_terms:ir.ui.view,arch_db:app_chatgpt.is_res_config_settings_view
|
||||
msgid "同步配置"
|
||||
msgstr ""
|
||||
|
||||
#. module: app_chatgpt
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020-Present InTechual Solutions. (<https://intechualsolutions.com/>)
|
||||
|
||||
from . import mail_channel
|
||||
from . import res_config_settings
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import requests
|
||||
import requests, json
|
||||
import openai
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
from .lib.WordsSearch import WordsSearch
|
||||
|
||||
import logging
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AiRobot(models.Model):
|
||||
@@ -9,9 +15,10 @@ class AiRobot(models.Model):
|
||||
_description = 'Gpt Robot'
|
||||
_order = 'sequence, name'
|
||||
|
||||
name = fields.Char(string='Name', translate=True)
|
||||
provider = fields.Selection(string="AI Provider", selection=[('openai', 'OpenAI')], required=True, default='openai')
|
||||
name = fields.Char(string='Name', translate=True, required=True)
|
||||
provider = fields.Selection(string="AI Provider", selection=[('openai', 'OpenAI'), ('azure', 'Azure')], required=True, default='openai')
|
||||
ai_model = fields.Selection(string="AI Model", selection=[
|
||||
('gpt-4', 'Chatgpt 4'),
|
||||
('gpt-3.5-turbo', 'Chatgpt 3.5 Turbo'),
|
||||
('gpt-3.5-turbo-0301', 'Chatgpt 3.5 Turbo on 20230301'),
|
||||
('text-davinci-003', 'Chatgpt 3 Davinci'),
|
||||
@@ -20,6 +27,7 @@ class AiRobot(models.Model):
|
||||
('dall-e2', 'Dall-E Image'),
|
||||
], required=True, default='gpt-3.5-turbo',
|
||||
help="""
|
||||
GPT-4: Can understand Image, generate natural language or code.
|
||||
GPT-3.5: A set of models that improve on GPT-3 and can understand as well as generate natural language or code
|
||||
DALL·E: A model that can generate and edit images given a natural language prompt
|
||||
Whisper: A model that can convert audio into text
|
||||
@@ -30,10 +38,126 @@ GPT-3 A set of models that can understand and generate natural language
|
||||
""")
|
||||
openapi_api_key = fields.Char(string="API Key", help="Provide the API key here")
|
||||
temperature = fields.Float(string='Temperature', default=0.9)
|
||||
|
||||
|
||||
max_length = fields.Integer('Max Length', default=300)
|
||||
endpoint = fields.Char('End Point', default='https://api.openai.com/v1/chat/completions')
|
||||
engine = fields.Char('Engine', help='If use Azure, Please input the Model deployment name.')
|
||||
api_version = fields.Char('API Version', default='2022-12-01')
|
||||
sequence = fields.Integer('Sequence', help="Determine the display order", default=10)
|
||||
sensitive_words = fields.Text('Sensitive Words Plus', help='Sensitive word filtering. Separate keywords with a carriage return.')
|
||||
is_filtering = fields.Boolean('Filter Sensitive Words', default=False, help='Use base Filter in dir models/lib/sensi_words.txt')
|
||||
|
||||
def action_disconnect(self):
|
||||
requests.delete('https://chatgpt.com/v1/disconnect')
|
||||
|
||||
def get_ai(self, data, partner_name='odoo', *args):
|
||||
# 通用方法
|
||||
self.ensure_one()
|
||||
if hasattr(self, 'get_%s' % self.provider):
|
||||
return getattr(self, 'get_%s' % self.provider)(data, partner_name, *args)
|
||||
else:
|
||||
return _('No robot provider found')
|
||||
|
||||
def get_openai(self, data, partner_name='odoo', *args):
|
||||
self.ensure_one()
|
||||
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {self.openapi_api_key}"}
|
||||
R_TIMEOUT = 300
|
||||
o_url = self.endpoint or "https://api.openai.com/v1/chat/completions"
|
||||
|
||||
# 以下处理 open ai
|
||||
# 获取模型信息
|
||||
# list_model = requests.get("https://api.openai.com/v1/models", headers=headers)
|
||||
# model_info = requests.get("https://api.openai.com/v1/models/%s" % ai_model, headers=headers)
|
||||
if self.ai_model == 'dall-e2':
|
||||
# todo: 处理 图像引擎,主要是返回参数到聊天中
|
||||
# image_url = response['data'][0]['url']
|
||||
# https://platform.openai.com/docs/guides/images/introduction
|
||||
pdata = {
|
||||
"prompt": data,
|
||||
"n": 3,
|
||||
"size": "1024x1024",
|
||||
}
|
||||
return '建设中'
|
||||
elif self.ai_model in ['gpt-3.5-turbo', 'gpt-3.5-turbo-0301']:
|
||||
pdata = {
|
||||
"model": self.ai_model,
|
||||
"messages": [{"role": "user", "content": data}],
|
||||
"temperature": 0.9,
|
||||
"max_tokens": self.max_length or 1000,
|
||||
"top_p": 1,
|
||||
"frequency_penalty": 0.0,
|
||||
"presence_penalty": 0.6,
|
||||
"user": partner_name,
|
||||
"stop": ["Human:", "AI:"]
|
||||
}
|
||||
_logger.warning('=====================open input pdata: %s' % pdata)
|
||||
response = requests.post(o_url, data=json.dumps(pdata), headers=headers, timeout=R_TIMEOUT)
|
||||
res = response.json()
|
||||
if 'choices' in res:
|
||||
# for rec in res:
|
||||
# res = rec['message']['content']
|
||||
res = '\n'.join([x['message']['content'] for x in res['choices']])
|
||||
res = self.filter_sensitive_words(res)
|
||||
return res
|
||||
else:
|
||||
pdata = {
|
||||
"model": self.ai_model,
|
||||
"prompt": data,
|
||||
"temperature": 0.9,
|
||||
"max_tokens": self.max_length or 1000,
|
||||
"top_p": 1,
|
||||
"frequency_penalty": 0.0,
|
||||
"presence_penalty": 0.6,
|
||||
"user": partner_name,
|
||||
"stop": ["Human:", "AI:"]
|
||||
}
|
||||
response = requests.post(o_url, data=json.dumps(pdata), headers=headers, timeout=R_TIMEOUT)
|
||||
res = response.json()
|
||||
if 'choices' in res:
|
||||
res = '\n'.join([x['text'] for x in res['choices']])
|
||||
res = self.filter_sensitive_words(res)
|
||||
return res
|
||||
|
||||
return "获取结果超时,请重新跟我聊聊。"
|
||||
|
||||
def get_azure(self, data, partner_name='odoo', *args):
|
||||
self.ensure_one()
|
||||
# only for azure
|
||||
openai.api_type = self.provider
|
||||
if not self.endpoint:
|
||||
raise UserError(_("Please Set your AI robot's endpoint first."))
|
||||
openai.api_base = self.endpoint
|
||||
if not self.api_version:
|
||||
raise UserError(_("Please Set your AI robot's API Version first."))
|
||||
openai.api_version = self.api_version
|
||||
openai.api_key = self.openapi_api_key
|
||||
response = openai.Completion.create(
|
||||
engine=self.engine,
|
||||
prompt=data,
|
||||
temperature=self.temperature or 0.9,
|
||||
max_tokens=self.max_length or 600,
|
||||
top_p=0.5,
|
||||
frequency_penalty=0,
|
||||
presence_penalty=0, stop=["Human:", "AI:"])
|
||||
|
||||
_logger.warning('=====================azure input data: %s' % data)
|
||||
if 'choices' in response:
|
||||
res = response['choices'][0]['text'].replace(' .', '.').strip()
|
||||
res = self.filter_sensitive_words(res)
|
||||
return res
|
||||
|
||||
@api.onchange('provider')
|
||||
def _onchange_provider(self):
|
||||
if self.provider == 'openai':
|
||||
self.endpoint = 'https://api.openai.com/v1/chat/completions'
|
||||
elif self.provider == 'azure':
|
||||
self.endpoint = 'https://odoo.openai.azure.com'
|
||||
|
||||
def filter_sensitive_words(self, data):
|
||||
if self.is_filtering:
|
||||
search = WordsSearch()
|
||||
s = self.sensitive_words
|
||||
search.SetKeywords(s.split('\n'))
|
||||
result = search.Replace(text=data)
|
||||
return result
|
||||
else:
|
||||
return data
|
||||
|
||||
296
app_chatgpt/models/lib/WordsSearch.py
Normal file
@@ -0,0 +1,296 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
# ToolGood.Words.WordsSearch.py
|
||||
# 2020, Lin Zhijun, https://github.com/toolgood/ToolGood.Words
|
||||
# Licensed under the Apache License 2.0
|
||||
# 更新日志
|
||||
# 2020.04.06 第一次提交
|
||||
# 2020.05.16 修改,支持大于0xffff的字符
|
||||
|
||||
import os
|
||||
|
||||
__all__ = ['WordsSearch']
|
||||
__author__ = 'Lin Zhijun'
|
||||
__date__ = '2020.05.16'
|
||||
|
||||
|
||||
class TrieNode():
|
||||
def __init__(self):
|
||||
self.Index = 0
|
||||
self.Index = 0
|
||||
self.Layer = 0
|
||||
self.End = False
|
||||
self.Char = ''
|
||||
self.Results = []
|
||||
self.m_values = {}
|
||||
self.Failure = None
|
||||
self.Parent = None
|
||||
|
||||
def Add(self, c):
|
||||
if c in self.m_values:
|
||||
return self.m_values[c]
|
||||
node = TrieNode()
|
||||
node.Parent = self
|
||||
node.Char = c
|
||||
self.m_values[c] = node
|
||||
return node
|
||||
|
||||
def SetResults(self, index):
|
||||
if (self.End == False):
|
||||
self.End = True
|
||||
self.Results.append(index)
|
||||
|
||||
|
||||
class TrieNode2():
|
||||
def __init__(self):
|
||||
self.End = False
|
||||
self.Results = []
|
||||
self.m_values = {}
|
||||
self.minflag = 0xffff
|
||||
self.maxflag = 0
|
||||
|
||||
def Add(self, c, node3):
|
||||
if (self.minflag > c):
|
||||
self.minflag = c
|
||||
if (self.maxflag < c):
|
||||
self.maxflag = c
|
||||
self.m_values[c] = node3
|
||||
|
||||
def SetResults(self, index):
|
||||
if (self.End == False):
|
||||
self.End = True
|
||||
if (index in self.Results) == False:
|
||||
self.Results.append(index)
|
||||
|
||||
def HasKey(self, c):
|
||||
return c in self.m_values
|
||||
|
||||
def TryGetValue(self, c):
|
||||
if (self.minflag <= c and self.maxflag >= c):
|
||||
if c in self.m_values:
|
||||
return self.m_values[c]
|
||||
return None
|
||||
|
||||
|
||||
class WordsSearch():
|
||||
def __init__(self):
|
||||
self._first = {}
|
||||
self._keywords = []
|
||||
self._indexs = []
|
||||
|
||||
def SetKeywords(self, keywords):
|
||||
keyword_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'sensi_words.txt')
|
||||
s = open(keyword_path, 'r+', encoding='utf-8').read().split('\n')
|
||||
self._keywords = s + keywords
|
||||
# self._keywords = keywords
|
||||
self._indexs = []
|
||||
for i in range(len(keywords)):
|
||||
self._indexs.append(i)
|
||||
|
||||
root = TrieNode()
|
||||
allNodeLayer = {}
|
||||
|
||||
for i in range(len(self._keywords)): # for (i = 0; i < _keywords.length; i++)
|
||||
p = self._keywords[i]
|
||||
nd = root
|
||||
for j in range(len(p)): # for (j = 0; j < p.length; j++)
|
||||
nd = nd.Add(ord(p[j]))
|
||||
if (nd.Layer == 0):
|
||||
nd.Layer = j + 1
|
||||
if nd.Layer in allNodeLayer:
|
||||
allNodeLayer[nd.Layer].append(nd)
|
||||
else:
|
||||
allNodeLayer[nd.Layer] = []
|
||||
allNodeLayer[nd.Layer].append(nd)
|
||||
nd.SetResults(i)
|
||||
|
||||
allNode = []
|
||||
allNode.append(root)
|
||||
for key in allNodeLayer.keys():
|
||||
for nd in allNodeLayer[key]:
|
||||
allNode.append(nd)
|
||||
allNodeLayer = None
|
||||
|
||||
for i in range(len(allNode)): # for (i = 0; i < allNode.length; i++)
|
||||
if i == 0:
|
||||
continue
|
||||
nd = allNode[i]
|
||||
nd.Index = i
|
||||
r = nd.Parent.Failure
|
||||
c = nd.Char
|
||||
while (r != None and (c in r.m_values) == False):
|
||||
r = r.Failure
|
||||
if (r == None):
|
||||
nd.Failure = root
|
||||
else:
|
||||
nd.Failure = r.m_values[c]
|
||||
for key2 in nd.Failure.Results:
|
||||
nd.SetResults(key2)
|
||||
root.Failure = root
|
||||
|
||||
allNode2 = []
|
||||
for i in range(len(allNode)): # for (i = 0; i < allNode.length; i++)
|
||||
allNode2.append(TrieNode2())
|
||||
|
||||
for i in range(len(allNode2)): # for (i = 0; i < allNode2.length; i++)
|
||||
oldNode = allNode[i]
|
||||
newNode = allNode2[i]
|
||||
|
||||
for key in oldNode.m_values:
|
||||
index = oldNode.m_values[key].Index
|
||||
newNode.Add(key, allNode2[index])
|
||||
|
||||
for index in range(len(oldNode.Results)): # for (index = 0; index < oldNode.Results.length; index++)
|
||||
item = oldNode.Results[index]
|
||||
newNode.SetResults(item)
|
||||
|
||||
oldNode = oldNode.Failure
|
||||
while oldNode != root:
|
||||
for key in oldNode.m_values:
|
||||
if (newNode.HasKey(key) == False):
|
||||
index = oldNode.m_values[key].Index
|
||||
newNode.Add(key, allNode2[index])
|
||||
for index in range(len(oldNode.Results)):
|
||||
item = oldNode.Results[index]
|
||||
newNode.SetResults(item)
|
||||
oldNode = oldNode.Failure
|
||||
allNode = None
|
||||
root = None
|
||||
|
||||
# first = []
|
||||
# for index in range(65535):# for (index = 0; index < 0xffff; index++)
|
||||
# first.append(None)
|
||||
|
||||
# for key in allNode2[0].m_values :
|
||||
# first[key] = allNode2[0].m_values[key]
|
||||
|
||||
self._first = allNode2[0]
|
||||
|
||||
def FindFirst(self, text):
|
||||
ptr = None
|
||||
for index in range(len(text)): # for (index = 0; index < text.length; index++)
|
||||
t = ord(text[index]) # text.charCodeAt(index)
|
||||
tn = None
|
||||
if (ptr == None):
|
||||
tn = self._first.TryGetValue(t)
|
||||
else:
|
||||
tn = ptr.TryGetValue(t)
|
||||
if (tn == None):
|
||||
tn = self._first.TryGetValue(t)
|
||||
|
||||
if (tn != None):
|
||||
if (tn.End):
|
||||
item = tn.Results[0]
|
||||
keyword = self._keywords[item]
|
||||
return {"Keyword": keyword, "Success": True, "End": index, "Start": index + 1 - len(keyword), "Index": self._indexs[item]}
|
||||
ptr = tn
|
||||
return None
|
||||
|
||||
def FindAll(self, text):
|
||||
ptr = None
|
||||
list = []
|
||||
|
||||
for index in range(len(text)): # for (index = 0; index < text.length; index++)
|
||||
t = ord(text[index]) # text.charCodeAt(index)
|
||||
tn = None
|
||||
if (ptr == None):
|
||||
tn = self._first.TryGetValue(t)
|
||||
else:
|
||||
tn = ptr.TryGetValue(t)
|
||||
if (tn == None):
|
||||
tn = self._first.TryGetValue(t)
|
||||
|
||||
if (tn != None):
|
||||
if (tn.End):
|
||||
for j in range(len(tn.Results)): # for (j = 0; j < tn.Results.length; j++)
|
||||
item = tn.Results[j]
|
||||
keyword = self._keywords[item]
|
||||
list.append({"Keyword": keyword, "Success": True, "End": index, "Start": index + 1 - len(keyword), "Index": self._indexs[item]})
|
||||
ptr = tn
|
||||
return list
|
||||
|
||||
def ContainsAny(self, text):
|
||||
ptr = None
|
||||
for index in range(len(text)): # for (index = 0; index < text.length; index++)
|
||||
t = ord(text[index]) # text.charCodeAt(index)
|
||||
tn = None
|
||||
if (ptr == None):
|
||||
tn = self._first.TryGetValue(t)
|
||||
else:
|
||||
tn = ptr.TryGetValue(t)
|
||||
if (tn == None):
|
||||
tn = self._first.TryGetValue(t)
|
||||
|
||||
if (tn != None):
|
||||
if (tn.End):
|
||||
return True
|
||||
ptr = tn
|
||||
return False
|
||||
|
||||
def Replace(self, text, replaceChar='*'):
|
||||
result = list(text)
|
||||
|
||||
ptr = None
|
||||
for i in range(len(text)): # for (i = 0; i < text.length; i++)
|
||||
t = ord(text[i]) # text.charCodeAt(index)
|
||||
tn = None
|
||||
if (ptr == None):
|
||||
tn = self._first.TryGetValue(t)
|
||||
else:
|
||||
tn = ptr.TryGetValue(t)
|
||||
if (tn == None):
|
||||
tn = self._first.TryGetValue(t)
|
||||
|
||||
if (tn != None):
|
||||
if (tn.End):
|
||||
maxLength = len(self._keywords[tn.Results[0]])
|
||||
start = i + 1 - maxLength
|
||||
for j in range(start, i + 1): # for (j = start; j <= i; j++)
|
||||
result[j] = replaceChar
|
||||
ptr = tn
|
||||
return ''.join(result)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
s = "中国|国人|zg人|乾清宫"
|
||||
test = "我是中国人"
|
||||
|
||||
search = WordsSearch()
|
||||
search.SetKeywords(s.split('|'))
|
||||
|
||||
print("----------------------------------- WordsSearch -----------------------------------")
|
||||
|
||||
print("WordsSearch FindFirst is run.")
|
||||
f = search.FindFirst(test)
|
||||
if f["Keyword"] != "中国":
|
||||
print("WordsSearch FindFirst is error.............................")
|
||||
|
||||
print("WordsSearch FindFirst is run.")
|
||||
all = search.FindAll("乾清宫")
|
||||
if all[0]["Keyword"] != "乾清宫":
|
||||
print("WordsSearch FindFirst is error.............................")
|
||||
|
||||
print("WordsSearch FindAll is run.")
|
||||
all = search.FindAll(test)
|
||||
if all[0]["Keyword"] != "中国":
|
||||
print("WordsSearch FindAll is error.............................")
|
||||
if all[1]["Keyword"] != "国人":
|
||||
print("WordsSearch FindAll is error.............................")
|
||||
if all[0]["Start"] != 2:
|
||||
print("WordsSearch FindAll is error.............................")
|
||||
if all[0]["End"] != 3:
|
||||
print("WordsSearch FindAll is error.............................")
|
||||
if len(all) != 2:
|
||||
print("WordsSearch FindAll is error.............................")
|
||||
|
||||
print("WordsSearch ContainsAny is run.")
|
||||
b = search.ContainsAny(test)
|
||||
if b == False:
|
||||
print("WordsSearch ContainsAny is error.............................")
|
||||
|
||||
print("WordsSearch Replace is run.")
|
||||
txt = search.Replace(test)
|
||||
if (txt != "我是***"):
|
||||
print("WordsSearch Replace is error.............................")
|
||||
|
||||
print("----------------------------------- Test End -----------------------------------")
|
||||
14553
app_chatgpt/models/lib/sensi_words.txt
Normal file
@@ -1,12 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import openai
|
||||
import requests, json
|
||||
import datetime
|
||||
# from transformers import TextDavinciTokenizer, TextDavinciModel
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
import logging
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -14,63 +14,6 @@ _logger = logging.getLogger(__name__)
|
||||
class Channel(models.Model):
|
||||
_inherit = 'mail.channel'
|
||||
|
||||
@api.model
|
||||
def get_openai(self, api_key, ai_model, data, user="Odoo"):
|
||||
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}
|
||||
R_TIMEOUT = 5
|
||||
|
||||
if ai_model == 'dall-e2':
|
||||
# todo: 处理 图像引擎,主要是返回参数到聊天中
|
||||
# image_url = response['data'][0]['url']
|
||||
# https://platform.openai.com/docs/guides/images/introduction
|
||||
pdata = {
|
||||
"prompt": data,
|
||||
"n": 3,
|
||||
"size": "1024x1024",
|
||||
}
|
||||
return '建设中'
|
||||
elif ai_model in ['gpt-3.5-turbo', 'gpt-3.5-turbo-0301']:
|
||||
pdata = {
|
||||
"model": ai_model,
|
||||
"messages": [{"role": "user", "content": data}],
|
||||
"temperature": 0.9,
|
||||
"max_tokens": 2000,
|
||||
"top_p": 1,
|
||||
"frequency_penalty": 0.0,
|
||||
"presence_penalty": 0.6,
|
||||
"user": user,
|
||||
"stop": ["Human:", "AI:"]
|
||||
}
|
||||
response = requests.post("https://api.openai.com/v1/chat/completions", data=json.dumps(pdata), headers=headers, timeout=R_TIMEOUT)
|
||||
res = response.json()
|
||||
if 'choices' in res:
|
||||
# for rec in res:
|
||||
# res = rec['message']['content']
|
||||
res = '\n'.join([x['message']['content'] for x in res['choices']])
|
||||
return res
|
||||
else:
|
||||
pdata = {
|
||||
"model": ai_model,
|
||||
"prompt": data,
|
||||
"temperature": 0.9,
|
||||
"max_tokens": 2000,
|
||||
"top_p": 1,
|
||||
"frequency_penalty": 0.0,
|
||||
"presence_penalty": 0.6,
|
||||
"user": user,
|
||||
"stop": ["Human:", "AI:"]
|
||||
}
|
||||
response = requests.post("https://api.openai.com/v1/completions", data=json.dumps(pdata), headers=headers, timeout=R_TIMEOUT)
|
||||
res = response.json()
|
||||
if 'choices' in res:
|
||||
res = '\n'.join([x['text'] for x in res['choices']])
|
||||
return res
|
||||
# 获取模型信息
|
||||
# list_model = requests.get("https://api.openai.com/v1/models", headers=headers)
|
||||
# model_info = requests.get("https://api.openai.com/v1/models/%s" % ai_model, headers=headers)
|
||||
|
||||
return "获取结果超时,请重新跟我聊聊。"
|
||||
|
||||
@api.model
|
||||
def get_openai_context(self, channel_id, partner_chatgpt, current_prompt, seconds=600):
|
||||
afterTime = fields.Datetime.now() - datetime.timedelta(seconds=seconds)
|
||||
@@ -101,19 +44,11 @@ class Channel(models.Model):
|
||||
|
||||
return '\n'.join(prompt[::-1])
|
||||
|
||||
def get_chatgpt_answer(self, prompt, partner_name):
|
||||
response = openai.Completion.create(
|
||||
model="text-davinci-003",
|
||||
prompt=prompt,
|
||||
temperature=0.6,
|
||||
max_tokens=3000,
|
||||
top_p=1,
|
||||
frequency_penalty=0,
|
||||
presence_penalty=0,
|
||||
user=partner_name,
|
||||
)
|
||||
res = response['choices'][0]['text']
|
||||
return res
|
||||
def get_ai(self, ai, prompt, partner_name, channel, user_id, message):
|
||||
res = ai.get_ai(prompt, partner_name)
|
||||
if res:
|
||||
res = res.replace('\n', '<br/>')
|
||||
channel.with_user(user_id).message_post(body=res, message_type='comment', subtype_xmlid='mail.mt_comment', parent_id=message.id)
|
||||
|
||||
def _notify_thread(self, message, msg_vals=False, **kwargs):
|
||||
rdata = super(Channel, self)._notify_thread(message, msg_vals=msg_vals, **kwargs)
|
||||
@@ -121,7 +56,7 @@ class Channel(models.Model):
|
||||
to_partner_id = self.env['res.partner']
|
||||
user_id = self.env['res.users']
|
||||
author_id = msg_vals.get('author_id')
|
||||
gpt_id = self.env['ai.robot']
|
||||
ai = self.env['ai.robot']
|
||||
channel_type = self.channel_type
|
||||
if channel_type == 'chat':
|
||||
channel_partner_ids = self.channel_partner_ids
|
||||
@@ -132,7 +67,7 @@ class Channel(models.Model):
|
||||
gpt_wl_users = user_id.gpt_wl_users
|
||||
is_allow = message.create_uid.id in gpt_wl_users.ids
|
||||
if gpt_policy == 'all' or (gpt_policy == 'limit' and is_allow):
|
||||
gpt_id = user_id.gpt_id
|
||||
ai = user_id.gpt_id
|
||||
|
||||
elif channel_type in ['group', 'channel']:
|
||||
# partner_ids = @ ids
|
||||
@@ -147,14 +82,10 @@ class Channel(models.Model):
|
||||
is_allow = message.create_uid.id in gpt_wl_users.ids
|
||||
to_partner_id = user_id.partner_id
|
||||
if gpt_policy == 'all' or (gpt_policy == 'limit' and is_allow):
|
||||
gpt_id = user_id.gpt_id
|
||||
ai = user_id.gpt_id
|
||||
|
||||
chatgpt_channel_id = self.env.ref('app_chatgpt.channel_chatgpt')
|
||||
|
||||
# print('author_id:',author_id)
|
||||
|
||||
# print('partner_chatgpt.id:',partner_chatgpt.id)
|
||||
|
||||
prompt = msg_vals.get('body')
|
||||
# print('prompt:', prompt)
|
||||
# print('-----')
|
||||
@@ -162,8 +93,8 @@ class Channel(models.Model):
|
||||
return rdata
|
||||
# api_key = self.env['ir.config_parameter'].sudo().get_param('app_chatgpt.openapi_api_key')
|
||||
api_key = ''
|
||||
if gpt_id:
|
||||
api_key = gpt_id.openapi_api_key
|
||||
if ai:
|
||||
api_key = ai.openapi_api_key
|
||||
if not api_key:
|
||||
_logger.warning(_("ChatGPT Robot【%s】have not set open api key."))
|
||||
return rdata
|
||||
@@ -171,29 +102,29 @@ class Channel(models.Model):
|
||||
openapi_context_timeout = int(self.env['ir.config_parameter'].sudo().get_param('app_chatgpt.openapi_context_timeout')) or 600
|
||||
except:
|
||||
openapi_context_timeout = 600
|
||||
|
||||
sync_config = self.env['ir.config_parameter'].sudo().get_param('app_chatgpt.openai_sync_config')
|
||||
openai.api_key = api_key
|
||||
partner_name = ''
|
||||
# print(msg_vals)
|
||||
# print(msg_vals.get('record_name', ''))
|
||||
# print('self.channel_type :',self.channel_type)
|
||||
if gpt_id:
|
||||
ai_model = gpt_id.ai_model or 'text-davinci-003'
|
||||
# print('chatgpt_name:', chatgpt_name)
|
||||
# if author_id != to_partner_id.id and (chatgpt_name in msg_vals.get('record_name', '') or 'ChatGPT' in msg_vals.get('record_name', '') ) and self.channel_type == 'chat':
|
||||
if ai:
|
||||
if author_id != to_partner_id.id and self.channel_type == 'chat':
|
||||
_logger.info(f'私聊:author_id:{author_id},partner_chatgpt.id:{to_partner_id.id}')
|
||||
try:
|
||||
channel = self.env[msg_vals.get('model')].browse(msg_vals.get('res_id'))
|
||||
if ai_model not in ['gpt-3.5-turbo', 'gpt-3.5-turbo-0301']:
|
||||
# if ai_model not in ['gpt-3.5-turbo', 'gpt-3.5-turbo-0301']:
|
||||
prompt = self.get_openai_context(channel.id, to_partner_id.id, prompt, openapi_context_timeout)
|
||||
print(prompt)
|
||||
# res = self.get_chatgpt_answer(prompt,partner_name)
|
||||
res = self.get_openai(api_key, ai_model, prompt, partner_name)
|
||||
res = res.replace('\n', '<br/>')
|
||||
if sync_config == 'sync':
|
||||
self.get_ai(ai, prompt, partner_name, channel, user_id, message)
|
||||
else:
|
||||
self.with_delay().get_ai(ai, prompt, partner_name, channel, user_id, message)
|
||||
# res = ai.get_ai(prompt, partner_name)
|
||||
# res = res.replace('\n', '<br/>')
|
||||
# print('res:',res)
|
||||
# print('channel:',channel)
|
||||
channel.with_user(user_id).message_post(body=res, message_type='comment',subtype_xmlid='mail.mt_comment', parent_id=message.id)
|
||||
# channel.with_user(user_id).message_post(body=res, message_type='comment',subtype_xmlid='mail.mt_comment', parent_id=message.id)
|
||||
# channel.with_user(user_chatgpt).message_post(body=res, message_type='notification', subtype_xmlid='mail.mt_comment')
|
||||
# channel.sudo().message_post(
|
||||
# body=res,
|
||||
@@ -204,17 +135,19 @@ class Channel(models.Model):
|
||||
# self.with_user(user_chatgpt).message_post(body=res, message_type='comment', subtype_xmlid='mail.mt_comment')
|
||||
except Exception as e:
|
||||
raise UserError(_(e))
|
||||
|
||||
elif author_id != to_partner_id.id and msg_vals.get('model', '') == 'mail.channel' and msg_vals.get('res_id', 0) == chatgpt_channel_id.id:
|
||||
_logger.info(f'频道群聊:author_id:{author_id},partner_chatgpt.id:{to_partner_id.id}')
|
||||
try:
|
||||
prompt = self.get_openai_context(chatgpt_channel_id.id, to_partner_id.id, prompt, openapi_context_timeout)
|
||||
# print(prompt)
|
||||
# res = self.get_chatgpt_answer(prompt, partner_name)
|
||||
res = self.get_openai(api_key, ai_model, prompt, partner_name)
|
||||
res = res.replace('\n', '<br/>')
|
||||
chatgpt_channel_id.with_user(user_id).message_post(body=res, message_type='comment', subtype_xmlid='mail.mt_comment',parent_id=message.id)
|
||||
if sync_config == 'sync':
|
||||
self.get_ai(ai, prompt, 'odoo', chatgpt_channel_id, user_id, message)
|
||||
else:
|
||||
self.with_delay().get_ai(ai, prompt, 'odoo', chatgpt_channel_id, user_id, message)
|
||||
# res = ai.get_ai(prompt, 'odoo')
|
||||
# res = res.replace('\n', '<br/>')
|
||||
# chatgpt_channel_id.with_user(user_id).message_post(body=res, message_type='comment', subtype_xmlid='mail.mt_comment', parent_id=message.id)
|
||||
except Exception as e:
|
||||
raise UserError(_(e))
|
||||
|
||||
return rdata
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020-Present InTechual Solutions. (<https://intechualsolutions.com/>)
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
@@ -7,4 +6,8 @@ from odoo import fields, models
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = "res.config.settings"
|
||||
|
||||
openapi_context_timeout = fields.Integer(string="上下文连接超时", help="多少秒以内的聊天信息作为上下文继续", config_parameter="app_chatgpt.openapi_context_timeout")
|
||||
openapi_context_timeout = fields.Integer(string="Connect Timout", help="多少秒以内的聊天信息作为上下文继续", config_parameter="app_chatgpt.openapi_context_timeout")
|
||||
openai_sync_config = fields.Selection([
|
||||
('sync', 'Synchronous'),
|
||||
('async', 'Asynchronous')
|
||||
], string='Sync Config', default='sync', config_parameter="app_chatgpt.openai_sync_config")
|
||||
|
||||
|
Before Width: | Height: | Size: 971 KiB After Width: | Height: | Size: 964 KiB |
BIN
app_chatgpt/static/description/demo81.jpg
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
app_chatgpt/static/description/demo91.jpg
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
app_chatgpt/static/description/demob.jpg
Normal file
|
After Width: | Height: | Size: 247 KiB |
@@ -2,9 +2,9 @@
|
||||
<div class="oe_row oe_spaced" >
|
||||
<div class="oe_span12">
|
||||
<h2 class="oe_slogan"> Latest ChatGPT AI Center. GPT 3.5, Dall-E Image.Multi Robot Support. Chat and Training </h2>
|
||||
<h3 class="oe_slogan"> Support chatgpt 3.5 turbo, text-davinci, DALL·E(Working Now.), Integration All ChatGpt Api </h3>
|
||||
<h3 class="oe_slogan"> Support chatgpt 4 image. 3.5 turbo, text-davinci, DALL·E, Integration All ChatGpt Api. </h3>
|
||||
<div class="oe_row">
|
||||
<h3>Lastest update: v16.23.03.05</h3>
|
||||
<h3>Lastest update: v16.23.03.16</h3>
|
||||
<div class="oe_span12">
|
||||
<img class="oe_demo oe_screenshot" style="max-height: 100%;" src="banner.gif">
|
||||
</div>
|
||||
@@ -18,7 +18,7 @@
|
||||
</li>
|
||||
<li>
|
||||
<i class="fa fa-check-square-o text-primary"></i>
|
||||
2. Multi Api support, Chatgpt 3.5 Turbo, Chatgpt 3 Davinci, Chatgpt 2 Code Optimized, 'Dall-E Image.
|
||||
2. Multi Api support, Chatgpt 4, Chatgpt 3.5 Turbo, Chatgpt 3 Davinci, Chatgpt 2 Code Optimized, 'Dall-E Image.
|
||||
</li>
|
||||
<li>
|
||||
<i class="fa fa-check-square-o text-primary"></i>
|
||||
@@ -40,7 +40,14 @@
|
||||
<i class="fa fa-check-square-o text-primary"></i>
|
||||
7. Evaluation the ai robot to make better response. This training.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<i class="fa fa-check-square-o text-primary"></i>
|
||||
8. Add api support Connect the Microsoft Azure OpenAI Service.
|
||||
</li>
|
||||
<li>
|
||||
<i class="fa fa-check-square-o text-primary"></i>
|
||||
9. Can set Synchronous or Asynchronous mode for Ai response.
|
||||
</li>
|
||||
<li>
|
||||
<i class="fa fa-check-square-o text-primary"></i>
|
||||
11. Multi-language Support. Multi-Company Support.
|
||||
@@ -61,6 +68,16 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container">
|
||||
<div class="oe_row oe_spaced">
|
||||
<h1 class="text-danger text-center">Easy to use Ai Robot with multi Provider. Easy chat, easy help</h1>
|
||||
<h4 class="oe_slogan"> Open Ai for more smart. Microsoft Azure chatgpt for china user.</h4>
|
||||
<div class="oe_demo oe_screenshot">
|
||||
<img src="demob.jpg"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container">
|
||||
<div class="oe_row oe_spaced">
|
||||
<h1 class="text-danger text-center">1. Multi ChatGpt openAI robot Connector. Chat and train.</h1>
|
||||
@@ -149,6 +166,26 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container">
|
||||
<div class="oe_row oe_spaced">
|
||||
<h1 class="text-danger text-center">8. Add api support Connect the Microsoft Azure OpenAI Service.</h1>
|
||||
<h4 class="oe_slogan"> Azure openai add. It is for china and other country which no chatgpt service.</h4>
|
||||
<div class="oe_demo oe_screenshot">
|
||||
<img src="demo81.jpg"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container">
|
||||
<div class="oe_row oe_spaced">
|
||||
<h1 class="text-danger text-center">9. Can set Synchronous or Asynchronous mode for Ai response.</h1>
|
||||
<h4 class="oe_slogan"> Synchronous(default) mode can get response then ask question again. Asynchronous mode would make you do other thing when waiting for response.</h4>
|
||||
<div class="oe_demo oe_screenshot">
|
||||
<img src="demo91.jpg"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container">
|
||||
<div class="oe_row oe_spaced">
|
||||
<h1 class="text-danger text-center">Multi-language Support..</h1>
|
||||
@@ -191,7 +228,7 @@
|
||||
</div>
|
||||
<div class="oe_row oe_spaced text-center">
|
||||
<h1>More Powerful addons, Make your odoo very easy to use, easy customize:
|
||||
<a class="btn btn-primary mb16" href="http://www.odoo.com/apps/modules/browse?author=Sunpop.cn">Supop.cn Odoo Addons</a>
|
||||
<a class="btn btn-primary mb16" href="http://www.odoo.com/apps/modules/browse?author=Sunpop.cn">Sunpop.cn Odoo Addons</a>
|
||||
</h1>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
BIN
app_chatgpt/static/description/src/chatgpt_logo.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
app_chatgpt/static/description/src/chatgpt_white.png
Normal file
|
After Width: | Height: | Size: 223 KiB |
BIN
app_chatgpt/static/description/src/code_bg.gif
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
app_chatgpt/static/description/src/demob.jpg
Normal file
|
After Width: | Height: | Size: 232 KiB |
@@ -21857,55 +21857,6 @@ const emojisData0 = `{
|
||||
"shortcodes": [
|
||||
":thumbs_down:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "ChatGpt Training",
|
||||
"codepoints": "👐",
|
||||
"emoticons": [],
|
||||
"keywords": [
|
||||
"` + _lt("mark") + `",
|
||||
"` + _lt("neutral") + `",
|
||||
"` + _lt("hand") + `",
|
||||
"` + _lt("open") + `",
|
||||
"` + _lt("open hands") + `"
|
||||
],
|
||||
"name": "` + _lt("mark_as_neutral. open hands") + `",
|
||||
"shortcodes": [
|
||||
":open_hands:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "ChatGpt Training",
|
||||
"codepoints": "👋",
|
||||
"emoticons": [],
|
||||
"keywords": [
|
||||
"` + _lt("mark") + `",
|
||||
"` + _lt("redundant") + `",
|
||||
"` + _lt("hand") + `",
|
||||
"` + _lt("wave") + `",
|
||||
"` + _lt("waving") + `"
|
||||
],
|
||||
"name": "` + _lt("mark_as_redundant. waving hand") + `",
|
||||
"shortcodes": [
|
||||
":waving_hand:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "ChatGpt Training",
|
||||
"codepoints": "🈵",
|
||||
"emoticons": [],
|
||||
"keywords": [
|
||||
"` + _lt("mark") + `",
|
||||
"` + _lt("unhelpful") + `",
|
||||
"` + _lt("“no vacancy”") + `",
|
||||
"` + _lt("ideograph") + `",
|
||||
"` + _lt("Japanese") + `",
|
||||
"` + _lt("満") + `"
|
||||
],
|
||||
"name": "` + _lt("mark_as_unhelpful. Need more answer") + `",
|
||||
"shortcodes": [
|
||||
":Japanese_“no_vacancy”_button:"
|
||||
]
|
||||
},`;
|
||||
|
||||
export const emojisData = JSON.parse(`[
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<field name="provider" optional="hide"/>
|
||||
<field name="ai_model" optional="show"/>
|
||||
<field name="openapi_api_key" password="True"/>
|
||||
<field name="max_length" optional="show"/>
|
||||
<field name="temperature"/>
|
||||
</tree>
|
||||
</field>
|
||||
@@ -20,11 +21,13 @@
|
||||
<field name="model">ai.robot</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<header>
|
||||
</header>
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="openapi_api_key" password="True"/>
|
||||
<field name="openapi_api_key" password="True" required="True"/>
|
||||
<field name="temperature"/>
|
||||
<field name="sequence"/>
|
||||
</group>
|
||||
@@ -37,6 +40,14 @@
|
||||
<field name="provider"/>
|
||||
<a href="https://platform.openai.com/docs/introduction" title="OpenAI Document" class="o_doc_link" target="_blank"></a>
|
||||
</div>
|
||||
<field name="max_length"/>
|
||||
<field name="engine"/>
|
||||
<field name="endpoint"/>
|
||||
<field name="api_version"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="is_filtering"/>
|
||||
<field name="sensitive_words" attrs="{'invisible': [('is_filtering', '=', False)]}"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
|
||||
@@ -6,14 +6,18 @@
|
||||
<field name="inherit_id" ref="base_setup.res_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='integration']" position="after">
|
||||
<h2>ChatGPT</h2>
|
||||
<h2>Ai Center(Chatgpt)</h2>
|
||||
<div class="col-xs-12 row o_settings_container" id="chatgpt_integraion">
|
||||
<div class="col-xs-12 col-md-10 o_setting_box">
|
||||
<div class="o_setting_right_pane border-start-0">
|
||||
<div class="content-group">
|
||||
<div class="row mt0">
|
||||
<label class="col-lg-2" string="上下文连接超时" for="openapi_context_timeout"/>
|
||||
<field name="openapi_context_timeout" title="上下文连接超时 秒数" style="width: 10% !important;"/>秒
|
||||
<label class="col-lg-2" string="Timout then disconnect(s)" for="openapi_context_timeout"/>
|
||||
<field name="openapi_context_timeout" title="After timeout seconds then Disconnect" style="width: 10% !important;"/>Seconds
|
||||
</div>
|
||||
<div class="row mt0">
|
||||
<label class="col-lg-2" for="openai_sync_config"/>
|
||||
<field name="openai_sync_config" style="width: 10% !important;"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<field name="model">res.users</field>
|
||||
<field name="inherit_id" ref="base.view_users_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//page[@name='preferences']" position="after">
|
||||
<xpath expr="//group[@name='preferences']/../.." position="after">
|
||||
<page name="page_chatgpt" string="ChatGPT">
|
||||
<group>
|
||||
<group>
|
||||
|
||||