diff --git a/app/README.md b/app/README.md new file mode 100644 index 0000000..e69de29 diff --git a/app/__pycache__/asyncproxy.cpython-310.pyc b/app/__pycache__/asyncproxy.cpython-310.pyc new file mode 100644 index 0000000..c7e6666 Binary files /dev/null and b/app/__pycache__/asyncproxy.cpython-310.pyc differ diff --git a/app/__pycache__/const.cpython-310.pyc b/app/__pycache__/const.cpython-310.pyc new file mode 100644 index 0000000..a7e7c96 Binary files /dev/null and b/app/__pycache__/const.cpython-310.pyc differ diff --git a/app/__pycache__/ext.cpython-310.pyc b/app/__pycache__/ext.cpython-310.pyc new file mode 100644 index 0000000..d1a089a Binary files /dev/null and b/app/__pycache__/ext.cpython-310.pyc differ diff --git a/app/__pycache__/llm_client.cpython-310.pyc b/app/__pycache__/llm_client.cpython-310.pyc new file mode 100644 index 0000000..5dd2ca4 Binary files /dev/null and b/app/__pycache__/llm_client.cpython-310.pyc differ diff --git a/app/__pycache__/rf.cpython-310.pyc b/app/__pycache__/rf.cpython-310.pyc new file mode 100644 index 0000000..54e3a5c Binary files /dev/null and b/app/__pycache__/rf.cpython-310.pyc differ diff --git a/app/__pycache__/streamproxy.cpython-310.pyc b/app/__pycache__/streamproxy.cpython-310.pyc new file mode 100644 index 0000000..bac737b Binary files /dev/null and b/app/__pycache__/streamproxy.cpython-310.pyc differ diff --git a/app/__pycache__/syncproxy.cpython-310.pyc b/app/__pycache__/syncproxy.cpython-310.pyc new file mode 100644 index 0000000..646052a Binary files /dev/null and b/app/__pycache__/syncproxy.cpython-310.pyc differ diff --git a/app/asr.py b/app/asr.py new file mode 100644 index 0000000..5abeec7 --- /dev/null +++ b/app/asr.py @@ -0,0 +1,34 @@ +import os, sys +import argparse +from appPublic.log import MyLogger, info, debug, warning +from appPublic.folderUtils import ProgramPath +from appPublic.jsonConfig import getConfig +from ahserver.configuredServer import ConfiguredServer +import asr_engine + +__version__ = '0.0.1' + +if __name__ == '__main__': + parser = argparse.ArgumentParser(prog="Sage") + parser.add_argument('-w', '--workdir') + parser.add_argument('-p', '--port') + args = parser.parse_args() + workdir = args.workdir or os.getcwd() + p = ProgramPath() + config = getConfig(workdir, NS={'workdir':workdir, 'ProgramPath':p}) + if config.logger: + logger = MyLogger(config.logger.name or 'sage', + levelname=config.logger.levelname or 'debug', + logfile=config.logger.logfile or None) + else: + logger = MyLogger('sage', levelname='debug') + + info(f'========sage version={__version__}========') + # server = ConfiguredServer(auth_klass=MyAuthAPI, workdir=workdir) + server = ConfiguredServer(workdir=workdir) + g = ServerEnv() + g.whisper_model = WhisperBase64() + port = args.port or config.website.port or 8080 + port = int(port) + server.run(port=port) + diff --git a/app/asr_engine.py b/app/asr_engine.py new file mode 100644 index 0000000..a5f4ced --- /dev/null +++ b/app/asr_engine.py @@ -0,0 +1,31 @@ +from ahserver.serverenv import ServerEnv +from aiohttp.web import StreamResponse + +from whisper.load_model import WhisperBase64 + +async def generate(request, **kw): + model = kw.get('model', 'whisper') + engine = None + g = ServerEnv() + if model=='whisper': + engine = g.whisper_engine + if engine is None: + engine = WhisperBase64 + g.whisper_engine = engine + + await resp.prepare(request) + line = await request.content.readline() + content = '' + while line: + txt = await engine.stt(line) + content += txt + d = json.dumps({'content':content}) + btxt = d.encode('utf8') + await resp.write(btxt) + await resp.drain() + line = await request.content.readline() + return resp + +rf = RegisterFunction() +rf.register('generate', generate) + diff --git a/app/sensevoice/__init__.py b/app/sensevoice/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/sensevoice/load_model.py b/app/sensevoice/load_model.py new file mode 100644 index 0000000..e03c21f --- /dev/null +++ b/app/sensevoice/load_model.py @@ -0,0 +1,22 @@ +from ahserver.serverenv import ServerEnv +from appPublic.worker import awaitify +from appPublic.jsonConfig import getConfig, get_definition +from funasr import AutoModel +from funasr.utils.postprocess_utils import rich_transcription_postprocess + +class SenseVoiceBase: + def __init__(self): + model_dir = get_definition('sensevoice_path') + self.model = AutoModel(model=model_dir) + + def _stt(self, x): + pass + stt = awaitify(_stt) + +class SenseVoiceFile(SenseVoiceBase): + def _stt(self, filepath): + res = this.model.generate(input=filepath,language="auto", + use_itn=True, + batch_size_s=60 + ) + return rich_transcription_postprocess(res[0]["text"]) diff --git a/app/whisper/__init__.py b/app/whisper/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/whisper/generate.dspy b/app/whisper/generate.dspy new file mode 100644 index 0000000..e5f5ddb --- /dev/null +++ b/app/whisper/generate.dspy @@ -0,0 +1,4 @@ +path = params_kw.get('audiofile') +print(f'whisper.generate.dspy, {params_kw=}, {file_realpath=}, {stt_engine=}' ) +x = await stt_engine.stt(file_realpath(path)) +return x diff --git a/app/whisper/load_model.py b/app/whisper/load_model.py new file mode 100644 index 0000000..221e207 --- /dev/null +++ b/app/whisper/load_model.py @@ -0,0 +1,45 @@ +from ahserver.serverenv import ServerEnv +from appPublic.worker import awaitify +from appPublic.jsonConfig import getConfig, get_definition +import numpy as np +import base64 +import whisper + +# 编码 +def base64_encode(text): + text_bytes = text.encode('utf-8') + encoded_bytes = base64.b64encode(text_bytes) + encoded_text = encoded_bytes.decode('utf-8') + return encoded_text + +# 解码 +def base64_decode(encoded_text): + encoded_bytes = encoded_text.encode('utf-8') + decoded_bytes = base64.b64decode(encoded_bytes) + decoded_text = decoded_bytes.decode('utf-8') + return decoded_text + +class WhisperBase: + def __init__(self): + model_name = get_definition('whisper_model') + self.model = whisper.load_model(model_name) + + def _stt(self, filepath): + pass + + stt = awaitify(_stt) + +class WhisperFile(WhisperBase): + def _stt(self, filepath): + return self.model.transcribe(filepath) + + +class WhisperBase64(WhisperBase): + def _stt(self, audio_base64): + raw = base64.decode(audio_base64) + ndarr = np.frombuffer(raw, dtype=np.float32) + return self.model.transcribe(raw) + +g = ServerEnv() +g.whisper_engine = WhisperBase64() + diff --git a/app/whisper/requirements.txt b/app/whisper/requirements.txt new file mode 100644 index 0000000..4076923 --- /dev/null +++ b/app/whisper/requirements.txt @@ -0,0 +1,2 @@ +openai-whisper + diff --git a/conf/config.json b/conf/config.json new file mode 100755 index 0000000..3f7b321 --- /dev/null +++ b/conf/config.json @@ -0,0 +1,86 @@ +{ + "logger":{ + "name":"sage", + "levelname":"info", + "logfile":"$[workdir]$/logs/sage.log" + }, + "definitions":{ + "whisper_model":"/d/ymq/osc/models/whisper/large-v3.pt" + }, + "filesroot":"$[workdir]$/files", + "databases":{ + "sage":{ + "driver":"aiomysql", + "async_mode":true, + "coding":"utf8", + "maxconn":100, + "dbname":"sage", + "kwargs":{ + "user":"test", + "db":"sage", + "password":"QUZVcXg5V1p1STMybG5Ia6mX9D0v7+g=", + "host":"localhost" + } + } + }, + "website":{ + "paths":[ + ["$[workdir]$/wwwroot",""] + ], + "client_max_size":10000, + "host":"0.0.0.0", + "port":9091, + "coding":"utf-8", + "ssl_gg":{ + "crtfile":"$[workdir]$/conf/www.bsppo.com.pem", + "keyfile":"$[workdir]$/conf/www.bsppo.com.key" + }, + "indexes":[ + "index.html", + "index.tmpl", + "index.ui", + "index.dspy", + "index.md" + ], + "startswiths":[ + { + "leading":"/generate", + "registerfunction":"generate" + } + ], + "processors":[ + [".ws","ws"], + [".xterm","xterm"], + [".proxy","proxy"], + [".llm", "llm"], + [".llms", "llms"], + [".llma", "llma"], + [".xlsxds","xlsxds"], + [".sqlds","sqlds"], + [".tmpl.js","tmpl"], + [".tmpl.css","tmpl"], + [".html.tmpl","tmpl"], + [".bcrud", "bricks_crud"], + [".tmpl","tmpl"], + [".bui","bui"], + [".ui","bui"], + [".dspy","dspy"], + [".md","md"] + ], + "rsakey":{ + "privatekey":"$[workdir]$/conf/rsa_private_key.pem", + "publickey":"$[workdir]$/conf/rsa_public_key.pem" + }, + "session_max_time":3000, + "session_issue_time":2500, + "session_redis":{ + "url":"redis://127.0.0.1:6379" + } + }, + "langMapping":{ + "zh-Hans-CN":"zh-cn", + "zh-CN":"zh-cn", + "en-us":"en", + "en-US":"en" + } +} diff --git a/plugins/README.md b/plugins/README.md new file mode 100644 index 0000000..fcda301 --- /dev/null +++ b/plugins/README.md @@ -0,0 +1,15 @@ +# 大模型公司账号信息 + +## 商汤 +### 开元云账号 +用户名:kyycloud +密码:Kyy123456@ +_VaV5trl8faujgr7xaE3D +调试用Bearer令牌 apikey= +eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzpoeWRyYS5qd3QuYWNjZXNzLXRva2VuIiwidHlwIjoiSldUIn0.eyJhdWQiOltdLCJjbGllbnRfaWQiOiI0ZTQxNDg1NC03MjAwLTUwOWYtYjk2MC1mOGIwZGJiYmYzMzEiLCJleHAiOjE3MjE3Mzc5MTYsImV4dCI6eyJhbGxfYXoiOmZhbHNlLCJhel9saXN0IjpbImNuLXNoLTAxeiJdLCJpc19kZWRpY2F0ZWRfdGVuYW50IjpmYWxzZSwicHJwX2xpc3QiOltdLCJ0ZW5hbnRfY2VydGlmeV9zdGF0dXMiOmZhbHNlLCJ0ZW5hbnRfY2VydGlmeV90eXBlIjoibm9uZSIsInRlbmFudF9jb2RlIjoia3l5Y2xvdWQiLCJ0ZW5hbnRfaWQiOiIwOTVjOGRhZS1lYjAzLTQ0YmEtYjdkOS00M2QxOWYxNzJhMWIiLCJ1c2VyX2lkIjoiNTM1ZmNlNjYtM2VlOC00ZDdhLTk3OWEtNjVlNDQzMGFmNTRiIiwidXNlcl90eXBlIjoiYWRtaW4iLCJ1c2VybmFtZSI6Imt5eWNsb3VkIn0sImlhdCI6MTcyMTcyNzExNiwiaXNzIjoiaHR0cHM6Ly9zaWduaW4uc2Vuc2Vjb3JlLmNuLyIsImp0aSI6ImNhOWU2YjgyLWY1ZjktNGYyOC05OGJkLTc4ZjNiZGRmOTIxNyIsIm5iZiI6MTcyMTcyNzExNiwic2NwIjpbIm9wZW5pZCIsIm9mZmxpbmUiLCJvZmZsaW5lX2FjY2VzcyJdLCJzdWIiOiJreXljbG91ZDowOTVjOGRhZS1lYjAzLTQ0YmEtYjdkOS00M2QxOWYxNzJhMWI6NTM1ZmNlNjYtM2VlOC00ZDdhLTk3OWEtNjVlNDQzMGFmNTRiIn0.rdsmjM2kqendUdycvmSc11xJ2t8rMy2H6QrMpOOInvIWj56WJxnpj3-4aGw7SE7MQm4hw9OxAOP3JVwQKfqCz16PUmjtc8ue61vHKJw2aXtOjuv5Hb1u3HLPhN7gsflDj80KV7Ga0QD4V6XYKN9cb-MRwsLrmJLYay2oyqpX3iNyZR3z5O07CEbCVE0MDDIjxt7EyhpkfpSPKTWbnbJaOW73pdJZq6Q5xzxRvKOdywVq1-5Ifem8NyvMPqFnjc1kGVJbmD13hktC6d-R3EfoqzBz-QutGKQdhZoTj1Bo6g6imIXzAcCNbRFNU7fU5Vn8-AkdqtpY0Nhd-CCnQNIvX2ngvA08WxKV4nt9VGouuSCrbvZ8LrtiyPx3Ays3F8fUdefH91WD28YRytzfA1SrAogMfZz7zX-pKulB0erHfoveRqbY4wjDiY8lYRARVmd0d_RVNE7q6ArilvgSOo-oiJI-VQYeFse16xuUcYnvhQjNR6fSW1vARiEvztMOhF1lwPhikcXggqY7-XEklsgot3Qi402kXPu8r9WEfjdlrcY3I8eaGfRew2i4PrwKEZulgwuU7LC1VQufdQDGKxS8X_vQntHMwe1b-3s0RZ8qpMcWB6mNXSB8T6ghT2N0taCkKTc6Oe_O322Y9lLWqLXAYC96cU9eoaIyC0jXNPp9tbE + +eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzpoeWRyYS5qd3QuYWNjZXNzLXRva2VuIiwidHlwIjoiSldUIn0.eyJhdWQiOltdLCJjbGllbnRfaWQiOiI0ZTQxNDg1NC03MjAwLTUwOWYtYjk2MC1mOGIwZGJiYmYzMzEiLCJleHAiOjE3MjE3Mzc5MTYsImV4dCI6eyJhbGxfYXoiOmZhbHNlLCJhel9saXN0IjpbImNuLXNoLTAxeiJdLCJpc19kZWRpY2F0ZWRfdGVuYW50IjpmYWxzZSwicHJwX2xpc3QiOltdLCJ0ZW5hbnRfY2VydGlmeV9zdGF0dXMiOmZhbHNlLCJ0ZW5hbnRfY2VydGlmeV90eXBlIjoibm9uZSIsInRlbmFudF9jb2RlIjoia3l5Y2xvdWQiLCJ0ZW5hbnRfaWQiOiIwOTVjOGRhZS1lYjAzLTQ0YmEtYjdkOS00M2QxOWYxNzJhMWIiLCJ1c2VyX2lkIjoiNTM1ZmNlNjYtM2VlOC00ZDdhLTk3OWEtNjVlNDQzMGFmNTRiIiwidXNlcl90eXBlIjoiYWRtaW4iLCJ1c2VybmFtZSI6Imt5eWNsb3VkIn0sImlhdCI6MTcyMTcyNzExNiwiaXNzIjoiaHR0cHM6Ly9zaWduaW4uc2Vuc2Vjb3JlLmNuLyIsImp0aSI6ImNhOWU2YjgyLWY1ZjktNGYyOC05OGJkLTc4ZjNiZGRmOTIxNyIsIm5iZiI6MTcyMTcyNzExNiwic2NwIjpbIm9wZW5pZCIsIm9mZmxpbmUiLCJvZmZsaW5lX2FjY2VzcyJdLCJzdWIiOiJreXljbG91ZDowOTVjOGRhZS1lYjAzLTQ0YmEtYjdkOS00M2QxOWYxNzJhMWI6NTM1ZmNlNjYtM2VlOC00ZDdhLTk3OWEtNjVlNDQzMGFmNTRiIn0.rdsmjM2kqendUdycvmSc11xJ2t8rMy2H6QrMpOOInvIWj56WJxnpj3-4aGw7SE7MQm4hw9OxAOP3JVwQKfqCz16PUmjtc8ue61vHKJw2aXtOjuv5Hb1u3HLPhN7gsflDj80KV7Ga0QD4V6XYKN9cb-MRwsLrmJLYay2oyqpX3iNyZR3z5O07CEbCVE0MDDIjxt7EyhpkfpSPKTWbnbJaOW73pdJZq6Q5xzxRvKOdywVq1-5Ifem8NyvMPqFnjc1kGVJbmD13hktC6d-R3EfoqzBz-QutGKQdhZoTj1Bo6g6imIXzAcCNbRFNU7fU5Vn8-AkdqtpY0Nhd-CCnQNIvX2ngvA08WxKV4nt9VGouuSCrbvZ8LrtiyPx3Ays3F8fUdefH91WD28YRytzfA1SrAogMfZz7zX-pKulB0erHfoveRqbY4wjDiY8lYRARVmd0d_RVNE7q6ArilvgSOo-oiJI-VQYeFse16xuUcYnvhQjNR6fSW1vARiEvztMOhF1lwPhikcXggqY7-XEklsgot3Qi402kXPu8r9WEfjdlrcY3I8eaGfRew2i4PrwKEZulgwuU7LC1VQufdQDGKxS8X_vQntHMwe1b-3s0RZ8qpMcWB6mNXSB8T6ghT2N0taCkKTc6Oe_O322Y9lLWqLXAYC96cU9eoaIyC0jXNPp9tbE + +AccessKey ID: A13ECA33C26F4B20AB283ADB11159792 AccessKey Secret:D3843572206F4701BB779949C89F7576 +以下是个人注册的 +AccessKey ID: 69DDB0B8B4D443A589F8E0AEF70CE29C AccessKey Secret:C7699DC1E8904B3189959942EFB8918B diff --git a/plugins/__pycache__/auth.cpython-310.pyc b/plugins/__pycache__/auth.cpython-310.pyc new file mode 100644 index 0000000..f76b50d Binary files /dev/null and b/plugins/__pycache__/auth.cpython-310.pyc differ diff --git a/plugins/__pycache__/plugin.cpython-310.pyc b/plugins/__pycache__/plugin.cpython-310.pyc new file mode 100644 index 0000000..c2a9b34 Binary files /dev/null and b/plugins/__pycache__/plugin.cpython-310.pyc differ diff --git a/plugins/__pycache__/wechat_agent.cpython-310.pyc b/plugins/__pycache__/wechat_agent.cpython-310.pyc new file mode 100644 index 0000000..5e1b7f8 Binary files /dev/null and b/plugins/__pycache__/wechat_agent.cpython-310.pyc differ diff --git a/plugins/auth.py b/plugins/auth.py new file mode 100644 index 0000000..8fbdebe --- /dev/null +++ b/plugins/auth.py @@ -0,0 +1,9 @@ +from appPublic.log import info +from ahserver.auth_api import AuthAPI +from sqlor.dbpools import DBPools + +async def checkUserPermission(self, user, path): + info(f'checkUserPermission():{user} access to {path} ..') + return True + +AuthAPI.checkUserPermission = checkUserPermission diff --git a/plugins/plugin.py b/plugins/plugin.py new file mode 100644 index 0000000..ff7b9c1 --- /dev/null +++ b/plugins/plugin.py @@ -0,0 +1,56 @@ +import sys +from ahserver.serverenv import ServerEnv +from appPublic.dictObject import DictObject +import time +import jwt + +def generate_zhipuai_token(apikey: str, exp_seconds: int=86400): + try: + id, secret = apikey.split(".") + except Exception as e: + raise Exception("invalid apikey", e) + + payload = { + "api_key": id, + "exp": int(round(time.time() * 1000)) + exp_seconds * 1000, + "timestamp": int(round(time.time() * 1000)), + } + + return jwt.encode( + payload, + secret, + algorithm="HS256", + headers={"alg": "HS256", "sign_type": "SIGN"}, + ) + +async def get_llm_user_apikey(apiname, user): + if apiname == 'qianwen': + return DictObject(apikey='sk-ca5dfeb58d494f32a9cf1e9f064370c8') + + if apiname=='baiduqianfan': + return DictObject(apikey='SjAN4GHU07LuB8ZYOIstB31G', + secretkey='QbakADoGJsM2qjUzIogTkBZruToxYAve') + if apiname=='baichuanai': + return DictObject(apikey='sk-f1fca6335df32d13c096e5f2e72821db') + if apiname=='deepseek': + return DictObject(apikey='sk-a6a2d5eca1b7419b95f2c263c362be1e') + + if apiname == 'minimax': + return DictObject(apikey='eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJHcm91cE5hbWUiOiJtb3FpbmcgeXUiLCJVc2VyTmFtZSI6Im1vcWluZyB5dSIsIkFjY291bnQiOiIiLCJTdWJqZWN0SUQiOiIxNzY4NTM3NjQ1ODMyNDg3NjAyIiwiUGhvbmUiOiIxMzgwMTAxNTI5MiIsIkdyb3VwSUQiOiIxNzY4NTM3NjQ1ODI4MjkyOTMwIiwiUGFnZU5hbWUiOiIiLCJNYWlsIjoiIiwiQ3JlYXRlVGltZSI6IjIwMjQtMDQtMTAgMTg6MDA6NTMiLCJpc3MiOiJtaW5pbWF4In0.VaRRHr9XMUSYhZOKVS2PRZv6Y9VCaW4JX2ks4QZX3aFr_emjnDbGv5HfNskf54piflEAeTMW4Qw1nG7bqhYea7N5LKHGf0YpesPGSoqxwyZUR4oaJNNVUsSe6eiLbdYSDO2wMb_hV5xyawh-lYe1reBKWaPVuOjfTrDhxzA0IBmzl-jAQhL8-kIZet2uX-p3NjxElpo_zjmVV_hA1BJEvTwuAk8ka-1SBZmXciMhBi1fJG4jcqoHCCN_JHJ7pgjKr5bk2Zw5qCqiU2Ecsc-kPIEK1SI5EYoLszT43UpJ8_wV4Pm07UBCn3vktAa0fjKDSUArPkBoYWSkgKDMWlmxig', groupid='1768537645828292930') + if apiname == 'zhipuai': + return DictObject(token=generate_zhipuai_token('ffd0affcb6b5f9368f517c09c75a6817.jp9DdpcgwdxXvDiT')) + if apiname == 'moonshot': + return DictObject(apikey='sk-fHOyIKC2mlIDfGwUQV6SwjwVJkjBJgkNWYv82yt3OdpYh592') + if apiname == 'openai': + return DictObject(apikey='sk-proj-gFbYlxVnhmfqf8MXhX42T3BlbkFJprO7jXabkwtjmrNeH77Z') + if apiname == 'doubao': + return DictObject(apikey='a2fddeaa-c31c-4cbe-aacb-732318408dac') + + if apiname == 'tianqi': + return DictObject(apikey='94b72c37e62e49f796502d29955447ab', secretkey='afcac498e0a74302bec06d22dcdff213') + + print(f'{user=} not have apikey for {apiname=}') + return DictObject() + +g = ServerEnv() +g.get_llm_user_apikey = get_llm_user_apikey diff --git a/plugins/wechat_agent.py b/plugins/wechat_agent.py new file mode 100644 index 0000000..7c0be83 --- /dev/null +++ b/plugins/wechat_agent.py @@ -0,0 +1,11 @@ +import itchat +from appPublic.worker import awaitify +from appPublic.dictObject import DictObject +from appPublic.background import Background +from ahserver.globalEnv import GlobalEnv + +def wechat_login(login_callback, qr_callback): + Background(itchat.login, login_callback=login_callback, + qr_callback=qr_callback) +g = GlobalEnv() +g.wechat_login = wechat_login diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..4076923 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +openai-whisper +