learnhouse/apps/api/src/services/ai/ai.py
2024-08-11 15:44:12 +02:00

207 lines
6.9 KiB
Python

from fastapi import Depends, HTTPException, Request
from sqlmodel import Session, select
from src.db.organization_config import OrganizationConfig
from src.db.organizations import Organization
from src.services.ai.utils import check_limits_and_config, count_ai_ask
from src.db.courses.courses import Course, CourseRead
from src.core.events.database import get_db_session
from src.db.users import PublicUser
from src.db.courses.activities import Activity, ActivityRead
from src.security.auth import get_current_user
from src.services.ai.base import ask_ai, get_chat_session_history
from src.services.ai.schemas.ai import (
ActivityAIChatSessionResponse,
SendActivityAIChatMessage,
StartActivityAIChatSession,
)
from src.services.courses.activities.utils import (
serialize_activity_text_to_ai_comprehensible_text,
structure_activity_content_by_type,
)
def ai_start_activity_chat_session(
request: Request,
chat_session_object: StartActivityAIChatSession,
current_user: PublicUser = Depends(get_current_user),
db_session: Session = Depends(get_db_session),
) -> ActivityAIChatSessionResponse:
"""
Start a new AI Chat session with a Course Activity
"""
# Get the Activity
statement = select(Activity).where(
Activity.activity_uuid == chat_session_object.activity_uuid
)
activity = db_session.exec(statement).first()
activity = ActivityRead.model_validate(activity)
# Get the Course
statement = (
select(Course)
.join(Activity)
.where(Activity.activity_uuid == chat_session_object.activity_uuid)
)
course = db_session.exec(statement).first()
course = CourseRead.model_validate(course)
# Get the Organization
statement = select(Organization).where(Organization.id == course.org_id)
org = db_session.exec(statement).first()
# Check limits and usage
check_limits_and_config(db_session, org) # type: ignore
count_ai_ask(org, "increment") # type: ignore
if not activity:
raise HTTPException(
status_code=404,
detail="Activity not found",
)
# Get Activity Content Blocks
content = activity.content
# Serialize Activity Content Blocks to a text comprehensible by the AI
structured = structure_activity_content_by_type(content)
isEmpty = structured == []
ai_friendly_text = serialize_activity_text_to_ai_comprehensible_text(
structured, course, activity, isActivityEmpty=isEmpty
)
# Get Activity Organization
statement = select(Organization).where(Organization.id == course.org_id)
org = db_session.exec(statement).first()
# Get Organization Config
statement = select(OrganizationConfig).where(
OrganizationConfig.org_id == org.id # type: ignore
)
result = db_session.exec(statement)
org_config = result.first()
org_config = OrganizationConfig.model_validate(org_config)
embeddings = "text-embedding-ada-002"
ai_model = org_config.config["features"]["ai"]["model"]
chat_session = get_chat_session_history()
message = "You are a helpful Education Assistant, and you are helping a student with the associated Course. "
message += "Use the available tools to get context about this question even if the question is not specific enough."
message += "For context, this is the Course name :"
message += course.name
message += " and this is the Lecture name :"
message += activity.name
message += "."
message += "Use your knowledge to help the student if the context is not enough."
response = ask_ai(
chat_session_object.message,
chat_session["message_history"],
ai_friendly_text,
message,
embeddings,
ai_model,
)
return ActivityAIChatSessionResponse(
aichat_uuid=chat_session["aichat_uuid"],
activity_uuid=activity.activity_uuid,
message=response["output"],
)
def ai_send_activity_chat_message(
request: Request,
chat_session_object: SendActivityAIChatMessage,
current_user: PublicUser = Depends(get_current_user),
db_session: Session = Depends(get_db_session),
) -> ActivityAIChatSessionResponse:
"""
Start a new AI Chat session with a Course Activity
"""
# Get the Activity
statement = select(Activity).where(
Activity.activity_uuid == chat_session_object.activity_uuid
)
activity = db_session.exec(statement).first()
activity = ActivityRead.model_validate(activity)
# Get the Course
statement = (
select(Course)
.join(Activity)
.where(Activity.activity_uuid == chat_session_object.activity_uuid)
)
course = db_session.exec(statement).first()
course = CourseRead.model_validate(course)
# Get the Organization
statement = select(Organization).where(Organization.id == course.org_id)
org = db_session.exec(statement).first()
# Check limits and usage
check_limits_and_config(db_session, org) # type: ignore
count_ai_ask(org, "increment") # type: ignore
if not activity:
raise HTTPException(
status_code=404,
detail="Activity not found",
)
# Get Activity Content Blocks
content = activity.content
# Serialize Activity Content Blocks to a text comprehensible by the AI
structured = structure_activity_content_by_type(content)
ai_friendly_text = serialize_activity_text_to_ai_comprehensible_text(
structured, course, activity
)
# Get Activity Organization
statement = select(Organization).where(Organization.id == course.org_id)
org = db_session.exec(statement).first()
# Get Organization Config
statement = select(OrganizationConfig).where(
OrganizationConfig.org_id == org.id # type: ignore
)
result = db_session.exec(statement)
org_config = result.first()
org_config = OrganizationConfig.model_validate(org_config)
embeddings = "text-embedding-ada-002"
ai_model = org_config.config["features"]["ai"]["model"]
chat_session = get_chat_session_history(chat_session_object.aichat_uuid)
message = "You are a helpful Education Assistant, and you are helping a student with the associated Course. "
message += "Use the available tools to get context about this question even if the question is not specific enough."
message += "For context, this is the Course name :"
message += course.name
message += " and this is the Lecture name :"
message += activity.name
message += "."
message += "Use your knowledge to help the student if the context is not enough."
response = ask_ai(
chat_session_object.message,
chat_session["message_history"],
ai_friendly_text,
message,
embeddings,
ai_model,
)
return ActivityAIChatSessionResponse(
aichat_uuid=chat_session["aichat_uuid"],
activity_uuid=activity.activity_uuid,
message=response["output"],
)