hAmAruKi commited on
Commit
ea8b9b3
1 Parent(s): b116934

add base app

Browse files
Files changed (14) hide show
  1. .dockerignore +11 -0
  2. .gitignore +137 -0
  3. .streamlit/config.toml +6 -0
  4. Dockerfile +19 -0
  5. app.py +31 -0
  6. config_loader.py +17 -0
  7. docker-compose.yml +12 -0
  8. img/screenshot.png +0 -0
  9. line_bot.py +62 -0
  10. main.py +32 -0
  11. ngrok_manager.py +15 -0
  12. requirements.txt +4 -0
  13. settings.json +5 -0
  14. youri_bot.py +103 -0
.dockerignore ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __pycache__
2
+ *.pyc
3
+ *.pyo
4
+ *.pyd
5
+ .Python
6
+ .env*
7
+ .cache
8
+ *.log
9
+ .git*
10
+ scripts
11
+ archive
.gitignore ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .python-version
2
+ /.vscode/
3
+ *.code-workspace
4
+ todo.txt
5
+ *.ipynb
6
+ .env
7
+ .DS_Store
8
+
9
+ # Byte-compiled / optimized / DLL files
10
+ __pycache__/
11
+ *.py[cod]
12
+ *$py.class
13
+
14
+ # C extensions
15
+ *.so
16
+
17
+ # Distribution / packaging
18
+ .Python
19
+ build/
20
+ develop-eggs/
21
+ dist/
22
+ downloads/
23
+ eggs/
24
+ .eggs/
25
+ lib/
26
+ lib64/
27
+ parts/
28
+ sdist/
29
+ var/
30
+ wheels/
31
+ pip-wheel-metadata/
32
+ share/python-wheels/
33
+ *.egg-info/
34
+ .installed.cfg
35
+ *.egg
36
+ MANIFEST
37
+
38
+ # PyInstaller
39
+ # Usually these files are written by a python script from a template
40
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
41
+ *.manifest
42
+ *.spec
43
+
44
+ # Installer logs
45
+ pip-log.txt
46
+ pip-delete-this-directory.txt
47
+
48
+ # Unit test / coverage reports
49
+ htmlcov/
50
+ .tox/
51
+ .nox/
52
+ .coverage
53
+ .coverage.*
54
+ .cache
55
+ nosetests.xml
56
+ coverage.xml
57
+ *.cover
58
+ *.py,cover
59
+ .hypothesis/
60
+ .pytest_cache/
61
+
62
+ # Translations
63
+ *.mo
64
+ *.pot
65
+
66
+ # Django stuff:
67
+ *.log
68
+ local_settings.py
69
+ db.sqlite3
70
+ db.sqlite3-journal
71
+
72
+ # Flask stuff:
73
+ instance/
74
+ .webassets-cache
75
+
76
+ # Scrapy stuff:
77
+ .scrapy
78
+
79
+ # Sphinx documentation
80
+ docs/_build/
81
+
82
+ # PyBuilder
83
+ target/
84
+
85
+ # Jupyter Notebook
86
+ .ipynb_checkpoints
87
+
88
+ # IPython
89
+ profile_default/
90
+ ipython_config.py
91
+
92
+ # pyenv
93
+ .python-version
94
+
95
+ # pipenv
96
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
97
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
98
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
99
+ # install all needed dependencies.
100
+ #Pipfile.lock
101
+
102
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
103
+ __pypackages__/
104
+
105
+ # Celery stuff
106
+ celerybeat-schedule
107
+ celerybeat.pid
108
+
109
+ # SageMath parsed files
110
+ *.sage.py
111
+
112
+ # Environments
113
+ .env
114
+ .venv
115
+ env/
116
+ venv/
117
+ ENV/
118
+ env.bak/
119
+ venv.bak/
120
+
121
+ # Spyder project settings
122
+ .spyderproject
123
+ .spyproject
124
+
125
+ # Rope project settings
126
+ .ropeproject
127
+
128
+ # mkdocs documentation
129
+ /site
130
+
131
+ # mypy
132
+ .mypy_cache/
133
+ .dmypy.json
134
+ dmypy.json
135
+
136
+ # Pyre type checker
137
+ .pyre/
.streamlit/config.toml ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ [theme]
2
+ primaryColor="#E3371E"
3
+ backgroundColor="#F2E8DF"
4
+ secondaryBackgroundColor="#FFCB9A"
5
+ textColor="#4C5958"
6
+ font="sans serif"
Dockerfile ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.7
2
+
3
+ WORKDIR /home
4
+
5
+ # dont write pyc files
6
+ # dont buffer to stdout/stderr
7
+ ENV PYTHONDONTWRITEBYTECODE 1
8
+ ENV PYTHONUNBUFFERED 1
9
+
10
+ COPY ./requirements.txt /home/requirements.txt
11
+
12
+ # dependencies
13
+ RUN pip install --upgrade pip setuptools wheel \
14
+ && pip install -r requirements.txt \
15
+ && rm -rf /root/.cache/pip
16
+
17
+ # COPY ./ /usr/src/app
18
+
19
+ RUN pip install -U scikit-learn umap-learn hdbscan matplotlib japanize-matplotlib ipympl plotly
app.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import json
3
+ import subprocess
4
+
5
+ # タイトルの設定
6
+ st.title("Settings Configuration")
7
+
8
+ # 設定ファイルのパス
9
+ config_file_path = 'settings.json'
10
+
11
+ # 設定入力用のフォームを作成
12
+ with st.form("settings_form"):
13
+ st.write("Please enter the configuration settings:")
14
+ ngrok_authtoken = st.text_input("NGROK_AUTHTOKEN")
15
+ line_access_token = st.text_input("LINE_ACCESS_TOKEN")
16
+ line_channel_secret = st.text_input("LINE_CHANNEL_SECRET")
17
+ submitted = st.form_submit_button("Submit")
18
+
19
+ # フォームが送信された場合、入力された設定をJSONファイルとして保存
20
+ if submitted:
21
+ settings = {
22
+ "NGROK_AUTHTOKEN": ngrok_authtoken,
23
+ "LINE_ACCESS_TOKEN": line_access_token,
24
+ "LINE_CHANNEL_SECRET": line_channel_secret
25
+ }
26
+ with open(config_file_path, 'w') as config_file:
27
+ json.dump(settings, config_file, indent=4)
28
+
29
+ st.success("Settings saved successfully!")
30
+ # `main.py`をサブプロセスとして起動
31
+ subprocess.run(["python", "main.py"])
config_loader.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # config_loader.py
2
+ import json # jsonモジュールをインポートします。これによりJSON形式のファイルを扱うことができます。
3
+
4
+ # ConfigLoaderという名前のクラスを定義します。
5
+ class ConfigLoader:
6
+ # クラスの初期化メソッドです。インスタンスが作成されるときに自動的に呼び出されます。
7
+ def __init__(self, file_name):
8
+ self.file_name = file_name # file_nameという引数をインスタンス変数に代入します。
9
+ self.settings = self.load_settings() # load_settingsメソッドを呼び出して、設定を読み込みます。
10
+
11
+ # 設定をファイルから読み込むメソッドです。
12
+ def load_settings(self):
13
+ # ファイルを読み込むコンテキストを開始します。'r'は読み込みモードを意味します。
14
+ with open(self.file_name, 'r') as file:
15
+ # json.loadを使って、開いたファイルの内容をJSONとして読み込みます。
16
+ # 読み込んだデータはPythonの辞書形式に変換されます。
17
+ return json.load(file)
docker-compose.yml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ build: ./
6
+ # command: streamlit run app.py --server.port 8502
7
+ volumes:
8
+ - ./:/home
9
+ ports:
10
+ - 8502:8502
11
+ tty:
12
+ true
img/screenshot.png ADDED
line_bot.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # line_bot.py
2
+ from flask import Flask, request, abort
3
+ from linebot import LineBotApi, WebhookHandler
4
+ from linebot.exceptions import InvalidSignatureError
5
+ from linebot.models import MessageEvent, TextMessage, TextSendMessage
6
+
7
+ # LineBot クラスを定義します。
8
+ # このクラスは、LINE Bot APIとのやり取りを管理するためのメソッドを含んでいます。
9
+ class LineBot:
10
+ # コンストラクタでは、LINE Bot APIとWebhookHandlerの初期化を行います。
11
+ def __init__(self, access_token, channel_secret):
12
+ # LineBotApiオブジェクトを作成し、LINEのアクセストークンを設定します。
13
+ self.line_bot_api = LineBotApi(access_token)
14
+ # WebhookHandlerオブジェクトを作成し、LINEのチャネルシークレットを設定します。
15
+ self.handler = WebhookHandler(channel_secret)
16
+
17
+ # Flaskアプリケーションを作成するメソッドです。
18
+ def create_app(self):
19
+ # Flaskのインスタンスを作成します。
20
+ app = Flask(__name__)
21
+
22
+ # '/test'のパスにアクセスがあった場合の処理を定義します。
23
+ @app.route("/test")
24
+ def test():
25
+ # テスト用のエンドポイントなので、"TEST OK"というレスポンスを返します。
26
+ return "TEST OK"
27
+
28
+ # '/'のパスにPOSTリクエストがあった場合の処理を定義します。
29
+ # これはLINE PlatformからのWebhookを処理するためのエンドポイントです。
30
+ @app.route("/", methods=['POST'])
31
+ def callback():
32
+ # LINE Platformからのリクエストに含まれる署名を取得します。
33
+ signature = request.headers['X-Line-Signature']
34
+ # リクエストの本体(body)をテキストとして取得します。
35
+ body = request.get_data(as_text=True)
36
+ # リクエストの内容をログに記録します。
37
+ app.logger.info("Request body: " + body)
38
+
39
+ # 署名を検証し、イベントハンドラを呼び出します。
40
+ try:
41
+ self.handler.handle(body, signature)
42
+ except InvalidSignatureError:
43
+ # 署名が無効な場合は、エラーメッセージを出力し、400エラーを返します。
44
+ print("Invalid signature. Please check your channel access token/channel secret.")
45
+ abort(400)
46
+
47
+ # すべて正常に処理された場合は、'OK'のレスポンスを返します。
48
+ return 'OK'
49
+
50
+ # MessageEventとTextMessageを処理するイベントハンドラを定義します。
51
+ @self.handler.add(MessageEvent, message=TextMessage)
52
+ def handle_message(event):
53
+ # 受信したメッセージの内容をログに出力します。
54
+ print("event.message.text:{}".format(event.message.text))
55
+ # ユーザーに送られたテキストメッセージと同じ内容で返信します。
56
+ self.line_bot_api.reply_message(
57
+ event.reply_token,
58
+ TextSendMessage(text=event.message.text),
59
+ )
60
+
61
+ # Flaskアプリケーションのインスタンスを返します。
62
+ return app
main.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # main.py
2
+ # 必要なクラスを他のファイルからインポートします。
3
+ from config_loader import ConfigLoader
4
+ from ngrok_manager import NgrokManager
5
+ from line_bot import LineBot
6
+ # from youri_bot import YouriBot
7
+
8
+ # このスクリプトが直接実行された時だけ、以下のコードが実行されます。
9
+ if __name__ == '__main__':
10
+ # 設定ファイル 'settings.json' を読み込むために ConfigLoader クラスを使用します。
11
+ config_loader = ConfigLoader('settings.json')
12
+
13
+ # 設定ファイルから読み込んだ設定を取得します。
14
+ settings = config_loader.settings
15
+
16
+ # Ngrokを管理するためのクラスをインスタンス化し、ngrokのAuthtokenを渡します。
17
+ ngrok_manager = NgrokManager(settings['NGROK_AUTHTOKEN'])
18
+
19
+ # ngrokによって生成されたWebhook URLを出力します。
20
+ print(f"Webhook URL: {ngrok_manager.webhook_url}")
21
+
22
+ # LINE Botのインスタンスを作成します。これには、設定から取得したアクセストークンと
23
+ # チャネルシークレットを渡します。
24
+ bot = LineBot(settings['LINE_ACCESS_TOKEN'], settings['LINE_CHANNEL_SECRET'])
25
+ # bot = YouriBot(settings['LINE_ACCESS_TOKEN'], settings['LINE_CHANNEL_SECRET'])
26
+
27
+ # Flaskアプリケーションを作成します。
28
+ app = bot.create_app()
29
+
30
+ # アプリケーションを起動します。これにより、Webサーバーが起動し、
31
+ # LINEからのリクエストを待機する状態になります。
32
+ app.run()
ngrok_manager.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ngrok_manager.py
2
+ import os
3
+ from pyngrok import ngrok
4
+ from pyngrok.conf import PyngrokConfig
5
+
6
+ class NgrokManager:
7
+ def __init__(self, authtoken):
8
+ self.authtoken = authtoken
9
+ self.webhook_url = self.start_ngrok()
10
+
11
+ def start_ngrok(self):
12
+ # 既に実行中のngrokプロセスを終了します(もしあれば)。
13
+ os.system('kill -9 $(pgrep ngrok)')
14
+ # 認証トークンを設定した状態でngrokセッションを開始します。
15
+ return ngrok.connect(addr='127.0.0.1:5000', pyngrok_config=PyngrokConfig(start_new_session=True))
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ streamlit
2
+ pyngrok
3
+ flask
4
+ line-bot-sdk
settings.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ {
2
+ "NGROK_AUTHTOKEN": "2Xekcp4V81ixf4G9q4ih2GrefKp_3BcdjGJYi1zgAxVTShf2",
3
+ "LINE_ACCESS_TOKEN": "hCsTRCitcPJUPEgAY1kaBnVBVEdzGG8ju6yXI7mSs3dyZQiW5KJw13wIdLmWr3AstOxCd9SuikXI45jpjJHojdjDCoV+Yy8UmPJ6ZrGvBs172Rcs/SP+V9UGJtvmdfRelQB9i4cdGEYYoNTzU8ujewdB04t89/1O/w1cDnyilFU=",
4
+ "LINE_CHANNEL_SECRET": "af80ad7b208212a7ee6a73e9ab2d0127"
5
+ }
youri_bot.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # line_bot.py
2
+ from flask import Flask, request, abort
3
+ from linebot import LineBotApi, WebhookHandler
4
+ from linebot.exceptions import InvalidSignatureError
5
+ from linebot.models import MessageEvent, TextMessage, TextSendMessage
6
+ from line_bot import LineBot # your_line_bot_fileは、LineBotクラスを含むファイルの名前です。
7
+ import torch
8
+ from transformers import AutoTokenizer
9
+ from auto_gptq import AutoGPTQForCausalLM # your_model_libraryは、モデルクラスを含むライブラリの名前です。
10
+
11
+ # LineBot クラスを定義します。
12
+ # このクラスは、LINE Bot APIとのやり取りを管理するためのメソッドを含んでいます。
13
+ class YouriBot(LineBot):
14
+ # コンストラクタでは、LINE Bot APIとWebhookHandlerの初期化を行います。
15
+ def __init__(self, access_token, channel_secret):
16
+ # LineBotApiオブジェクトを作成し、LINEのアクセストークンを設定します。
17
+ self.line_bot_api = LineBotApi(access_token)
18
+ # WebhookHandlerオブジェクトを作成し、LINEのチャネルシークレットを設定します。
19
+ self.handler = WebhookHandler(channel_secret)
20
+ # トークナイザーとモデルの準備
21
+ self.tokenizer = AutoTokenizer.from_pretrained(
22
+ "rinna/youri-7b-chat-gptq"
23
+ )
24
+ self.model = AutoGPTQForCausalLM.from_quantized(
25
+ "rinna/youri-7b-chat-gptq",
26
+ device_map="auto",
27
+ use_safetensors=True
28
+ )
29
+
30
+ def generate_response(self, prompt):
31
+ # 推論の実行
32
+ token_ids = self.tokenizer.encode(
33
+ prompt,
34
+ add_special_tokens=False,
35
+ return_tensors="pt")
36
+ with torch.no_grad():
37
+ output_ids = self.model.generate(
38
+ input_ids=token_ids.to(self.model.device),
39
+ max_new_tokens=200,
40
+ do_sample=True,
41
+ temperature=0.5,
42
+ pad_token_id=self.tokenizer.pad_token_id,
43
+ bos_token_id=self.tokenizer.bos_token_id,
44
+ eos_token_id=self.tokenizer.eos_token_id
45
+ )
46
+ return self.tokenizer.decode(
47
+ output_ids[0][token_ids.size(1):],
48
+ skip_special_tokens=True
49
+ )
50
+
51
+ # Flaskアプリケーションを作成するメソッドです。
52
+ def create_app(self):
53
+ # Flaskのインスタンスを作成します。
54
+ app = Flask(__name__)
55
+
56
+ # '/test'のパスにアクセスがあった場合の処理を定義します。
57
+ @app.route("/test")
58
+ def test():
59
+ # テスト用のエンドポイントなので、"TEST OK"というレスポンスを返します。
60
+ return "TEST OK"
61
+
62
+ # '/'のパスにPOSTリクエストがあった場合の処理を定義します。
63
+ # これはLINE PlatformからのWebhookを処理するためのエンドポイントです。
64
+ @app.route("/", methods=['POST'])
65
+ def callback():
66
+ # LINE Platformからのリクエストに含まれる署名を取得します。
67
+ signature = request.headers['X-Line-Signature']
68
+ # リクエストの本体(body)をテキストとして取得します。
69
+ body = request.get_data(as_text=True)
70
+ # リクエストの内容をログに記録します。
71
+ app.logger.info("Request body: " + body)
72
+
73
+ # 署名を検証し、イベントハンドラを呼び出します。
74
+ try:
75
+ self.handler.handle(body, signature)
76
+ except InvalidSignatureError:
77
+ # 署名が無効な場合は、エラーメッセージを出力し、400エラーを返します。
78
+ print("Invalid signature. Please check your channel access token/channel secret.")
79
+ abort(400)
80
+
81
+ # すべて正常に処理された場合は、'OK'のレスポンスを返します。
82
+ return 'OK'
83
+
84
+ # MessageEventとTextMessageを処理するイベントハンドラを定義します。
85
+ @self.handler.add(MessageEvent, message=TextMessage)
86
+ def handle_message(event):
87
+ # 受信したメッセージの内容をログに出力します。
88
+ print("event.message.text:{}".format(event.message.text))
89
+ # ユーザーに送られたテキストメッセージと同じ内容で返信します。
90
+
91
+ prompt = f"設定: あなたの優秀なAIアシスタントです。\nユーザー: {event.message.text}\nシステム: "
92
+ print(f"prompt:{prompt}")
93
+ # AIによるレスポンス生成
94
+ response_text = self.generate_response(prompt)
95
+ print(f"response_text:{response_text}")
96
+
97
+ self.line_bot_api.reply_message(
98
+ event.reply_token,
99
+ TextSendMessage(text=event.message.text),
100
+ )
101
+
102
+ # Flaskアプリケーションのインスタンスを返します。
103
+ return app