Skip to content

Commit e1c15a6

Browse files
committed
Add local file knowledge base
1 parent ce55769 commit e1c15a6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+4255
-1612
lines changed

crawler_module/__init__.py

-1
This file was deleted.

crawler_module/document_embedding.py

-55
This file was deleted.

env_of_openai

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
LLM_NAME="OpenAI"
2+
OPENAI_API_KEY="xxxx"
3+
GPT_MODEL_NAME="gpt-3.5-turbo"
4+
MIN_RELEVANCE_SCORE=0.3
5+
BOT_TOPIC="xxxx"
6+
URL_PREFIX="http://127.0.0.1:7000/"
7+
USE_PREPROCESS_QUERY=0
8+
USE_RERANKING=1
9+
USE_DEBUG=0

env_of_zhipuai

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
LLM_NAME="ZhipuAI"
2+
ZHIPUAI_API_KEY="xxxx"
3+
GLM_MODEL_NAME="glm-3-turbo"
4+
MIN_RELEVANCE_SCORE=0.3
5+
BOT_TOPIC="xxxx"
6+
URL_PREFIX="http://127.0.0.1:7000/"
7+
USE_PREPROCESS_QUERY=0
8+
USE_RERANKING=1
9+
USE_DEBUG=0

rag_gpt_app.py

+26-1,317
Large diffs are not rendered by default.

requirements.txt

+11
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,14 @@ flask-cors==4.0.0
1616
diskcache==5.6.3
1717
html2text==2024.2.26
1818
langchain-openai==0.1.3
19+
py3langid==0.2.2
20+
zhipuai==2.0.1
21+
pymupdf==1.24.2
22+
mammoth==1.7.1
23+
python-pptx==0.6.23
24+
pandas==2.2.1
25+
tabulate==0.9.0
26+
aiofiles==23.2.1
27+
tokenizers==0.15.2
28+
onnxruntime==1.16.3
29+
numpy==1.26.4

server/__init__.py

Whitespace-only changes.

server/app/__init__.py

Whitespace-only changes.

server/app/account.py

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import time
2+
from flask import Blueprint, Flask, request
3+
from werkzeug.security import generate_password_hash, check_password_hash
4+
from server.app.utils.decorators import token_required
5+
from server.app.utils.diskcache_lock import diskcache_lock
6+
from server.app.utils.sqlite_client import get_db_connection
7+
from server.app.utils.token_helper import TokenHelper
8+
from server.logger.logger_config import my_logger as logger
9+
10+
11+
account_bp = Blueprint('account_config', __name__, url_prefix='/open_kf_api/account')
12+
13+
14+
@account_bp.route('/login', methods=['POST'])
15+
def login():
16+
data = request.json
17+
account_name = data.get('account_name')
18+
password = data.get('password')
19+
20+
if not account_name or not password:
21+
return {'retcode': -20000, 'message': 'Account name and password are required', 'data': {}}
22+
23+
conn = None
24+
try:
25+
conn = get_db_connection()
26+
cur = conn.cursor()
27+
28+
# Check if the account exists and verify the password
29+
cur.execute('SELECT id, password_hash FROM t_account_tab WHERE account_name = ?', (account_name,))
30+
account = cur.fetchone()
31+
32+
if account and check_password_hash(account['password_hash'], password):
33+
# Generate token with account_name in the payload
34+
token = TokenHelper.generate_token(account_name)
35+
logger.info(f"Generate token: '{token}'")
36+
37+
# Set is_login to 1 and update mtime to the current Unix timestamp
38+
try:
39+
with diskcache_lock.lock():
40+
cur.execute('UPDATE t_account_tab SET is_login = 1, mtime = ? WHERE account_name = ?', (int(time.time()), account_name,))
41+
conn.commit()
42+
except Exception as e:
43+
logger.error(f"Process discache_lock exception: {e}")
44+
return {'retcode': -30000, 'message': f'An error occurred: {e}', 'data': {}}
45+
46+
return {'retcode': 0, 'message': 'Login successful', 'data': {'token': token}}
47+
else:
48+
return {'retcode': -20001, 'message': 'Invalid credentials', 'data': {}}
49+
except Exception as e:
50+
return {'retcode': -30000, 'message': f'An error occurred during login, exception: {e}', 'data': {}}
51+
finally:
52+
if conn:
53+
conn.close()
54+
55+
56+
@account_bp.route('/update_password', methods=['POST'])
57+
@token_required
58+
def update_password():
59+
data = request.json
60+
account_name = data.get('account_name')
61+
current_password = data.get('current_password')
62+
new_password = data.get('new_password')
63+
64+
if None in (account_name, current_password, new_password):
65+
return {'retcode': -20000, 'message': 'Account name, current password, and new password are required', 'data': {}}
66+
67+
token_user_id = request.user_payload['user_id']
68+
if token_user_id != account_name:
69+
logger.error(f"account_name:'{account_name}' does not match with token_user_id: '{token_user_id}'")
70+
return {'retcode': -20001, 'message': 'Token is invalid!', 'data': {}}
71+
72+
conn = None
73+
try:
74+
conn = get_db_connection()
75+
cur = conn.cursor()
76+
77+
# Check if the account exists and verify the current password
78+
cur.execute('SELECT id, password_hash FROM t_account_tab WHERE account_name = ?', (account_name,))
79+
account = cur.fetchone()
80+
81+
if not account or not check_password_hash(account['password_hash'], current_password):
82+
logger.error(f"Invalid account_name: '{account_name}' or current_password: '{current_password}'")
83+
return {'retcode': -20001, 'message': 'Invalid account name or password', 'data': {}}
84+
85+
# Update the password
86+
new_password_hash = generate_password_hash(new_password, method='pbkdf2:sha256', salt_length=10)
87+
try:
88+
with diskcache_lock.lock():
89+
cur.execute('UPDATE t_account_tab SET password_hash = ?, mtime = ? WHERE account_name = ?', (new_password_hash, int(time.time()), account_name,))
90+
conn.commit()
91+
except Exception as e:
92+
logger.error(f"Process discache_lock exception: {e}")
93+
return {'retcode': -30000, 'message': f'An error occurred: {e}', 'data': {}}
94+
95+
return {'retcode': 0, 'message': 'Password updated successfully', 'data': {}}
96+
except Exception as e:
97+
return {'retcode': -20001, 'message': f'An error occurred: {e}', 'data': {}}
98+
finally:
99+
if conn:
100+
conn.close()

server/app/auth.py

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from flask import Blueprint, request
2+
from server.logger.logger_config import my_logger as logger
3+
from server.app.utils.token_helper import TokenHelper
4+
5+
6+
auth_bp = Blueprint('auth', __name__, url_prefix='/open_kf_api/auth')
7+
8+
9+
@auth_bp.route('/get_token', methods=['POST'])
10+
def get_token():
11+
data = request.json
12+
user_id = data.get('user_id')
13+
if not user_id:
14+
return {'retcode': -20000, 'message': 'user_id is required', 'data': {}}
15+
16+
try:
17+
# generate token
18+
token = TokenHelper.generate_token(user_id)
19+
logger.success(f"Generate token: '{token}' with user_id: '{user_id}'")
20+
return {"retcode": 0, "message": "success", "data": {"token": token}}
21+
except Exception as e:
22+
logger.error(f"Generate token with user_id: '{user_id}' is failed, the exception is {e}")
23+
return {'retcode': -20001, 'message': str(e), 'data': {}}

server/app/bot_config.py

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import json
2+
import time
3+
from flask import Blueprint, Flask, request
4+
from server.app.utils.decorators import token_required
5+
from server.app.utils.sqlite_client import get_db_connection
6+
from server.app.utils.diskcache_client import diskcache_client
7+
from server.app.utils.diskcache_lock import diskcache_lock
8+
from server.logger.logger_config import my_logger as logger
9+
10+
11+
bot_config_bp = Blueprint('bot_config', __name__, url_prefix='/open_kf_api/bot_config')
12+
13+
14+
@bot_config_bp.route('/get_bot_setting', methods=['POST'])
15+
def get_bot_setting():
16+
"""Retrieve bot setting, first trying Cache and falling back to DB if not found."""
17+
try:
18+
# Attempt to retrieve the setting from Cache
19+
key = "open_kf:bot_setting"
20+
setting_cache = diskcache_client.get(key)
21+
if setting_cache:
22+
setting_data = json.loads(setting_cache)
23+
return {'retcode': 0, 'message': 'Success', 'data': {'config': setting_data}}
24+
else:
25+
logger.warning(f"could not find '{key}' in Cache!")
26+
except Exception as e:
27+
logger.error(f"Error retrieving setting from Cache, excpetion:{e}")
28+
# Just ignore Cache error
29+
#return {'retcode': -30000, 'message': f'An error occurred: {str(e)}', 'data': {}}
30+
31+
conn = None
32+
try:
33+
conn = get_db_connection()
34+
cur = conn.cursor()
35+
36+
cur.execute('SELECT * FROM t_bot_setting_tab LIMIT 1')
37+
setting = cur.fetchone()
38+
if setting:
39+
setting = dict(setting)
40+
# Process and return the setting details
41+
setting_data = {k: json.loads(v) if k in ['initial_messages', 'suggested_messages'] else v for k, v in setting.items()}
42+
43+
# Add bot setting into Cache
44+
try:
45+
key = "open_kf:bot_setting"
46+
diskcache_client.set(key, json.dumps(setting_data))
47+
except Exception as e:
48+
logger.error(f"Add bot setting into Cache is failed, the exception is {e}")
49+
# Just ignore Reids error
50+
51+
return {'retcode': 0, 'message': 'Success', 'data': {'config': setting_data}}
52+
else:
53+
logger.warning(f"No setting found")
54+
return {'retcode': -20001, 'message': 'No setting found', 'data': {}}
55+
except Exception as e:
56+
logger.error(f"Error retrieving setting: {e}")
57+
return {'retcode': -30000, 'message': f'An error occurred: {e}', 'data': {}}
58+
finally:
59+
if conn:
60+
conn.close()
61+
62+
63+
@bot_config_bp.route('/update_bot_setting', methods=['POST'])
64+
@token_required
65+
def update_bot_setting():
66+
data = request.json
67+
# Extract and validate all required fields
68+
setting_id = data.get('id')
69+
initial_messages = data.get('initial_messages')
70+
suggested_messages = data.get('suggested_messages')
71+
bot_name = data.get('bot_name')
72+
bot_avatar = data.get('bot_avatar')
73+
chat_icon = data.get('chat_icon')
74+
placeholder = data.get('placeholder')
75+
model = data.get('model')
76+
77+
# Check for the presence of all required fields
78+
if None in (setting_id, initial_messages, suggested_messages, bot_name, bot_avatar, chat_icon, placeholder, model):
79+
return {'retcode': -20000, 'message': 'All fields are required', 'data': {}}
80+
81+
conn = None
82+
try:
83+
conn = get_db_connection()
84+
cur = conn.cursor()
85+
86+
# Check if the setting with provided ID exists
87+
cur.execute('SELECT id FROM t_bot_setting_tab WHERE id = ?', (setting_id,))
88+
if not cur.fetchone():
89+
logger.error(f"No setting found")
90+
return {'retcode': -20001, 'message': 'Setting not found', 'data': {}}
91+
92+
# Convert lists to JSON strings for storage
93+
initial_messages_json = json.dumps(initial_messages)
94+
suggested_messages_json = json.dumps(suggested_messages)
95+
96+
# Update bot setting in DB
97+
timestamp = int(time.time())
98+
try:
99+
with diskcache_lock.lock():
100+
cur.execute('''
101+
UPDATE t_bot_setting_tab
102+
SET initial_messages = ?, suggested_messages = ?, bot_name = ?, bot_avatar = ?, chat_icon = ?, placeholder = ?, model = ?, mtime = ?
103+
WHERE id = ?
104+
''', (initial_messages_json, suggested_messages_json, bot_name, bot_avatar, chat_icon, placeholder, model, timestamp, setting_id))
105+
conn.commit()
106+
except Exception as e:
107+
logger.error(f"Process discache_lock exception: {e}")
108+
return {'retcode': -30000, 'message': f'An error occurred: {e}', 'data': {}}
109+
110+
# Update bot setting in Cache
111+
try:
112+
key = "open_kf:bot_setting"
113+
bot_setting = {
114+
'id': setting_id,
115+
'initial_messages': initial_messages,
116+
'suggested_messages': suggested_messages,
117+
'bot_name': bot_name,
118+
'bot_avatar': bot_avatar,
119+
'chat_icon': chat_icon,
120+
'placeholder': placeholder,
121+
'model': model,
122+
'ctime': timestamp,
123+
'mtime': timestamp
124+
}
125+
diskcache_client.set(key, json.dumps(bot_setting))
126+
except Exception as e:
127+
logger.error(f"Ppdate bot seeting in Cache is failed, the exception is {e}")
128+
return {'retcode': -20001, 'message': f'An error occurred: {e}', 'data': {}}
129+
130+
return {'retcode': 0, 'message': 'Settings updated successfully', 'data': {}}
131+
except Exception as e:
132+
logger.error(f"Error updating setting in DB: {e}")
133+
return {'retcode': -30000, 'message': f'An error occurred: {e}', 'data': {}}
134+
finally:
135+
if conn:
136+
conn.close()

server/app/common.py

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from datetime import datetime
2+
import os
3+
import uuid
4+
from flask import Blueprint, Flask, request
5+
from werkzeug.utils import secure_filename
6+
from server.constant.constants import STATIC_DIR, MEDIA_DIR
7+
from server.app.utils.decorators import token_required
8+
from server.logger.logger_config import my_logger as logger
9+
10+
11+
URL_PREFIX = os.getenv('URL_PREFIX')
12+
13+
common_bp = Blueprint('common', __name__, url_prefix='/open_kf_api/common')
14+
15+
16+
@common_bp.route('/upload_picture', methods=['POST'])
17+
@token_required
18+
def upload_picture():
19+
picture_file = request.files.get('picture_file')
20+
if not picture_file:
21+
logger.error("Missing required parameters picture_file")
22+
return {'retcode': -20000, 'message': 'Missing required parameters picture_file', data:{}}
23+
24+
try:
25+
original_filename = secure_filename(picture_file.filename)
26+
27+
day_folder = datetime.now().strftime("%Y_%m_%d")
28+
unique_folder = str(uuid.uuid4())
29+
save_directory = os.path.join(STATIC_DIR, MEDIA_DIR, day_folder, unique_folder)
30+
os.makedirs(save_directory, exist_ok=True)
31+
32+
image_path = os.path.join(save_directory, original_filename)
33+
picture_file.save(image_path)
34+
picture_url = f"{URL_PREFIX}{MEDIA_DIR}/{day_folder}/{unique_folder}/{original_filename}"
35+
return {'retcode': 0, 'message': 'upload picture success', 'data': {'picture_url': picture_url}}
36+
except Exception as e:
37+
logger.error(f"An error occureed: {str(e)}")
38+
return {'retcode': -30000, 'message': f'An error occurred: {str(e)}', 'data': {}}

0 commit comments

Comments
 (0)