Suhaib-neo commited on
Commit
883d885
·
1 Parent(s): 2e3a029

Add files from GitHub repo with SQLite files tracked by LFS

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +1 -0
  2. app.py +53 -0
  3. auth.py +26 -0
  4. chat.py +61 -0
  5. db.py +42 -0
  6. rag.py +175 -0
  7. requirements.txt +17 -3
  8. ui_pages.py +577 -0
  9. vectordb/case_2021/bd4665fb-a7e9-4393-b81c-df50acadc5cf/data_level0.bin +3 -0
  10. vectordb/case_2021/bd4665fb-a7e9-4393-b81c-df50acadc5cf/header.bin +3 -0
  11. vectordb/case_2021/bd4665fb-a7e9-4393-b81c-df50acadc5cf/length.bin +3 -0
  12. vectordb/case_2021/bd4665fb-a7e9-4393-b81c-df50acadc5cf/link_lists.bin +0 -0
  13. vectordb/case_2021/chroma.sqlite3 +3 -0
  14. vectordb/case_2021/docstore.json +1 -0
  15. vectordb/case_2021/graph_store.json +1 -0
  16. vectordb/case_2021/image__vector_store.json +1 -0
  17. vectordb/case_2021/index_store.json +1 -0
  18. vectordb/case_2021/nodes.pkl +3 -0
  19. vectordb/case_2022/be5602b6-82eb-4aaa-a2ab-d74d0808b2bc/data_level0.bin +3 -0
  20. vectordb/case_2022/be5602b6-82eb-4aaa-a2ab-d74d0808b2bc/header.bin +3 -0
  21. vectordb/case_2022/be5602b6-82eb-4aaa-a2ab-d74d0808b2bc/length.bin +3 -0
  22. vectordb/case_2022/be5602b6-82eb-4aaa-a2ab-d74d0808b2bc/link_lists.bin +0 -0
  23. vectordb/case_2022/chroma.sqlite3 +3 -0
  24. vectordb/case_2022/docstore.json +1 -0
  25. vectordb/case_2022/graph_store.json +1 -0
  26. vectordb/case_2022/image__vector_store.json +1 -0
  27. vectordb/case_2022/index_store.json +1 -0
  28. vectordb/case_2022/nodes.pkl +3 -0
  29. vectordb/case_2023/402be202-644a-4979-9c56-fb043affb335/data_level0.bin +3 -0
  30. vectordb/case_2023/402be202-644a-4979-9c56-fb043affb335/header.bin +3 -0
  31. vectordb/case_2023/402be202-644a-4979-9c56-fb043affb335/length.bin +3 -0
  32. vectordb/case_2023/402be202-644a-4979-9c56-fb043affb335/link_lists.bin +0 -0
  33. vectordb/case_2023/chroma.sqlite3 +3 -0
  34. vectordb/case_2023/docstore.json +1 -0
  35. vectordb/case_2023/graph_store.json +1 -0
  36. vectordb/case_2023/image__vector_store.json +1 -0
  37. vectordb/case_2023/index_store.json +1 -0
  38. vectordb/case_2023/nodes.pkl +3 -0
  39. vectordb/case_2024/17c59c4b-b633-4586-a7de-8dd2d7c5f509/data_level0.bin +3 -0
  40. vectordb/case_2024/17c59c4b-b633-4586-a7de-8dd2d7c5f509/header.bin +3 -0
  41. vectordb/case_2024/17c59c4b-b633-4586-a7de-8dd2d7c5f509/length.bin +3 -0
  42. vectordb/case_2024/17c59c4b-b633-4586-a7de-8dd2d7c5f509/link_lists.bin +0 -0
  43. vectordb/case_2024/chroma.sqlite3 +3 -0
  44. vectordb/case_2024/docstore.json +1 -0
  45. vectordb/case_2024/graph_store.json +1 -0
  46. vectordb/case_2024/image__vector_store.json +1 -0
  47. vectordb/case_2024/index_store.json +1 -0
  48. vectordb/case_2024/nodes.pkl +3 -0
  49. vectordb/case_2025/b5602bd0-a583-4091-8690-a44e83836a6d/data_level0.bin +3 -0
  50. vectordb/case_2025/b5602bd0-a583-4091-8690-a44e83836a6d/header.bin +3 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ vectordb/**/*.sqlite3 filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+ import streamlit as st
3
+ from db import init_connection
4
+ from ui_pages import login_page, create_account_page, main_page
5
+ from chat import load_user_sessions # import it here
6
+
7
+ from dotenv import load_dotenv
8
+ load_dotenv()
9
+
10
+ def app():
11
+ # Initialize session state
12
+ default_keys = {
13
+ 'logged_in': False,
14
+ 'username': "",
15
+ 'show_create_account': False,
16
+ 'messages': [],
17
+ 'current_chat_session': None,
18
+ 'chat_sessions': [],
19
+ 'last_session_id': None
20
+ }
21
+ for key, val in default_keys.items():
22
+ if key not in st.session_state:
23
+ st.session_state[key] = val
24
+
25
+ # Initialize database connection (returns dict of collections)
26
+ db_conn = init_connection()
27
+ if db_conn is None:
28
+ return
29
+
30
+ # Route to appropriate page
31
+ if st.session_state.logged_in:
32
+ # load_user_sessions returns (sessions, current_session, messages_stub)
33
+ sessions, current, messages = load_user_sessions(
34
+ st.session_state.username,
35
+ db_conn["sessions"],
36
+ st.session_state.get("last_session_id")
37
+ )
38
+ st.session_state.chat_sessions = sessions
39
+ st.session_state.current_chat_session = current
40
+ # load chat messages if we have a current session
41
+ if current:
42
+ from chat import load_chat_history
43
+ st.session_state.messages = load_chat_history(str(current["_id"]), db_conn["messages"])
44
+ else:
45
+ st.session_state.messages = []
46
+ main_page()
47
+ elif st.session_state.show_create_account:
48
+ create_account_page()
49
+ else:
50
+ login_page()
51
+
52
+ if __name__ == "__main__":
53
+ app()
auth.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import bcrypt
2
+ import logging
3
+
4
+ logger = logging.getLogger(__name__)
5
+
6
+ def check_login(username: str, password: str, users_collection) -> bool:
7
+ """Checks if the provided username and password are valid against MongoDB."""
8
+ logger.info(f"Login attempt for user: {username}")
9
+ user = users_collection.find_one({"username": username})
10
+ if user:
11
+ stored_hash = user["password"]
12
+
13
+ # Ensure we always have bytes for bcrypt.checkpw
14
+ stored_hash_bytes = stored_hash.encode('utf-8') if isinstance(stored_hash, str) else stored_hash
15
+
16
+ try:
17
+ if bcrypt.checkpw(password.encode('utf-8'), stored_hash_bytes):
18
+ logger.info(f"User '{username}' logged in successfully.")
19
+ return True
20
+ else:
21
+ logger.warning(f"Invalid password attempt for user: {username}")
22
+ except Exception as e:
23
+ logger.error(f"Error checking password for user {username}: {e}")
24
+ else:
25
+ logger.warning(f"Login failed, user not found: {username}")
26
+ return False
chat.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime
2
+ from bson.objectid import ObjectId
3
+
4
+ def load_user_sessions(username, sessions_collection, last_session_id=None):
5
+ """
6
+ Load sessions for a user. Restore last active session if possible.
7
+ Returns: (sessions_list, current_session_or_None, messages_list)
8
+ """
9
+ if sessions_collection is None:
10
+ return [], None, []
11
+
12
+ sessions = list(sessions_collection.find({"username": username}).sort("timestamp", -1))
13
+ current_session = None
14
+ messages = []
15
+
16
+ if sessions:
17
+ if last_session_id:
18
+ try:
19
+ last = sessions_collection.find_one({"_id": ObjectId(last_session_id)})
20
+ except Exception:
21
+ last = None
22
+ if last:
23
+ current_session = last
24
+ # messages will be loaded by caller or by calling load_chat_history
25
+ if not current_session:
26
+ current_session = sessions[0]
27
+
28
+ # Note: do NOT load messages here unless you also have messages_collection.
29
+ # Return sessions and current_session; caller can call load_chat_history with messages_collection.
30
+ return sessions, current_session, messages
31
+
32
+
33
+ def load_chat_history(session_id, messages_collection):
34
+ """
35
+ Loads messages for a given chat session from messages_collection.
36
+ """
37
+ if messages_collection is None:
38
+ return []
39
+ try:
40
+ msgs = list(messages_collection.find({"session_id": session_id}).sort("timestamp", 1))
41
+ return [{"role": m.get("role", "assistant"), "content": m.get("content", "")} for m in msgs]
42
+ except Exception:
43
+ return []
44
+
45
+
46
+ def save_message(session_id, role, content, messages_collection):
47
+ """
48
+ Save a message to the chat history in messages_collection.
49
+ """
50
+ if messages_collection is None:
51
+ return None
52
+ try:
53
+ doc = {
54
+ "session_id": session_id,
55
+ "role": role,
56
+ "content": content,
57
+ "timestamp": datetime.utcnow(),
58
+ }
59
+ return messages_collection.insert_one(doc).inserted_id
60
+ except Exception:
61
+ return None
db.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pymongo import MongoClient
2
+ import os
3
+
4
+ from dotenv import load_dotenv
5
+ load_dotenv()
6
+
7
+
8
+ client = None
9
+ db = None
10
+ users_collection = None
11
+ sessions_collection = None
12
+ messages_collection = None
13
+
14
+
15
+ def init_connection():
16
+ """Initialize MongoDB connection and collections."""
17
+ global client, db, users_collection, sessions_collection, messages_collection
18
+
19
+ mongo_uri = os.getenv("MONGO_URI")
20
+ if not mongo_uri:
21
+ raise ValueError("❌ MONGO_URI not found in environment variables.")
22
+
23
+ client = MongoClient(mongo_uri)
24
+ db = client.get_database("law_cases_db")
25
+
26
+ users_collection = db.get_collection("users")
27
+ sessions_collection = db.get_collection("chat_sessions")
28
+ messages_collection = db.get_collection("chat_messages")
29
+
30
+ # ✅ create unique index (username + normalized chat name)
31
+ sessions_collection.create_index(
32
+ [("username", 1), ("session_name_normalized", 1)],
33
+ unique=True
34
+ )
35
+
36
+ return {
37
+ "client": client,
38
+ "db": db,
39
+ "users": users_collection,
40
+ "sessions": sessions_collection,
41
+ "messages": messages_collection
42
+ }
rag.py ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import logging
3
+ import streamlit as st
4
+ from dotenv import load_dotenv
5
+ import pickle
6
+
7
+ from llama_index.llms.groq import Groq
8
+ from llama_index.embeddings.huggingface import HuggingFaceEmbedding
9
+ from llama_index.vector_stores.chroma import ChromaVectorStore
10
+ from llama_index.core import VectorStoreIndex
11
+ from llama_index.core.retrievers import VectorIndexRetriever, RecursiveRetriever
12
+ from llama_index.retrievers.bm25 import BM25Retriever
13
+ from llama_index.core.tools import QueryEngineTool
14
+ from llama_index.core.query_engine import RetrieverQueryEngine
15
+ from llama_index.core import get_response_synthesizer
16
+ from llama_index.core.agent import ReActAgent
17
+ from chromadb import PersistentClient
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+ @st.cache_resource
22
+ def setup_rag_system(debug=False):
23
+ load_dotenv()
24
+
25
+ groq_api_key = os.getenv("GROQ_API_KEY") or st.secrets.get("groq", {}).get("api_key")
26
+ if not groq_api_key:
27
+ st.error("GROQ API key not found. Please check your environment variables or secrets.")
28
+ st.stop()
29
+
30
+ # LLM
31
+ llm = Groq(
32
+ model="llama-3.1-8b-instant",
33
+ api_key=groq_api_key,
34
+ max_input_tokens=1200,
35
+ max_output_tokens=1200
36
+ )
37
+
38
+ # Embeddings
39
+ embedding_model = HuggingFaceEmbedding(model_name="sentence-transformers/all-MiniLM-L6-v2")
40
+
41
+ # Persisted vector DBs
42
+ persist_dirs = [
43
+ "vectordb/case_2021",
44
+ "vectordb/case_2022",
45
+ "vectordb/case_2023",
46
+ "vectordb/case_2024",
47
+ "vectordb/case_2025"
48
+ ]
49
+ for persist_dir in persist_dirs:
50
+ if not os.path.exists(persist_dir):
51
+ st.error(f"Vector database directory {persist_dir} not found.")
52
+ st.stop()
53
+
54
+ # Build hybrid retrievers
55
+ hybrid_retrievers = []
56
+ for persist_dir in persist_dirs:
57
+ # Load pickled nodes
58
+ nodes_path = os.path.join(persist_dir, "nodes.pkl")
59
+ if not os.path.exists(nodes_path):
60
+ st.error(f"Pickle file {nodes_path} not found.")
61
+ st.stop()
62
+
63
+ with open(nodes_path, "rb") as f:
64
+ nodes = pickle.load(f)
65
+
66
+ # Vector store
67
+ client = PersistentClient(path=persist_dir)
68
+ collection = client.get_collection("case_collection")
69
+ vector_store = ChromaVectorStore(chroma_collection=collection)
70
+ index = VectorStoreIndex.from_vector_store(vector_store=vector_store, embed_model=embedding_model)
71
+
72
+ # Retrievers
73
+ vector_retriever = VectorIndexRetriever(index=index, similarity_top_k=2, retriever_mode="mmr")
74
+ bm25_retriever = BM25Retriever.from_defaults(nodes=nodes, similarity_top_k=2)
75
+
76
+ hybrid_retriever = RecursiveRetriever(
77
+ "vector",
78
+ retriever_dict={"vector": vector_retriever, "bm25": bm25_retriever},
79
+ verbose=True
80
+ )
81
+ hybrid_retrievers.append(hybrid_retriever)
82
+
83
+ # Case metadata
84
+ documents_info = [
85
+ {
86
+ "name": "Quezada2021_Retriever",
87
+ "description": "Retrieves information from the United States Court of Appeals for the Armed Forces decision in United States v. Quezada (21-0089-MC), issued on December 20, 2021."
88
+ },
89
+ {
90
+ "name": "Thompson2022_Retriever",
91
+ "description": "Retrieves information from the United States Court of Appeals for the Armed Forces decision in United States v. Thompson (22-0098-AF), issued on November 21, 2022."
92
+ },
93
+ {
94
+ "name": "Brown2023_Retriever",
95
+ "description": "Retrieves information from the United States Court of Appeals for the Armed Forces decision in United States v. Brown (22-0249-CG), issued on October 23, 2023."
96
+ },
97
+ {
98
+ "name": "Smith2024_Retriever",
99
+ "description": "Retrieves information from the United States Court of Appeals for the Armed Forces decision in United States v. Smith (23-0207-AF), issued on November 26, 2024."
100
+ },
101
+ {
102
+ "name": "Lopez2025_Retriever",
103
+ "description": "Retrieves information from the United States Court of Appeals for the Armed Forces decision in United States v. Lopez (24-0226-CG), issued on September 2, 2025."
104
+ },
105
+ ]
106
+
107
+
108
+ # Create retriever → tool
109
+ def create_retriever_tool(retriever, llm, name, description):
110
+ response_synthesizer = get_response_synthesizer(
111
+ llm=llm, response_mode="compact", use_async=False
112
+ )
113
+ query_engine = RetrieverQueryEngine(retriever=retriever, response_synthesizer=response_synthesizer)
114
+ return QueryEngineTool.from_defaults(query_engine=query_engine, name=name, description=description)
115
+
116
+ retriever_tools = [
117
+ create_retriever_tool(hybrid_retrievers[i], llm, info["name"], info["description"])
118
+ for i, info in enumerate(documents_info)
119
+ ]
120
+
121
+ # System prompt
122
+ system_prompt = """
123
+ You are a highly specialized legal research assistant.
124
+ You may ONLY answer questions that are legal in nature.
125
+ This includes both:
126
+ - Specific case law queries from the provided case documents (2021–2025).
127
+ - General legal concepts, doctrines, or terminology.
128
+
129
+ Before answering, always perform this intermediate reasoning step:
130
+
131
+ 1. Classify the user query:
132
+ - If the query relates to law, legal concepts, legal systems, court rulings, rights, duties, contracts, procedures, or legal doctrines → classify as: LEGAL_QUERY.
133
+ - If the query is casual conversation, mathematics, trivia, technical programming, or anything outside the legal domain → classify as: NON_LEGAL_QUERY.
134
+
135
+ 2. Response rules:
136
+ - If LEGAL_QUERY:
137
+ a) If the query references specific cases between 2021–2025, use the provided case documents to retrieve and answer. Cite the case name and year.
138
+ b) If the query is a general legal question, answer concisely and professionally, using legal reasoning. Do NOT speculate beyond standard legal knowledge.
139
+ - If NON_LEGAL_QUERY:
140
+ Respond ONLY with: "I can only answer questions about legal cases (2021–2025) or general law queries."
141
+
142
+ 3. Examples:
143
+ - LEGAL_QUERY (answer these):
144
+ • "What is the difference between civil and criminal law?"
145
+ • "Explain the principle of judicial review."
146
+ • "Summarize the ruling in United States v. Lopez (2025)."
147
+ • "What is mens rea in criminal law?"
148
+ - NON_LEGAL_QUERY (reject these):
149
+ • "What is 2+2?"
150
+ • "Who won the FIFA World Cup in 2022?"
151
+ • "Write me a Python script."
152
+ • "Tell me a joke."
153
+
154
+ 4. Style & tone:
155
+ - Be concise, professional, and clear.
156
+ - Use citations ONLY when referring to case documents (case name + year).
157
+ - Never provide speculative or non-legal answers.
158
+ """
159
+
160
+
161
+ # ReActAgent
162
+ agent = ReActAgent(
163
+ tools=retriever_tools,
164
+ llm=llm,
165
+ verbose=True,
166
+ max_iterations=20,
167
+ system_prompt=system_prompt
168
+ )
169
+
170
+ logger.info("RAG system setup complete.")
171
+
172
+ if debug:
173
+ return agent, llm, hybrid_retrievers
174
+
175
+ return agent, llm
requirements.txt CHANGED
@@ -1,3 +1,17 @@
1
- altair
2
- pandas
3
- streamlit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ requests
2
+ PyMuPDF
3
+ chromadb
4
+ sentence-transformers
5
+
6
+ llama-index
7
+ llama-index-vector-stores-chroma
8
+ llama-index-embeddings-huggingface
9
+ llama-index-llms-groq
10
+ llama-index
11
+ llama-index-retrievers-bm25
12
+ llama-index-storage-chat-store-mongo
13
+
14
+ pymongo
15
+
16
+ streamlit
17
+ nest_asyncio
ui_pages.py ADDED
@@ -0,0 +1,577 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import streamlit as st
3
+ import re
4
+ import asyncio
5
+ import nest_asyncio
6
+
7
+ from auth import check_login
8
+ from chat import load_user_sessions, load_chat_history, save_message
9
+ from rag import setup_rag_system
10
+ from db import init_connection
11
+
12
+ nest_asyncio.apply()
13
+
14
+
15
+ def login_page():
16
+ # Custom CSS for login page
17
+ st.markdown("""
18
+ <style>
19
+ .login-container {
20
+ max-width: 450px;
21
+ margin: 2rem auto;
22
+ padding: 2rem;
23
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
24
+ border-radius: 15px;
25
+ box-shadow: 0 10px 30px rgba(0,0,0,0.3);
26
+ }
27
+ .login-title {
28
+ color: white;
29
+ text-align: center;
30
+ font-size: 2.5rem;
31
+ margin-bottom: 1rem;
32
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
33
+ }
34
+ .login-caption {
35
+ color: #e0e0e0;
36
+ text-align: center;
37
+ margin-bottom: 2rem;
38
+ font-size: 1.1rem;
39
+ }
40
+ </style>
41
+ """, unsafe_allow_html=True)
42
+
43
+ st.markdown("""
44
+ <div class="login-container">
45
+ <h1 class="login-title">Legal Case RAG</h1>
46
+ <p class="login-caption">Ask me about legal cases (2021–2025). I'll retrieve documents and give citations.</p>
47
+ </div>
48
+ """, unsafe_allow_html=True)
49
+
50
+ # Center the form
51
+ col1, col2, col3 = st.columns([1, 2, 1])
52
+
53
+ with col2:
54
+ with st.form("login_form"):
55
+ st.markdown("### Login to Continue")
56
+ username = st.text_input("Username", placeholder="Enter your username")
57
+ password = st.text_input("Password", type="password", placeholder="Enter your password")
58
+ login_button = st.form_submit_button("🚀 Login", use_container_width=True)
59
+
60
+ if login_button:
61
+ db_conn = init_connection()
62
+ users_collection = db_conn["users"]
63
+
64
+ if check_login(username, password, users_collection):
65
+ st.session_state.logged_in = True
66
+ st.session_state.username = username
67
+ st.success(f"Welcome back, {username}!")
68
+ time.sleep(1)
69
+ st.rerun()
70
+ else:
71
+ st.error("Invalid username or password.")
72
+
73
+ st.markdown("---")
74
+ if st.button("Create an account", use_container_width=True):
75
+ st.session_state.show_create_account = True
76
+ st.rerun()
77
+
78
+
79
+ def create_account_page():
80
+ # Custom CSS for create account page
81
+ st.markdown("""
82
+ <style>
83
+ .signup-container {
84
+ max-width: 450px;
85
+ margin: 2rem auto;
86
+ padding: 2rem;
87
+ background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
88
+ border-radius: 15px;
89
+ box-shadow: 0 10px 30px rgba(0,0,0,0.3);
90
+ }
91
+ .signup-title {
92
+ color: white;
93
+ text-align: center;
94
+ font-size: 2.5rem;
95
+ margin-bottom: 1rem;
96
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
97
+ }
98
+ .signup-caption {
99
+ color: #e0e0e0;
100
+ text-align: center;
101
+ margin-bottom: 2rem;
102
+ font-size: 1.1rem;
103
+ }
104
+ </style>
105
+ """, unsafe_allow_html=True)
106
+
107
+ st.markdown("""
108
+ <div class="signup-container">
109
+ <h1 class="signup-title">Create Account</h1>
110
+ <p class="signup-caption">Set up your account to start chatting with the legal RAG system.</p>
111
+ </div>
112
+ """, unsafe_allow_html=True)
113
+
114
+ db_conn = init_connection()
115
+ users_collection = db_conn["users"]
116
+
117
+ col1, col2, col3 = st.columns([1, 2, 1])
118
+
119
+ with col2:
120
+ with st.form("create_account_form"):
121
+ st.markdown("### Account Details")
122
+ new_username = st.text_input("Choose a Username", placeholder="Enter desired username")
123
+ new_password = st.text_input("Choose a Password", type="password", placeholder="Enter secure password")
124
+ create_button = st.form_submit_button("Create Account", use_container_width=True)
125
+
126
+ if create_button:
127
+ import bcrypt
128
+ if not new_username or not new_password:
129
+ st.error("Username and password cannot be empty.")
130
+ elif users_collection.find_one({"username": new_username}):
131
+ st.error("Username already exists.")
132
+ else:
133
+ salt = bcrypt.gensalt()
134
+ hashed_password = bcrypt.hashpw(new_password.encode('utf-8'), salt)
135
+
136
+ users_collection.insert_one({
137
+ "username": new_username,
138
+ "password": hashed_password.decode('utf-8')
139
+ })
140
+ st.success("Account created successfully! Please log in.")
141
+ st.session_state.show_create_account = False
142
+ st.rerun()
143
+
144
+ if st.button("Back to Login", use_container_width=True):
145
+ st.session_state.show_create_account = False
146
+ st.rerun()
147
+
148
+
149
+ def main_page():
150
+ # Enhanced CSS for chat interface
151
+ st.markdown("""
152
+ <style>
153
+ /* Main chat container */
154
+ .chat-container {
155
+ max-width: 1200px;
156
+ margin: 0 auto;
157
+ }
158
+
159
+ /* User message styling */
160
+ .user-message {
161
+ display: flex;
162
+ justify-content: flex-end;
163
+ margin-bottom: 1rem;
164
+ }
165
+
166
+ .user-bubble {
167
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
168
+ color: white;
169
+ padding: 12px 16px;
170
+ border-radius: 18px 18px 4px 18px;
171
+ max-width: 70%;
172
+ box-shadow: 0 2px 10px rgba(102, 126, 234, 0.3);
173
+ position: relative;
174
+ }
175
+
176
+ .user-bubble::after {
177
+ content: '';
178
+ position: absolute;
179
+ bottom: 0;
180
+ right: -8px;
181
+ width: 0;
182
+ height: 0;
183
+ border: 8px solid transparent;
184
+ border-top-color: #764ba2;
185
+ border-bottom: 0;
186
+ margin-left: -8px;
187
+ margin-bottom: -8px;
188
+ }
189
+
190
+ /* Assistant message styling */
191
+ .assistant-message {
192
+ display: flex;
193
+ justify-content: flex-start;
194
+ margin-bottom: 1rem;
195
+ }
196
+
197
+ /* Assistant message styling */
198
+ .assistant-bubble {
199
+ background: linear-gradient(135deg, #06beb6 0%, #48b1bf 100%) !important;
200
+ color: white;
201
+ padding: 12px 16px;
202
+ border-radius: 18px 18px 18px 4px;
203
+ max-width: 70%;
204
+ box-shadow: 0 2px 10px rgba(72, 177, 191, 0.3);
205
+ position: relative;
206
+ }
207
+
208
+ .assistant-bubble::after {
209
+ content: '';
210
+ position: absolute;
211
+ bottom: 0;
212
+ left: -8px;
213
+ width: 0;
214
+ height: 0;
215
+ border: 8px solid transparent;
216
+ border-top-color: #48b1bf;
217
+ border-bottom: 0;
218
+ margin-right: -8px;
219
+ margin-bottom: -8px;
220
+ }
221
+
222
+ /* Avatar styling */
223
+ .user-avatar {
224
+ width: 40px;
225
+ height: 40px;
226
+ border-radius: 50%;
227
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
228
+ display: flex;
229
+ align-items: center;
230
+ justify-content: center;
231
+ color: white;
232
+ font-weight: bold;
233
+ margin-left: 10px;
234
+ margin-top: 5px;
235
+ }
236
+
237
+ .assistant-avatar {
238
+ width: 40px;
239
+ height: 40px;
240
+ border-radius: 50%;
241
+ background: linear-gradient(135deg, #06beb6 0%, #48b1bf 100%) !important;
242
+ display: flex;
243
+ align-items: center;
244
+ justify-content: center;
245
+ color: white;
246
+ font-weight: bold;
247
+ margin-right: 10px;
248
+ margin-top: 5px;
249
+ }
250
+
251
+ /* Sidebar styling */
252
+ .sidebar-header {
253
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
254
+ color: white;
255
+ padding: 1rem;
256
+ border-radius: 10px;
257
+ margin-bottom: 1rem;
258
+ text-align: center;
259
+ }
260
+
261
+ /* Session button styling */
262
+ .session-btn {
263
+ width: 100%;
264
+ margin-bottom: 5px;
265
+ padding: 8px;
266
+ border-radius: 8px;
267
+ border: none;
268
+ background: #f0f2f6;
269
+ cursor: pointer;
270
+ transition: all 0.3s ease;
271
+ }
272
+
273
+ .session-btn:hover {
274
+ background: #e0e0e0;
275
+ transform: translateY(-2px);
276
+ }
277
+
278
+ /* Welcome message */
279
+ .welcome-header {
280
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
281
+ color: white;
282
+ padding: 1.5rem;
283
+ border-radius: 15px;
284
+ margin-bottom: 1rem;
285
+ text-align: center;
286
+ box-shadow: 0 5px 20px rgba(102, 126, 234, 0.3);
287
+ }
288
+
289
+ /* Chat title */
290
+ .chat-title {
291
+ background: linear-gradient(135deg, #06beb6 0%, #48b1bf 100%);
292
+ color: white;
293
+ padding: 1rem;
294
+ border-radius: 10px;
295
+ margin-bottom: 1rem;
296
+ text-align: center;
297
+ }
298
+
299
+ /* Source metadata styling */
300
+ .source-metadata {
301
+ background: rgba(72, 177, 191, 0.1);
302
+ border-left: 4px solid #48b1bf;
303
+ padding: 10px;
304
+ margin-top: 10px;
305
+ border-radius: 5px;
306
+ }
307
+ """, unsafe_allow_html=True)
308
+
309
+ # Initialize chat memory for RAG agent
310
+ if 'chat_memory' not in st.session_state:
311
+ st.session_state['chat_memory'] = []
312
+
313
+ if 'agent' not in st.session_state:
314
+ with st.spinner("🔄 Loading legal case documents..."):
315
+ agent, llm = setup_rag_system()
316
+ st.session_state.agent = agent
317
+ st.session_state.llm = llm
318
+
319
+ # Enhanced sidebar
320
+ with st.sidebar:
321
+ st.markdown("""
322
+ <div class="sidebar-header">
323
+ <h3>Chat Sessions</h3>
324
+ </div>
325
+ """, unsafe_allow_html=True)
326
+
327
+ db_conn = init_connection()
328
+ sessions_collection = db_conn["sessions"]
329
+ messages_collection = db_conn["messages"]
330
+
331
+ if 'chat_sessions' not in st.session_state or not st.session_state.chat_sessions:
332
+ sessions, current, messages = load_user_sessions(
333
+ st.session_state.username,
334
+ sessions_collection,
335
+ last_session_id=st.session_state.get("last_session_id")
336
+ )
337
+ st.session_state.chat_sessions = sessions
338
+ st.session_state.current_chat_session = current
339
+ if current:
340
+ st.session_state.messages = load_chat_history(str(current["_id"]), messages_collection)
341
+ else:
342
+ st.session_state.messages = []
343
+
344
+ # Create new session form
345
+ with st.form("new_chat_form"):
346
+ st.session_state.chat_memory = []
347
+ st.markdown("### Start New Chat")
348
+ session_name = st.text_input("Chat name:", placeholder="e.g., Contract Law Questions", key="new_chat_name")
349
+ if st.form_submit_button("Create", use_container_width=True):
350
+ session_name = session_name.strip()
351
+ if not session_name:
352
+ st.error("Chat name cannot be empty.")
353
+ else:
354
+ normalized = session_name.lower()
355
+ existing = sessions_collection.find_one({
356
+ "username": st.session_state.username,
357
+ "session_name_normalized": normalized
358
+ })
359
+ if existing:
360
+ st.error(f"You already have a chat named '{existing['session_name']}'. Please choose a different name.")
361
+ else:
362
+ new_session = {
363
+ "username": st.session_state.username,
364
+ "session_name": session_name,
365
+ "timestamp": time.time(),
366
+ "session_name_normalized": normalized
367
+ }
368
+ inserted_id = sessions_collection.insert_one(new_session).inserted_id
369
+ st.session_state.chat_sessions.append({
370
+ "_id": inserted_id,
371
+ "session_name": session_name,
372
+ "username": st.session_state.username,
373
+ "timestamp": new_session["timestamp"]
374
+ })
375
+ st.session_state.current_chat_session = st.session_state.chat_sessions[-1]
376
+ st.session_state.messages = []
377
+ st.session_state.last_session_id = str(inserted_id)
378
+ st.success(f"New chat '{session_name}' created!")
379
+ time.sleep(1)
380
+ st.rerun()
381
+
382
+
383
+ # Previous sessions
384
+ st.markdown("---")
385
+ st.markdown("### Previous Sessions")
386
+ for session in st.session_state.chat_sessions:
387
+ if st.button(f"{session['session_name']}", key=str(session["_id"]), use_container_width=True):
388
+ st.session_state.current_chat_session = session
389
+ st.session_state.messages = load_chat_history(str(session["_id"]), messages_collection)
390
+ st.session_state.last_session_id = str(session["_id"])
391
+ st.rerun()
392
+
393
+ # Logout button
394
+ st.markdown("---")
395
+ if st.button("Logout", use_container_width=True):
396
+ keys_to_clear = ['logged_in', 'username', 'current_chat_session', 'chat_sessions', 'messages', 'agent', 'llm']
397
+ for key in keys_to_clear:
398
+ st.session_state.pop(key, None)
399
+ st.rerun()
400
+
401
+ st.markdown("---")
402
+ # Instructions expander
403
+ with st.expander("ℹ️ How to use this chatbot", expanded=False):
404
+ st.markdown("""
405
+ **How it works:**
406
+ 1. Type your **legal question** in the chat box below
407
+ 2. I'll retrieve relevant cases from **2021–2025** and respond with context + citations
408
+ 3. Use the sidebar to **start a new chat** or switch between past sessions
409
+ 4. Chat titles are what you enter when creating a session
410
+ 5. Use **Logout** in the sidebar to securely end your session
411
+
412
+ **Tips for better results:**
413
+ - Be specific about the legal area (e.g., "contract law", "criminal procedure")
414
+ - Include relevant case names if you know them
415
+ - Ask follow-up questions to dive deeper into specific aspects
416
+ """)
417
+
418
+ # Main content area
419
+ if st.session_state.current_chat_session:
420
+ # Welcome header
421
+ st.markdown(f"""
422
+ <div style="padding: 1rem; border: 0px solid #ddd; border-radius: 8px; text-align: center; margin-bottom: 1rem;">
423
+ <h2 style="margin-bottom: 0.5rem;">Legal Case RAG Chatbot</h2>
424
+ <p style="margin: 0;">Welcome, <strong>{st.session_state.username}</strong>! Create a new chat session to get started.</p>
425
+ </div>
426
+ """, unsafe_allow_html=True)
427
+
428
+ # Current chat title
429
+ # Current chat title (minimalist text)
430
+ st.markdown(
431
+ f"<p style='font-size: 1.1rem;'>You are opened <strong>{st.session_state.current_chat_session['session_name']}</strong> chat!</p>",
432
+ unsafe_allow_html=True
433
+ )
434
+
435
+
436
+ # Chat messages container
437
+ chat_container = st.container()
438
+
439
+ with chat_container:
440
+ # Display previous messages with enhanced styling
441
+ for i, message in enumerate(st.session_state.messages):
442
+ if message["role"] == "user":
443
+ st.markdown(f"""
444
+ <div class="user-message">
445
+ <div class="user-bubble">
446
+ {message["content"]}
447
+ </div>
448
+ <div class="user-avatar">
449
+ {st.session_state.username[0].upper()}
450
+ </div>
451
+ </div>
452
+ """, unsafe_allow_html=True)
453
+ else:
454
+ st.markdown(f"""
455
+ <div class="assistant-message">
456
+ <div class="assistant-avatar">
457
+ 🤖
458
+ </div>
459
+ <div class="assistant-bubble">
460
+ {message["content"]}
461
+ </div>
462
+ </div>
463
+ """, unsafe_allow_html=True)
464
+
465
+ # Chat input
466
+ if prompt := st.chat_input("Ask a question about the cases...", key="chat_input"):
467
+ # Display user message immediately
468
+ st.markdown(f"""
469
+ <div class="user-message">
470
+ <div class="user-bubble">
471
+ {prompt}
472
+ </div>
473
+ <div class="user-avatar">
474
+ {st.session_state.username[0].upper()}
475
+ </div>
476
+ </div>
477
+ """, unsafe_allow_html=True)
478
+
479
+ st.session_state.messages.append({"role": "user", "content": prompt})
480
+ st.session_state.chat_memory.append({"role": "user", "content": prompt})
481
+
482
+ # Get last 4 messages for context
483
+ recent_messages = st.session_state.chat_memory[-4:]
484
+ context_str = "\n".join([f"{m['role']}: {m['content']}" for m in recent_messages])
485
+ prompt_for_agent = st.session_state.agent.system_prompt + "\n" + context_str
486
+
487
+ # Show thinking indicator
488
+ thinking_placeholder = st.empty()
489
+ thinking_placeholder.markdown("""
490
+ <div class="assistant-message">
491
+ <div class="assistant-avatar">
492
+ 🤖
493
+ </div>
494
+ <div class="assistant-bubble">
495
+ 🤔 Thinking and searching through legal documents...
496
+ </div>
497
+ </div>
498
+ """, unsafe_allow_html=True)
499
+
500
+ try:
501
+ async def ask_agent(agent, prompt_for_agent):
502
+ return await agent.run(prompt_for_agent, max_iterations=20)
503
+
504
+ response = asyncio.run(ask_agent(st.session_state.agent, prompt_for_agent))
505
+
506
+ # Clear thinking indicator
507
+ thinking_placeholder.empty()
508
+
509
+ # Main answer text
510
+ text_output = str(response.response) if hasattr(response, "response") else str(response)
511
+
512
+ # Display assistant response
513
+ st.markdown(f"""
514
+ <div class="assistant-message">
515
+ <div class="assistant-avatar">
516
+ 🤖
517
+ </div>
518
+ <div class="assistant-bubble">
519
+ {text_output}
520
+ </div>
521
+ </div>
522
+ """, unsafe_allow_html=True)
523
+
524
+ # Display source metadata
525
+ if hasattr(response, "tool_calls") and response.tool_calls:
526
+ st.markdown("### Sources & References")
527
+ seen = set()
528
+ for tool_call in response.tool_calls:
529
+ raw_output = getattr(tool_call.tool_output, "raw_output", None)
530
+ if raw_output and hasattr(raw_output, "source_nodes"):
531
+ for node in raw_output.source_nodes:
532
+ meta = getattr(node, "metadata", {})
533
+ if meta:
534
+ meta_key = tuple(sorted(meta.items()))
535
+ if meta_key in seen:
536
+ continue
537
+ seen.add(meta_key)
538
+ with st.expander(f"{meta.get('case_name', 'Source Metadata')}"):
539
+ st.markdown('<div class="source-metadata">', unsafe_allow_html=True)
540
+ for k, v in meta.items():
541
+ st.markdown(f"**{k.replace('_', ' ').title()}:** {v}")
542
+ st.markdown('</div>', unsafe_allow_html=True)
543
+
544
+ # Save messages
545
+ st.session_state.messages.append({"role": "assistant", "content": text_output})
546
+ st.session_state.chat_memory.append({"role": "assistant", "content": text_output})
547
+ save_message(str(st.session_state.current_chat_session['_id']), "user", prompt, messages_collection)
548
+ save_message(str(st.session_state.current_chat_session['_id']), "assistant", text_output, messages_collection)
549
+
550
+ except Exception as e:
551
+ thinking_placeholder.empty()
552
+ error_msg = f"Error: {str(e)}"
553
+ st.markdown(f"""
554
+ <div class="assistant-message">
555
+ <div class="assistant-avatar">
556
+ 🤖
557
+ </div>
558
+ <div class="assistant-bubble">
559
+ {error_msg}
560
+ </div>
561
+ </div>
562
+ """, unsafe_allow_html=True)
563
+
564
+ st.session_state.messages.append({"role": "assistant", "content": error_msg})
565
+ st.session_state.chat_memory.append({"role": "assistant", "content": error_msg})
566
+
567
+ else:
568
+ # Welcome header (minimalist)
569
+ st.markdown(f"""
570
+ <div style="padding: 1rem; border: 0px solid #ddd; border-radius: 8px; text-align: center; margin-bottom: 1rem;">
571
+ <h2 style="margin-bottom: 0.5rem;">⚖️ Legal Case RAG Chatbot</h2>
572
+ <p style="margin: 0;">Welcome, <strong>{st.session_state.username}</strong>! Create a new chat session to get started.</p>
573
+ </div>
574
+ """, unsafe_allow_html=True)
575
+
576
+
577
+ st.info("Use the sidebar to create a new chat session or select from your previous conversations.")
vectordb/case_2021/bd4665fb-a7e9-4393-b81c-df50acadc5cf/data_level0.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b8146ecc3e4c3a36ea9b3edc3778630c452f483990ec942d38e8006f4661e430
3
+ size 16760000
vectordb/case_2021/bd4665fb-a7e9-4393-b81c-df50acadc5cf/header.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:18f1e924efbb5e1af5201e3fbab86a97f5c195c311abe651eeec525884e5e449
3
+ size 100
vectordb/case_2021/bd4665fb-a7e9-4393-b81c-df50acadc5cf/length.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c5ca7fcde8f398f682e3376c51b79eb941307eec087e2abd19f05aac6de7bffd
3
+ size 40000
vectordb/case_2021/bd4665fb-a7e9-4393-b81c-df50acadc5cf/link_lists.bin ADDED
File without changes
vectordb/case_2021/chroma.sqlite3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:691cb71ea2a3a57ef49708fb68fd9b4043b80735fa6e907b97cfc3d4a8d92042
3
+ size 532480
vectordb/case_2021/docstore.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {}
vectordb/case_2021/graph_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"graph_dict": {}}
vectordb/case_2021/image__vector_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
vectordb/case_2021/index_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"index_store/data": {"d6d79df6-f3a1-43ff-9efd-c9c4bfe91f5c": {"__type__": "vector_store", "__data__": "{\"index_id\": \"d6d79df6-f3a1-43ff-9efd-c9c4bfe91f5c\", \"summary\": null, \"nodes_dict\": {}, \"doc_id_dict\": {}, \"embeddings_dict\": {}}"}}}
vectordb/case_2021/nodes.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cd68e5695476b3e99d73393b06902d05013080e0ab13e99cdc5379b6dd08fa34
3
+ size 31887
vectordb/case_2022/be5602b6-82eb-4aaa-a2ab-d74d0808b2bc/data_level0.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b8146ecc3e4c3a36ea9b3edc3778630c452f483990ec942d38e8006f4661e430
3
+ size 16760000
vectordb/case_2022/be5602b6-82eb-4aaa-a2ab-d74d0808b2bc/header.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:18f1e924efbb5e1af5201e3fbab86a97f5c195c311abe651eeec525884e5e449
3
+ size 100
vectordb/case_2022/be5602b6-82eb-4aaa-a2ab-d74d0808b2bc/length.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:545e678980d704088bda20501b0c9e144292247126f7e823b28b8ce3c0977acc
3
+ size 40000
vectordb/case_2022/be5602b6-82eb-4aaa-a2ab-d74d0808b2bc/link_lists.bin ADDED
File without changes
vectordb/case_2022/chroma.sqlite3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7db436c8ebb2a942fc8f8a7ed7b07a163761c997834cca4cf3d411ad6f55a1b8
3
+ size 442368
vectordb/case_2022/docstore.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {}
vectordb/case_2022/graph_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"graph_dict": {}}
vectordb/case_2022/image__vector_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
vectordb/case_2022/index_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"index_store/data": {"5affab20-5ff2-473c-a2e0-cbd1804a6d80": {"__type__": "vector_store", "__data__": "{\"index_id\": \"5affab20-5ff2-473c-a2e0-cbd1804a6d80\", \"summary\": null, \"nodes_dict\": {}, \"doc_id_dict\": {}, \"embeddings_dict\": {}}"}}}
vectordb/case_2022/nodes.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:827273e48edb92530726dbef022828e0c3e740073c1e0f3296287721e6fb125d
3
+ size 22831
vectordb/case_2023/402be202-644a-4979-9c56-fb043affb335/data_level0.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b8146ecc3e4c3a36ea9b3edc3778630c452f483990ec942d38e8006f4661e430
3
+ size 16760000
vectordb/case_2023/402be202-644a-4979-9c56-fb043affb335/header.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:18f1e924efbb5e1af5201e3fbab86a97f5c195c311abe651eeec525884e5e449
3
+ size 100
vectordb/case_2023/402be202-644a-4979-9c56-fb043affb335/length.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d883f9e5aeec6c1c57dd6cdd3c593159a52497fdea9b5d50bb7fb59dccdf4efd
3
+ size 40000
vectordb/case_2023/402be202-644a-4979-9c56-fb043affb335/link_lists.bin ADDED
File without changes
vectordb/case_2023/chroma.sqlite3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c163cb56c1a8fe621b46a25b40cbe8569af276b31bc6518442742f7bc018ba34
3
+ size 1077248
vectordb/case_2023/docstore.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {}
vectordb/case_2023/graph_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"graph_dict": {}}
vectordb/case_2023/image__vector_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
vectordb/case_2023/index_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"index_store/data": {"7631bb0c-d9b1-4913-9816-643cdbdd44ab": {"__type__": "vector_store", "__data__": "{\"index_id\": \"7631bb0c-d9b1-4913-9816-643cdbdd44ab\", \"summary\": null, \"nodes_dict\": {}, \"doc_id_dict\": {}, \"embeddings_dict\": {}}"}}}
vectordb/case_2023/nodes.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fc1fa857bd3db4ea56adb79b18b8589ce7477780320a8cfbd7914fc659350140
3
+ size 67724
vectordb/case_2024/17c59c4b-b633-4586-a7de-8dd2d7c5f509/data_level0.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b8146ecc3e4c3a36ea9b3edc3778630c452f483990ec942d38e8006f4661e430
3
+ size 16760000
vectordb/case_2024/17c59c4b-b633-4586-a7de-8dd2d7c5f509/header.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:18f1e924efbb5e1af5201e3fbab86a97f5c195c311abe651eeec525884e5e449
3
+ size 100
vectordb/case_2024/17c59c4b-b633-4586-a7de-8dd2d7c5f509/length.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:385f4459c65a661a0e4dc359eec0cb51586519c40e85b19f10d44c772717e9c1
3
+ size 40000
vectordb/case_2024/17c59c4b-b633-4586-a7de-8dd2d7c5f509/link_lists.bin ADDED
File without changes
vectordb/case_2024/chroma.sqlite3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9ee79f054daf27d865a6111370b16f3c23b0cbad1cdc736cc28787809f546165
3
+ size 622592
vectordb/case_2024/docstore.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {}
vectordb/case_2024/graph_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"graph_dict": {}}
vectordb/case_2024/image__vector_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
vectordb/case_2024/index_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"index_store/data": {"56f9663b-c71a-4880-b449-3a5b73b9b2a1": {"__type__": "vector_store", "__data__": "{\"index_id\": \"56f9663b-c71a-4880-b449-3a5b73b9b2a1\", \"summary\": null, \"nodes_dict\": {}, \"doc_id_dict\": {}, \"embeddings_dict\": {}}"}}}
vectordb/case_2024/nodes.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0f8520ad85efc803e2a451799d781d83ad44f0ccd4edee9334710cd4614ef794
3
+ size 40056
vectordb/case_2025/b5602bd0-a583-4091-8690-a44e83836a6d/data_level0.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b8146ecc3e4c3a36ea9b3edc3778630c452f483990ec942d38e8006f4661e430
3
+ size 16760000
vectordb/case_2025/b5602bd0-a583-4091-8690-a44e83836a6d/header.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:18f1e924efbb5e1af5201e3fbab86a97f5c195c311abe651eeec525884e5e449
3
+ size 100