ghost1112 commited on
Commit
8a2ae8e
·
verified ·
1 Parent(s): ed5a8e0

Upload 7 files

Browse files
Files changed (7) hide show
  1. .gitattributes +35 -35
  2. Dockerfile +42 -21
  3. README.md +10 -19
  4. app.py +38 -0
  5. generation.py +78 -0
  6. requirements.txt +11 -3
  7. retrieval.py +69 -0
.gitattributes CHANGED
@@ -1,35 +1,35 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz 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
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz 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
Dockerfile CHANGED
@@ -1,21 +1,42 @@
1
- FROM python:3.9-slim
2
-
3
- WORKDIR /app
4
-
5
- RUN apt-get update && apt-get install -y \
6
- build-essential \
7
- curl \
8
- software-properties-common \
9
- git \
10
- && rm -rf /var/lib/apt/lists/*
11
-
12
- COPY requirements.txt ./
13
- COPY src/ ./src/
14
-
15
- RUN pip3 install -r requirements.txt
16
-
17
- EXPOSE 8501
18
-
19
- HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
20
-
21
- ENTRYPOINT ["streamlit", "run", "src/streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use the official Python image from the Docker Hub
2
+ FROM python:3.10-slim
3
+
4
+ # Set up a new user named "user" with user ID 1000
5
+ RUN useradd -m -u 1000 user
6
+
7
+ # Set environment variables for the cache directory (use a writable directory)
8
+ ENV TRANSFORMERS_CACHE=/home/user/.cache/huggingface
9
+
10
+ # Create and set the cache directory so the user can write to it
11
+ RUN mkdir -p /home/user/.cache/huggingface && chown -R user:user /home/user/.cache
12
+
13
+ # Switch to the "user" user
14
+ USER user
15
+
16
+ # Set home to the user's home directory
17
+ ENV HOME=/home/user \
18
+ PATH=/home/user/.local/bin:$PATH
19
+
20
+ # Set the working directory to the user's home directory
21
+ WORKDIR $HOME/app
22
+
23
+ # Upgrade pip to the latest version to avoid issues with outdated pip
24
+ RUN pip install --no-cache-dir --upgrade pip
25
+
26
+ # Copy the current directory contents into the container at $HOME/app setting the owner to the user
27
+ COPY --chown=user . $HOME/app
28
+
29
+ # Install dependencies
30
+ RUN pip install --no-cache-dir -r requirements.txt
31
+
32
+ # Download any necessary assets
33
+ RUN mkdir content
34
+ ADD --chown=user https://huggingface.co/datasets/manhteky123/LawVietnamese/resolve/main/data.csv content/data.csv
35
+ ADD --chown=user https://huggingface.co/datasets/manhteky123/LawVietnamese/resolve/main/faiss_index.bin content/faiss_index.bin
36
+ ADD --chown=user https://huggingface.co/datasets/manhteky123/LawVietnamese/resolve/main/vectors.npy content/vectors.npy
37
+
38
+ # Expose the port the app runs on
39
+ EXPOSE 5000
40
+
41
+ # Define the command to run the application
42
+ CMD ["python", "app.py"]
README.md CHANGED
@@ -1,19 +1,10 @@
1
- ---
2
- title: LAWCHAT
3
- emoji: 🚀
4
- colorFrom: red
5
- colorTo: red
6
- sdk: docker
7
- app_port: 8501
8
- tags:
9
- - streamlit
10
- pinned: false
11
- short_description: Streamlit template space
12
- ---
13
-
14
- # Welcome to Streamlit!
15
-
16
- Edit `/src/streamlit_app.py` to customize this app to your heart's desire. :heart:
17
-
18
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
19
- forums](https://discuss.streamlit.io).
 
1
+ ---
2
+ title: VN Law Chat
3
+ emoji: 👁
4
+ colorFrom: indigo
5
+ colorTo: green
6
+ sdk: docker
7
+ pinned: false
8
+ ---
9
+
10
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
app.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify, render_template, session
2
+ from retrieval import retrieve_documents
3
+ from generation import generate_response
4
+ import os
5
+
6
+ app = Flask(__name__)
7
+ app.secret_key = os.urandom(24) # Set a secret key for session management
8
+
9
+ @app.route('/')
10
+ def index():
11
+ return render_template('index.html')
12
+
13
+ @app.route('/retrieve', methods=['POST'])
14
+ def retrieve():
15
+ query = request.json.get('query')
16
+ documents = retrieve_documents(query)
17
+ return jsonify(documents)
18
+
19
+ @app.route('/generate', methods=['POST'])
20
+ def generate():
21
+ context = request.json.get('context')
22
+ retrieved_data = request.json.get('retrieved_data', [])
23
+
24
+ # Get the conversation history from the session
25
+ conversation_history = session.get('conversation_history', [])
26
+ conversation_history.append(context)
27
+ session['conversation_history'] = conversation_history
28
+
29
+ response = generate_response(context, retrieved_data, conversation_history)
30
+ return jsonify(response)
31
+
32
+ @app.route('/reset', methods=['POST'])
33
+ def reset():
34
+ session.pop('conversation_history', None)
35
+ return jsonify({"message": "Conversation history reset."})
36
+
37
+ if __name__ == "__main__":
38
+ app.run(host="0.0.0.0", port=7860)
generation.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import google.generativeai as genai
2
+
3
+ # Configure the API key
4
+ genai.configure(api_key="AIzaSyBHAbEv8rMAbhAoBWXsubsUHqwP-EAlp6I")
5
+
6
+ from google.generativeai.types import HarmCategory, HarmBlockThreshold
7
+
8
+ safe = {
9
+ "HARM_CATEGORY_HARASSMENT": "BLOCK_NONE",
10
+ "HARM_CATEGORY_HATE_SPEECH": "BLOCK_NONE",
11
+ "HARM_CATEGORY_SEXUALLY_EXPLICIT": "BLOCK_NONE",
12
+ "HARM_CATEGORY_DANGEROUS_CONTENT": "BLOCK_NONE",
13
+ }
14
+
15
+ def generate_response(context, retrieved_data, conversation_history):
16
+ """
17
+ Generate a response using a generative AI model in a Retrieval-Augmented Generation (RAG) setup.
18
+
19
+ Parameters:
20
+ context (str): The user's question or query.
21
+ retrieved_data (str): Relevant information retrieved from the database.
22
+ conversation_history (list): List of previous questions in the conversation.
23
+
24
+ Returns:
25
+ str: The response generated by the model.
26
+ """
27
+ # Select the appropriate model
28
+ model = genai.GenerativeModel("gemini-2.0-flash")
29
+
30
+ # Construct the prompt based on the availability of retrieved data
31
+ if conversation_history:
32
+ history = "\n".join(conversation_history)
33
+ if retrieved_data:
34
+ prompt = (
35
+ "Bạn là một chuyên gia tư vấn luật pháp hàng đầu tại Việt Nam với kiến thức sâu rộng và kinh nghiệm thực tiễn. "
36
+ "Dựa trên các thông tin được cung cấp dưới đây, hãy đưa ra câu trả lời chi tiết, dễ hiểu và có tính chuyên nghiệp cao để hỗ trợ người dùng:\n"
37
+ "--- Thông tin tham khảo ---\n"
38
+ f"{retrieved_data}\n\n"
39
+ "--- Lịch sử cuộc trò chuyện ---\n"
40
+ f"{history}\n\n"
41
+ "--- Câu hỏi hiện tại của người dùng ---\n"
42
+ f"{context}\n\n"
43
+ "Hãy đảm bảo câu trả lời được trình bày một cách rõ ràng, chính xác, và phù hợp với ngữ cảnh pháp lý tại Việt Nam."
44
+ )
45
+ else:
46
+ prompt = (
47
+ "Bạn là một chuyên gia tư vấn luật pháp hàng đầu tại Việt Nam. "
48
+ "Hiện tại, không có thông tin cụ thể nào để hỗ trợ trả lời câu hỏi của người dùng. "
49
+ "Vui lòng yêu cầu người dùng cung cấp thêm thông tin chi tiết hoặc hướng dẫn họ tập trung vào các khía cạnh cụ thể hơn liên quan đến luật pháp Việt Nam."
50
+ )
51
+ else:
52
+ if retrieved_data:
53
+ prompt = (
54
+ "Bạn là một chuyên gia tư vấn luật pháp hàng đầu tại Việt Nam với kiến thức sâu rộng và kinh nghiệm thực tiễn. "
55
+ "Dựa trên các thông tin được cung cấp dưới đây, hãy đưa ra câu trả lời chi tiết, dễ hiểu và có tính chuyên nghiệp cao để hỗ trợ người dùng:\n"
56
+ "--- Thông tin tham khảo ---\n"
57
+ f"{retrieved_data}\n\n"
58
+ "--- Câu hỏi hiện tại của người dùng ---\n"
59
+ f"{context}\n\n"
60
+ "Hãy đảm bảo câu trả lời được trình bày một cách rõ ràng, chính xác, và phù hợp với ngữ cảnh pháp lý tại Việt Nam."
61
+ )
62
+ else:
63
+ prompt = (
64
+ "Bạn là một chuyên gia tư vấn luật pháp hàng đầu tại Việt Nam. "
65
+ "Hiện tại, không có thông tin cụ thể nào để hỗ trợ trả lời câu hỏi của người dùng. "
66
+ "Vui lòng yêu cầu người dùng cung cấp thêm thông tin chi tiết hoặc hướng dẫn họ tập trung vào các khía cạnh cụ thể hơn liên quan đến luật pháp Việt Nam."
67
+ )
68
+
69
+ # Generate the response using the model
70
+
71
+ try:
72
+ response = model.generate_content(prompt, safety_settings=safe)
73
+ if response and response.text:
74
+ return response.text.strip()
75
+ else:
76
+ return "Lỗi: Không có phản hồi từ mô hình."
77
+ except Exception as e:
78
+ return f"Đã xảy ra lỗi khi gọi mô hình: {str(e)}"
requirements.txt CHANGED
@@ -1,3 +1,11 @@
1
- altair
2
- pandas
3
- streamlit
 
 
 
 
 
 
 
 
 
1
+ Flask==2.1.2
2
+ google-generativeai
3
+ faiss-cpu==1.7.2
4
+ pandas==1.3.3
5
+ numpy==1.21.2
6
+ tqdm==4.62.3
7
+ pyngrok==5.1.0
8
+ requests==2.26.0
9
+ Werkzeug==2.2.2
10
+ sentence-transformers==2.2.2
11
+ huggingface-hub==0.11.0
retrieval.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pandas as pd
3
+ from sentence_transformers import SentenceTransformer
4
+ import numpy as np
5
+ from tqdm import tqdm
6
+ import csv
7
+ import faiss
8
+ import requests
9
+
10
+ os.environ['TRANSFORMERS_CACHE'] = '/tmp/huggingface_cache'
11
+
12
+ # URLs of files from Hugging Face
13
+ base_url = "https://huggingface.co/datasets/manhteky123/LawVietnamese/resolve/main/"
14
+ data_url = f"{base_url}data.csv"
15
+ faiss_index_url = f"{base_url}faiss_index.bin"
16
+ vectors_url = f"{base_url}vectors.npy"
17
+
18
+ # Function to download files to disk
19
+ def download_to_disk(url, filename):
20
+ response = requests.get(url)
21
+ if response.status_code == 200:
22
+ with open(filename, 'wb') as f:
23
+ f.write(response.content)
24
+ print(f"Downloaded {url} to {filename}.")
25
+ else:
26
+ raise Exception(f"Failed to download {url}: {response.status_code}")
27
+
28
+ # Download the necessary files to disk
29
+ data_file_path = 'data.csv'
30
+ faiss_index_file_path = 'faiss_index.bin'
31
+ vectors_file_path = 'vectors.npy'
32
+
33
+ download_to_disk(data_url, data_file_path)
34
+ download_to_disk(faiss_index_url, faiss_index_file_path)
35
+ download_to_disk(vectors_url, vectors_file_path)
36
+
37
+ # Read the CSV data from the downloaded file
38
+ with open(data_file_path, 'r', encoding='utf-8') as file:
39
+ reader = csv.reader(file)
40
+ next(reader) # Skip the header row
41
+ data = [row[0].split(',', 2) for row in reader]
42
+ df = pd.DataFrame(data, columns=['so_hieu', 'dieu', 'truncated_text'])
43
+
44
+ print(df.head())
45
+
46
+ # Use the correct column name
47
+ column_name = 'truncated_text'
48
+
49
+ # Use the 'truncated_text' column
50
+ column_name = 'truncated_text'
51
+
52
+ # Load SentenceTransformer
53
+ model = SentenceTransformer('intfloat/multilingual-e5-small')
54
+
55
+ # Read FAISS index from file
56
+ index = faiss.read_index(faiss_index_file_path)
57
+
58
+ # Load vectors
59
+ vectors = np.load(vectors_file_path)
60
+
61
+ def retrieve_documents(query, k=5, threshold=0.7):
62
+ query_vector = model.encode([query], convert_to_tensor=True).cpu().numpy()
63
+ D, I = index.search(query_vector, k)
64
+ similarities = 1 / (1 + D[0])
65
+ filtered_documents = []
66
+ for i, similarity in enumerate(similarities):
67
+ if similarity >= threshold:
68
+ filtered_documents.append(df.iloc[I[0][i]][column_name])
69
+ return filtered_documents