diff --git a/alembic/versions/57167fd38273_changes.py b/alembic/versions/57167fd38273_changes.py new file mode 100644 index 00000000..2c873c50 --- /dev/null +++ b/alembic/versions/57167fd38273_changes.py @@ -0,0 +1,53 @@ +"""Changes + +Revision ID: 57167fd38273 +Revises: +Create Date: 2024-04-07 12:33:40.975147 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '57167fd38273' +down_revision: Union[str, None] = None +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('chat_history', + sa.Column('conversation_id', sa.UUID(), nullable=False), + sa.Column('title', sa.String(length=255), nullable=True), + sa.Column('created_at', sa.DateTime(), nullable=True), + sa.Column('updated_at', sa.DateTime(), nullable=True), + sa.Column('user_id', sa.Integer(), nullable=True), + sa.Column('_title_generated', sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), + sa.PrimaryKeyConstraint('conversation_id') + ) + op.create_table('chat_items', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('sender', sa.String(length=225), nullable=False), + sa.Column('content', sa.JSON(), nullable=True), + sa.Column('created_at', sa.DateTime(), nullable=True), + sa.Column('updated_at', sa.DateTime(), nullable=True), + sa.Column('like', sa.Boolean(), nullable=True), + sa.Column('conversation_id', sa.UUID(), nullable=False), + sa.ForeignKeyConstraint(['conversation_id'], ['chat_history.conversation_id'], ), + sa.PrimaryKeyConstraint('id') + ) + # op.create_unique_constraint('unique_user_role', 'user_roles', ['user_id', 'role_id', 'company_id']) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + # op.drop_constraint('unique_user_role', 'user_roles', type_='unique') + op.drop_table('chat_items') + op.drop_table('chat_history') + # ### end Alembic commands ### diff --git a/alembic/versions/5f1c1d3934a1_changes_content_to_json.py b/alembic/versions/5f1c1d3934a1_changes_content_to_json.py new file mode 100644 index 00000000..e626aa07 --- /dev/null +++ b/alembic/versions/5f1c1d3934a1_changes_content_to_json.py @@ -0,0 +1,39 @@ +"""Changes content to json + +Revision ID: 5f1c1d3934a1 +Revises: eb18396f592a +Create Date: 2024-04-07 12:29:18.009919 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '5f1c1d3934a1' +down_revision: Union[str, None] = 'eb18396f592a' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('chat_items', 'content', + existing_type=sa.TEXT(), + type_=sa.JSON(), + existing_nullable=True, + ) + # op.create_unique_constraint('unique_user_role', 'user_roles', ['user_id', 'role_id', 'company_id']) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + # op.drop_constraint('unique_user_role', 'user_roles', type_='unique') + op.alter_column('chat_items', 'content', + existing_type=sa.JSON(), + type_=sa.TEXT(), + existing_nullable=True) + # ### end Alembic commands ### diff --git a/alembic_readme.md b/alembic_readme.md index 219862b1..abf42332 100644 --- a/alembic_readme.md +++ b/alembic_readme.md @@ -4,4 +4,8 @@ `alembic revision --autogenerate -m "Create user model"` # first migration -`alembic upgrade 66b63a` # reflect migration on database (here 66b63a) is ssh value \ No newline at end of file +`alembic upgrade 66b63a` # reflect migration on database (here 66b63a) is ssh value + + +## Local installation +`poetry install --extras "ui llms-llama-cpp embeddings-huggingface vector-stores-qdrant rerank-sentence-transformers"` \ No newline at end of file diff --git a/private_gpt/launcher.py b/private_gpt/launcher.py index 9aa5ecf5..4be45a91 100644 --- a/private_gpt/launcher.py +++ b/private_gpt/launcher.py @@ -54,6 +54,7 @@ def create_app(root_injector: Injector) -> FastAPI: "http://192.168.1.98", "http://192.168.1.98:5173", "http://localhost:3000","https://globaldocquery.gibl.com.np/", "http://127.0.0.1/", "http://localhost/", "http://localhost:80", "http://192.168.1.131", 'http://192.168.1.131:3000' , "http://192.168.1.127", 'http://192.168.1.127:3000' + , "http://192.168.1.70", 'http://192.168.1.70:3000' ], allow_methods=["DELETE", "GET", "POST", "PUT", "OPTIONS", "PATCH"], allow_headers=["*"], diff --git a/private_gpt/server/completions/completions_router.py b/private_gpt/server/completions/completions_router.py index 3915d976..aa708ffe 100644 --- a/private_gpt/server/completions/completions_router.py +++ b/private_gpt/server/completions/completions_router.py @@ -1,10 +1,11 @@ from fastapi import APIRouter, Depends, Request, Security, HTTPException, status from private_gpt.server.ingest.ingest_service import IngestService from pydantic import BaseModel +from typing import List, Dict, Any from sqlalchemy.orm import Session import traceback import logging - +import json logger = logging.getLogger(__name__) from starlette.responses import StreamingResponse @@ -47,6 +48,9 @@ class CompletionsBody(BaseModel): } +class ChatContentCreate(BaseModel): + content: Dict[str, Any] + # @completions_router.post( # "/completions", # response_model=None, @@ -155,8 +159,15 @@ async def prompt_completion( raise HTTPException( status_code=404, detail="Chat history not found") - messages = [OpenAIMessage(content=body.prompt, role="user")] - create_chat_item(db, "user", body.prompt, body.conversation_id) + user_message = OpenAIMessage(content=body.prompt, role="user") + user_message = user_message.model_dump(mode="json") + + user_message_json = { + 'text': body.prompt, + } + create_chat_item(db, "user", json.dumps(user_message_json) , body.conversation_id) + + messages = [user_message] if body.system_prompt: messages.insert(0, OpenAIMessage( @@ -178,9 +189,21 @@ async def prompt_completion( }, user_id=current_user.id ) + chat_response = await chat_completion(request, chat_body) - print(chat_response) - create_chat_item(db, "assistant", chat_response.choices[0].message.content, body.conversation_id) + ai_response = chat_response.model_dump(mode="json") + + text_list = [choice['message']['content'] for choice in ai_response['choices']] + sources_list = [source['document']['doc_metadata'] for choice in ai_response['choices'] for source in choice['sources']] + + ai_response_json = { + 'text': text_list[0], + 'sources': sources_list + } + ai_response_json_str = json.dumps(ai_response_json) + print("The ai response: ",ai_response_json_str) + + create_chat_item(db, "assistant", ai_response, body.conversation_id) return chat_response diff --git a/private_gpt/users/models/chat.py b/private_gpt/users/models/chat.py index 1101a9d7..d67d52c6 100644 --- a/private_gpt/users/models/chat.py +++ b/private_gpt/users/models/chat.py @@ -2,7 +2,7 @@ import uuid from datetime import datetime from sqlalchemy.orm import relationship from sqlalchemy.dialects.postgresql import UUID -from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Text, Boolean, event +from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Text, Boolean, event, JSON from private_gpt.users.db.base_class import Base @@ -49,7 +49,7 @@ class ChatItem(Base): id = Column(Integer, nullable=False, primary_key=True) sender = Column(String(225), nullable=False) - content = Column(Text, nullable=True) + content = Column(JSON, nullable=True) created_at = Column(DateTime, default=datetime.now) updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now) diff --git a/private_gpt/users/schemas/chat.py b/private_gpt/users/schemas/chat.py index eaf8abf8..148509a3 100644 --- a/private_gpt/users/schemas/chat.py +++ b/private_gpt/users/schemas/chat.py @@ -1,12 +1,12 @@ from datetime import datetime -from typing import List, Optional -from pydantic import BaseModel +from typing import List, Optional, Union, Dict +from pydantic import BaseModel, Json import uuid class ChatItemBase(BaseModel): conversation_id: uuid.UUID sender: str - content: Optional[str] + content: Union[str, Dict] class ChatItemCreate(ChatItemBase):