diff --git a/backend/.env.example b/backend/.env.example index 37ba235..83e69c1 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -2,6 +2,7 @@ # LLAMA_CLOUD_API_KEY= SQL_DATABASE_URL=mysql+pymysql://zjinfo1:Dy2Bcr53Hm5xRkba@110.42.234.166:3306/zjinfo1 #SQL_DATABASE_URL=mysql+pymysql://zjinfo2:GSKcziSdBixDXwcd@110.42.234.166:3306/zjinfo2 +SQLITE_DATABASE_URL=sqlite:///./source.db DASHSCOPE_API_KEY=sk-02c8540e86d84b7ca0e6f4f51bac6e60 # The provider for the AI models to use. diff --git a/backend/.env.xinference b/backend/.env.xinference index 6dd566f..1dc074c 100644 --- a/backend/.env.xinference +++ b/backend/.env.xinference @@ -2,6 +2,7 @@ # LLAMA_CLOUD_API_KEY= SQL_DATABASE_URL=mysql+pymysql://zjinfo1:Dy2Bcr53Hm5xRkba@110.42.234.166:3306/zjinfo1 #SQL_DATABASE_URL=mysql+pymysql://zjinfo2:GSKcziSdBixDXwcd@110.42.234.166:3306/zjinfo2 +SQLITE_DATABASE_URL=sqlite:///./source.db # The number of similar embeddings to return when retrieving documents. TOP_K=10 diff --git a/backend/app/api/routers/app.py b/backend/app/api/routers/app.py new file mode 100644 index 0000000..e806726 --- /dev/null +++ b/backend/app/api/routers/app.py @@ -0,0 +1,69 @@ +import os +from typing import Dict, List, Any, Optional, cast +from fastapi import APIRouter,Request +from app.api.routers.request.base import userMng,conversations +from app.api.routers.request.models import ChatRequestData + +api_router = r = APIRouter() +v1_router = v = APIRouter() + + +@v.post("/chat-messages") +async def post_conversations(request: Request,data: ChatRequestData): + userMng.findNoExistCreate(data.user) + + conversaObj = conversations() + conversationinfo = conversaObj.get(data.user) + if conversationinfo is None: + conversationinfo = conversaObj.add(data.user, "新建会话") + + return None + +@v.get("/messages") +async def query_messages(user:str, conversation_id:str): + pass + +@v.post("/conversations/{itemid}/name") +async def post_conversations(user:str): + pass + +@v.get("/conversations") +async def query_conversations(user:str): + user_id = '' if user is None else user + userMng.findNoExistCreate(user_id) + + return { + "limit": 20, + "has_more": False, + "data": conversations().gets(user_id) + } + + +@r.get("/conversations") +async def query_conversations(first_id:int = None, limit:int = None, pinned:bool = None): + pass + +#meta查询 +@r.get("/meta") +async def query_meta(): + pass + +#name查询 +@r.get("/name查询") +def query_name(): + with sessionlocal() as session: + name = session.query(NameOrm).first() + + return Name.from_orm(name) + +#parameters查询 +@r.get("/parameters") +async def query_parameters(): + pass + +#msite查询 +@r.get("/site") +async def query_site(): + pass + + diff --git a/backend/app/api/routers/request/base.py b/backend/app/api/routers/request/base.py new file mode 100644 index 0000000..b50333a --- /dev/null +++ b/backend/app/api/routers/request/base.py @@ -0,0 +1,127 @@ +import os +from typing import Dict, List, Any, Optional, cast +import json +from app.api.routers.request.dbOrm import DBManager +from app.api.routers.request.baseConfig import BaseConfig +from datetime import datetime + +dbManage = DBManager() + +class conversations: + def __init__(self) -> None: + self._tableName = 'conversations' + dbManage.createTable(self._tableName) + + def gets(self,user_id:str): + records = dbManage.query(self._tableName,user_id = user_id) + datas = [] + for record in records: + datas.append(record) + + return datas + + def get(self,user_id:str,id:str = ''): + records = dbManage.query(self._tableName,user_id = user_id,id = id) + if len(records) >0: + return records[0] + return None + + def add(self,user_id:str,name:str,id:str = ''): + template = BaseConfig.ConversationCfg + template['id'] = id + template['user_id'] = user_id + template['name'] = name + template['created_at'] = 1724399038 + + dbManage.addRecord(self._tableName,template) + + def delete(self,id:str): + dbManage.delete(self._tableName,id=id) + + def rename(self,id:str): + data = {'name':''} + dbManage.update(self._tableName,data,id=id) + +class user: + def __init__(self) -> None: + self._tableName = 'user' + dbManage.createTable(self._tableName) + + def gets(self): + return dbManage.query(self._tableName) + + def get(self,id:str): + return dbManage.query(self._tableName,id = id) + + def add(self,id:str): + info = { + 'id':id, + 'createtime': datetime.now().strftime("%Y-%m-%d %H:%M:%S") + } + dbManage.addRecord(self._tableName,info) + + def delete(self,id:str): + dbManage.delete(self._tableName,id = id) + +class userMng: + userObj = user() + @classmethod + def findNoExistCreate(cls,user_id:str): + userInfo = cls.userObj.get(user_id) + if userInfo is None: + cls.userObj.add(user_id) + + def remove(cls,user_id:str): + cls.userObj.delete(user_id) + +class parameter: + def __init__(self) -> None: + self._tableName = 'parameters' + dbManage.createTable(self._tableName) + + def get(self,user_id:str): + records = dbManage.query(self._tableName,user_id = user_id) + data = {} + for record in records: + key = record['name'] + value = record['value'] + data[key] = value + + return { + 'opening_statement':data['opening_statement'], + 'suggested_questions':data['suggested_questions'], + 'suggested_questions_after_answer':data['suggested_questions_after_answer'], + 'speech_to_text':data['speech_to_text'], + 'text_to_speech':data['text_to_speech'], + 'retriever_resource':data['retriever_resource'], + 'annotation_reply':data['annotation_reply'], + 'more_like_this':data['more_like_this'], + 'user_input_form':data['user_input_form'], + 'sensitive_word_avoidance':data['sensitive_word_avoidance'], + 'file_upload':data['file_upload'], + 'system_parameters':data['system_parameters'], + 'opening_statement':data['opening_statement'], + } + + def set(self,user_id:str): + dbManage.addRecord(self._tableName,{}) + + def delete(self,user_id:str): + dbManage.delete(self._tableName,user_id = user_id) + +class message: + def __init__(self) -> None: + self._tableName = 'messages' + dbManage.createTable(self._tableName) + + def gets(self,user_id:str): + return dbManage.query(self._tableName,user_id = user_id) + + def add(self,user_id:str): + dbManage.addRecord(self._tableName,{}) + + def delete(self,user_id:str): + dbManage.delete(self._tableName,user_id = user_id) + + + diff --git a/backend/app/api/routers/request/baseConfig.py b/backend/app/api/routers/request/baseConfig.py new file mode 100644 index 0000000..b81f03e --- /dev/null +++ b/backend/app/api/routers/request/baseConfig.py @@ -0,0 +1,52 @@ + +class BaseConfig: + ParamterCfg = { + "opening_statement": "您好,我是配网D3造价软件小助手,您可以问我有关配网造价软件的相关问题!", + "suggested_questions": [], + "suggested_questions_after_answer": { + "enabled": False + }, + "speech_to_text": { + "enabled": False + }, + "text_to_speech": { + "enabled": False, + "language": "", + "voice": "" + }, + "retriever_resource": { + "enabled": True + }, + "annotation_reply": { + "enabled": False + }, + "more_like_this": { + "enabled": False + }, + "user_input_form": [], + "sensitive_word_avoidance": { + "enabled": False + }, + "file_upload": { + "image": { + "enabled": False, + "number_limits": 3, + "transfer_methods": [ + "remote_url" + ] + } + }, + "system_parameters": { + "image_file_size_limit": "10" + } + } + + ConversationCfg = { + "id": "", + 'user_id':'', + "name": "", + "inputs": {}, + "status": "normal", + "introduction": ParamterCfg['opening_statement'], + "created_at":'' + } \ No newline at end of file diff --git a/backend/app/api/routers/request/dbOrm.py b/backend/app/api/routers/request/dbOrm.py new file mode 100644 index 0000000..539a669 --- /dev/null +++ b/backend/app/api/routers/request/dbOrm.py @@ -0,0 +1,194 @@ +import os +from typing import Dict, List, Any, Optional, cast + +from fastapi import APIRouter +from pydantic import BaseModel, Field +from sqlalchemy import create_engine, Column, String, Integer, Boolean, JSON,ForeignKey +from sqlalchemy.orm import sessionmaker, declarative_base,relationship +from sqlalchemy.engine.reflection import Inspector + +Base = declarative_base() + +#orm类 +class ConversationOrm(Base): + __tablename__ = "conversations" + + id = Column(String, primary_key=True) + user_id = Column(String) + name = Column(String) + inputs = Column(JSON) + status = Column(String) + introduction = Column(String) + created_at = Column(Integer) + +class UserOrm(Base): + __tablename__ = "user" + + id = Column(String, primary_key=True) + createtime = Column(String) + +class ParametersOrm(Base): + __tablename__ = "parameters" + + user_id = Column(String,primary_key=True) + name = Column(String) + value = Column(JSON) + +class MessagesOrm(Base): + __tablename__ = "messages" + + id = Column(String,primary_key=True) + user_id = Column(String) + conversation_id = Column(String) + inputs = Column(JSON) + query = Column(String) + answer = Column(JSON) + +#数据结构 +class ConversationModel(BaseModel): + id: str + name: str + inputs: Dict[str, Any] + status: str + introduction: str + created_at: int + + class Config: + #orm_mode = True + from_attributes=True + + @classmethod + def orm(cls): + return ConversationOrm + +class UserModel(BaseModel): + id: str + createtime: str + + class Config: + #orm_mode = True + from_attributes=True + + @classmethod + def orm(cls): + return UserOrm + +class ParametersModel(BaseModel): + user_id : str + name : str + value : Dict[str, Any] + + class Config: + #orm_mode = True + from_attributes=True + + @classmethod + def orm(cls): + return ParametersOrm + +class MessagesModel(BaseModel): + id :str + conversation_id :str + inputs : Dict[str, Any] + query : str + answer : Dict[str, Any] + + class Config: + #orm_mode = True + from_attributes=True + + @classmethod + def orm(cls): + return MessagesOrm + +class DBManager: + def __init__(self) -> None: + DATABASE_URL = os.getenv("SQLITE_DATABASE_URL") + self._engine = create_engine(DATABASE_URL) + self.SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=self._engine) + + def createTable(self,tableName:str): + if self._engine is None: + return + if not self.exist(tableName): + Base.metadata.tables[tableName].create(self._engine) + + def addRecord(self,tableName:str,record:Dict[str,Any]): + ormCls = self._get_orm(tableName) + if ormCls is None: + return + session = self.SessionLocal() + data = ormCls(**record) + session.add(data) + session.commit() + + def addRecords(self,tableName:str,records:List[Dict[str,Any]]): + ormCls = self._get_orm(tableName) + if ormCls is None: + return + datas = [] + session = self.SessionLocal() + for record in records: + datas.append(ormCls(**record)) + session.add(datas) + session.commit() + + def delete(self,tableName:str,**filter): + session = self.SessionLocal() + ormCls = self._get_orm(tableName) + if ormCls is None: + return + records = session.query(ormCls).filter_by(**filter).all() + if records is not None: + session.delete(records) + session.commit() + + def update(self,tableName:str,data:Dict[str,Any],**filter): + session = self.SessionLocal() + ormCls = self._get_orm(tableName) + if ormCls is None: + return + record = session.query(ormCls).filter_by(**filter).first() + if record is not None: + record.update(data) + session.commit() + + def query(self,tableName:str,**filter): + session = self.SessionLocal() + ormCls = self._get_orm(tableName) + if ormCls is None: + return + modelCls = self._get_model(ormCls) + if modelCls is None: + return + + if filter is not None: + records = session.query(ormCls).filter_by(**filter).all() + else: + records = session.query(ormCls).all() + + datas = [] + for record in records: + datas.append(modelCls.from_orm(record)) + return datas + + def exist(self,tableName:str)->bool: + if self._engine is None: + return + inspector = Inspector.from_engine(self._engine) + return inspector.has_table(tableName) + + def _get_orm(self,tableName:str): + subClss = Base.__subclasses__() + for sunCls in subClss: + if sunCls.__tablename__ == tableName: + return sunCls + return None + + def _get_model(self,orm:Any): + subClss = BaseModel.__subclasses__() + for sunCls in subClss: + if 'orm' in sunCls.__dict__ and sunCls.orm() == orm: + return sunCls + return None + diff --git a/backend/app/api/routers/request/models.py b/backend/app/api/routers/request/models.py new file mode 100644 index 0000000..493883c --- /dev/null +++ b/backend/app/api/routers/request/models.py @@ -0,0 +1,10 @@ +from pydantic import BaseModel +from typing import Dict, List, Any, Optional, cast + +class ChatRequestData(BaseModel): + inputs: Dict[str,Any] + query: str + user: str + response_mode: str + files: Any + \ No newline at end of file diff --git a/backend/main.py b/backend/main.py index 0f5e9ad..f4bca3e 100644 --- a/backend/main.py +++ b/backend/main.py @@ -12,6 +12,7 @@ from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import RedirectResponse from app.api.routers.chat import chat_router from app.api.routers.upload import file_upload_router +from app.api.routers.app import api_router,v1_router from app.settings import init_settings from app.observability import init_observability from fastapi.staticfiles import StaticFiles @@ -55,6 +56,8 @@ mount_static_files("data", "/api/files/data") mount_static_files("data_output", "/api/files/output") app.include_router(chat_router, prefix="/api/chat") app.include_router(file_upload_router, prefix="/api/chat/upload") +app.include_router(api_router, prefix="/api") +app.include_router(v1_router, prefix="/v1") @app.get("/") async def redirect_to_docs():