aki-008 commited on
Commit
0d22fa6
·
1 Parent(s): 4c91d90

chore: AI Chat improved

Browse files
Backend/app/api/v1/endpoints/notes.py CHANGED
@@ -2,13 +2,12 @@ from fastapi import APIRouter, Depends, HTTPException, status, File, UploadFile
2
  from sqlalchemy.ext.asyncio import AsyncSession
3
  from app.models import User
4
  from app.models.tables import PDFData
5
- from app.api.deps import get_db, get_current_user
6
  from app.schema import AI_chat_input
7
  from app.llm import stream_chat
8
  import uuid
9
  from fastapi.responses import StreamingResponse
10
  from chromadb.api.models.Collection import Collection
11
- from app.api.deps import get_chroma_collection
12
  from pathlib import Path
13
  from llama_index.readers.file import PyMuPDFReader
14
  from llama_index.core.node_parser import SentenceSplitter
@@ -16,7 +15,7 @@ from typing import Annotated
16
  import shutil
17
  import os
18
  from sentence_transformers import SentenceTransformer
19
-
20
 
21
  router = APIRouter(prefix="/notes")
22
 
@@ -28,12 +27,15 @@ embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
28
  @router.post("/stream_chat", response_class=StreamingResponse)
29
  async def ai_chat(
30
  Input_model: AI_chat_input,
 
31
  current_user: User = Depends(get_current_user)
32
  ):
33
  messages_dict = [msg.model_dump() for msg in Input_model.messages]
 
 
34
 
35
  return StreamingResponse(
36
- stream_chat(messages_dict, Input_model.context),
37
  media_type="text/plain"
38
  )
39
 
 
2
  from sqlalchemy.ext.asyncio import AsyncSession
3
  from app.models import User
4
  from app.models.tables import PDFData
5
+ from app.api.deps import get_db, get_current_user, get_chroma_collection
6
  from app.schema import AI_chat_input
7
  from app.llm import stream_chat
8
  import uuid
9
  from fastapi.responses import StreamingResponse
10
  from chromadb.api.models.Collection import Collection
 
11
  from pathlib import Path
12
  from llama_index.readers.file import PyMuPDFReader
13
  from llama_index.core.node_parser import SentenceSplitter
 
15
  import shutil
16
  import os
17
  from sentence_transformers import SentenceTransformer
18
+ from .quiz import search_logic
19
 
20
  router = APIRouter(prefix="/notes")
21
 
 
27
  @router.post("/stream_chat", response_class=StreamingResponse)
28
  async def ai_chat(
29
  Input_model: AI_chat_input,
30
+ collection: Collection = Depends(get_chroma_collection),
31
  current_user: User = Depends(get_current_user)
32
  ):
33
  messages_dict = [msg.model_dump() for msg in Input_model.messages]
34
+ query = f"{Input_model.context};{Input_model.messages[-1].content}"
35
+ retrieved_docs: str | None = await search_logic(query, collection)
36
 
37
  return StreamingResponse(
38
+ stream_chat(messages_dict, Input_model.context, retrieved_docs),
39
  media_type="text/plain"
40
  )
41
 
Backend/app/api/v1/endpoints/quiz.py CHANGED
@@ -9,15 +9,52 @@ from chromadb.api.models.Collection import Collection
9
  from app.api.deps import get_chroma_collection
10
  from app.llm import call_llm
11
  import uuid
 
 
12
 
13
  router = APIRouter(prefix="/quiz")
14
 
 
 
 
 
15
  async def search_logic(query: str, collection: Collection):
16
- results = await collection.query(
17
- query_texts=[query],
18
- n_results=5
19
- )
20
- return ''.join(results['documents'][0])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  @router.get("/search_docs")
23
  async def search_documents(
 
9
  from app.api.deps import get_chroma_collection
10
  from app.llm import call_llm
11
  import uuid
12
+ import logging
13
+
14
 
15
  router = APIRouter(prefix="/quiz")
16
 
17
+
18
+ # 1. Set up a logger (if you haven't already globally)
19
+ logger = logging.getLogger("uvicorn.error") # reusing uvicorn's logger ensures it shows up in your terminal
20
+
21
  async def search_logic(query: str, collection: Collection):
22
+ # Log the incoming query
23
+ logger.info(f"🔍 [Search Logic] Starting search for query: '{query}'")
24
+
25
+ try:
26
+ results = await collection.query(
27
+ query_texts=[query],
28
+ n_results=5
29
+ )
30
+
31
+ # Log the raw results to see exactly what ChromaDB returned (helps spot NoneTypes)
32
+ logger.info(f"📄 [Search Logic] Raw results from DB: {results}")
33
+
34
+ if results and results.get('documents') and len(results['documents']) > 0:
35
+ raw_docs = results['documents'][0]
36
+
37
+ # Filter None values and Log how many were found vs valid
38
+ valid_docs = [str(doc) for doc in raw_docs if doc is not None]
39
+
40
+ logger.info(f"✅ [Search Logic] Processing: Found {len(raw_docs)} items. Valid text items: {len(valid_docs)}")
41
+
42
+ if len(raw_docs) != len(valid_docs):
43
+ logger.warning("⚠️ [Search Logic] Warning: Some documents contained NoneType and were skipped.")
44
+
45
+ # Join with a space (safer than empty string)
46
+ final_context = " ".join(valid_docs)
47
+ return final_context
48
+
49
+ else:
50
+ logger.warning("⚠️ [Search Logic] No documents found for this query.")
51
+ return ""
52
+
53
+ except Exception as e:
54
+ # Log the full error if something crashes
55
+ logger.error(f"❌ [Search Logic] CRITICAL ERROR: {str(e)}")
56
+ # You might want to re-raise the error or return empty depending on your needs
57
+ return ""
58
 
59
  @router.get("/search_docs")
60
  async def search_documents(
Backend/app/llm.py CHANGED
@@ -37,36 +37,61 @@ async def call_llm(prompt:str):
37
 
38
 
39
 
40
- async def stream_chat(messages:List[dict], context:str):
 
 
41
  system_instruction = {
42
  "role": "system",
43
- "content": "You are a helpful AI assistant. Answer the user's question strictly based on the provided context."
44
  }
45
 
46
  conversation_history = [msg.copy() for msg in messages]
47
 
48
  if conversation_history and conversation_history[-1]['role'] == 'user':
49
  last_user_msg = conversation_history[-1]
50
- # Rewrite the content to: Context + \n\n + Question
51
- last_user_msg['content'] = (
52
- f"Here is the context/notes you must use:\n"
53
- f"---------------------\n"
54
- f"{context}\n"
55
- f"---------------------\n\n"
56
- f"User Question: {last_user_msg['content']}"
57
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  else:
59
  # Fallback: If for some reason there is no user message, add one.
 
 
60
  conversation_history.append({
61
  "role": "user",
62
- "content": f"Context:\n{context}\n\nPlease analyze this."
63
  })
64
 
65
- # 3. Combine System + Modified User History
66
  full_history = [system_instruction] + conversation_history
67
 
68
  try:
69
-
70
  stream = await client.chat.completions.create(
71
  model="openai/gpt-oss-20b",
72
  messages=full_history,
 
37
 
38
 
39
 
40
+ from typing import List
41
+
42
+ async def stream_chat(messages: List[dict], context: str, retrieved_docs: str | None):
43
  system_instruction = {
44
  "role": "system",
45
+ "content": "You are a helpful AI assistant. Answer the user's question based on the provided context and retrieved documents."
46
  }
47
 
48
  conversation_history = [msg.copy() for msg in messages]
49
 
50
  if conversation_history and conversation_history[-1]['role'] == 'user':
51
  last_user_msg = conversation_history[-1]
52
+ original_question = last_user_msg['content']
53
+
54
+ # Start constructing the augmented prompt
55
+ augmented_content = ""
56
+
57
+ # 1. Add Manual Context
58
+ if context:
59
+ augmented_content += (
60
+ f"Here is the context/notes you must use:\n"
61
+ f"---------------------\n"
62
+ f"{context}\n"
63
+ f"---------------------\n\n"
64
+ )
65
+
66
+ # 2. Add Retrieved Documents (New Logic)
67
+ if retrieved_docs:
68
+ augmented_content += (
69
+ f"Here is background information/retrieved documents:\n"
70
+ f"---------------------\n"
71
+ f"{retrieved_docs}\n"
72
+ f"---------------------\n\n"
73
+ )
74
+
75
+ # 3. Add the User Question
76
+ augmented_content += f"User Question: {original_question}"
77
+
78
+ # Update the message content
79
+ last_user_msg['content'] = augmented_content
80
+
81
  else:
82
  # Fallback: If for some reason there is no user message, add one.
83
+ # We combine context and docs here too just in case.
84
+ combined_context = f"{context}\n\n{retrieved_docs or ''}"
85
  conversation_history.append({
86
  "role": "user",
87
+ "content": f"Context:\n{combined_context}\n\nPlease analyze this."
88
  })
89
 
90
+ # 4. Combine System + Modified User History
91
  full_history = [system_instruction] + conversation_history
92
 
93
  try:
94
+ # Ensure 'client' is initialized before this function in your code
95
  stream = await client.chat.completions.create(
96
  model="openai/gpt-oss-20b",
97
  messages=full_history,