Bhushan4829 commited on
Commit
891ed69
·
1 Parent(s): 4e3847e

First Commit

Browse files
Files changed (5) hide show
  1. .dockerignore +7 -0
  2. Dockerfile +46 -0
  3. README.md +6 -7
  4. requirements.txt +5 -0
  5. semantic_search.py +94 -0
.dockerignore ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ __pycache__
2
+ *.pyc
3
+ *.pyo
4
+ *.pyd
5
+ *.db
6
+ *.sqlite3
7
+ *.log
Dockerfile ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use the official Python 3.9 image
2
+ FROM python:3.9-slim
3
+
4
+ # Create a non-root user
5
+ RUN useradd -m appuser
6
+
7
+ # Set the working directory inside the container
8
+ WORKDIR /app
9
+
10
+ # Set environment variables for cache
11
+ ENV TRANSFORMERS_CACHE=/app/cache/huggingface/transformers
12
+ ENV HF_HOME=/app/cache/huggingface
13
+ ENV SENTENCE_TRANSFORMERS_HOME=/app/cache/sentence_transformers
14
+
15
+ # Ensure the cache directory can be written to
16
+ RUN mkdir -p /app/cache/huggingface/transformers && \
17
+ mkdir -p /app/cache/sentence_transformers && \
18
+ chown -R appuser:appuser /app/cache
19
+
20
+ # Copy the requirements file into the container
21
+ COPY requirements.txt ./requirements.txt
22
+
23
+ # Install system dependencies and Python packages
24
+ RUN apt-get update && \
25
+ apt-get -y install gcc libpq-dev && \
26
+ pip install --no-cache-dir -r requirements.txt
27
+
28
+ # Copy the entire project into the container
29
+ COPY . /app
30
+
31
+ # Switch to the non-root user
32
+ USER appuser
33
+
34
+ # Create a script to load the models
35
+ RUN echo "from sentence_transformers import SentenceTransformer; \
36
+ SentenceTransformer('sentence-transformers/msmarco-distilbert-base-v3'); \
37
+ SentenceTransformer('sentence-transformers/all-mpnet-base-v2'); \
38
+ SentenceTransformer('sentence-transformers/paraphrase-MiniLM-L6-v2');" > load_models.py
39
+
40
+ # Run the model loading script
41
+ RUN python load_models.py
42
+ # RUN python -c "SentenceTransformer('sentence-transformers/paraphrase-MiniLM-L6-v2');"
43
+ # Start the application
44
+ # CMD ["python", "semantic_search.py"]
45
+ # CMD ["gunicorn","-b" , "0.0.0.0:7860", "semantic_search:app"]
46
+ CMD ["uvicorn", "semantic_search:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,13 +1,12 @@
1
  ---
2
- title: Semantic Eval
3
- emoji: 🐢
4
- colorFrom: yellow
5
- colorTo: yellow
6
- sdk: gradio
7
- sdk_version: 5.10.0
8
- app_file: app.py
9
  pinned: false
10
  short_description: Evaluation of semantic search
 
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: Semantic Search Evaluation
3
+ emoji: 🌖
4
+ colorFrom: indigo
5
+ colorTo: red
6
+ sdk: docker
 
 
7
  pinned: false
8
  short_description: Evaluation of semantic search
9
+ app_port: 8080
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ flask
2
+ sentence_transformers
3
+ pandas
4
+ # gunicorn
5
+ uvicorn
semantic_search.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify
2
+ from sentence_transformers import SentenceTransformer, util
3
+ import pandas as pd
4
+ import json
5
+ app = Flask(__name__)
6
+ class EnhancedSemanticSearchEvaluator:
7
+ def __init__(self, relevance_threshold=3, top_k=300, similarity_threshold=0.5):
8
+ self.models = {
9
+ "Model_1": SentenceTransformer('sentence-transformers/msmarco-distilbert-base-v3'),
10
+ "Model_2": SentenceTransformer('sentence-transformers/all-mpnet-base-v2'),
11
+ "Model_3": SentenceTransformer('sentence-transformers/paraphrase-MiniLM-L6-v2')
12
+ }
13
+ self.relevance_threshold = relevance_threshold
14
+ self.top_k = top_k
15
+ self.similarity_threshold = similarity_threshold
16
+
17
+ def compute_similarity(self, model, query, matches):
18
+ query_embedding = model.encode(query, convert_to_tensor=True)
19
+ match_embeddings = model.encode(
20
+ [match['metadata'] for match in matches], convert_to_tensor=True
21
+ )
22
+ scores = util.pytorch_cos_sim(query_embedding, match_embeddings).squeeze(0).tolist()
23
+ return scores
24
+
25
+ def rank_results(self, model, query, matches):
26
+ similarity_scores = self.compute_similarity(model, query, matches)
27
+ for match, score in zip(matches, similarity_scores):
28
+ match['similarity_score'] = score
29
+ ranked_matches = sorted(matches, key=lambda x: x['similarity_score'], reverse=True)
30
+ return ranked_matches
31
+
32
+ def evaluate_results(self, query, results):
33
+ all_metrics = {}
34
+ results_status = {}
35
+
36
+ for model_name, model in self.models.items():
37
+ ranked_matches = self.rank_results(model, query, results['matches'])
38
+
39
+ results_with_scores = []
40
+ for rank, match in enumerate(ranked_matches[:self.top_k], start=1):
41
+ doc_id = match['id']
42
+ similarity_score = match['similarity_score']
43
+
44
+ if similarity_score >= 0.7:
45
+ llm_score = 5
46
+ elif similarity_score >= 0.5:
47
+ llm_score = 4
48
+ elif similarity_score >= 0.3:
49
+ llm_score = 3
50
+ elif similarity_score >= 0.1:
51
+ llm_score = 2
52
+ else:
53
+ llm_score = 1
54
+
55
+ results_with_scores.append({
56
+ "Rank": rank,
57
+ "Document ID": doc_id,
58
+ "Similarity Score": similarity_score,
59
+ "LLM Score": llm_score
60
+ })
61
+
62
+ results_df = pd.DataFrame(results_with_scores)
63
+ results_df['Pass'] = results_df['LLM Score'] >= self.relevance_threshold
64
+
65
+ pass_rate = results_df['Pass'].mean()
66
+ metrics = {
67
+ "Pass Rate": pass_rate,
68
+ "Precision@K": results_df.head(self.top_k)['Pass'].mean(),
69
+ "Recall@K": results_df.head(self.top_k)['Pass'].sum() / max(results_df['Pass'].sum(), 1),
70
+ "F1@K": (
71
+ 2 * (results_df.head(self.top_k)['Pass'].mean() * (results_df.head(self.top_k)['Pass'].sum() / max(results_df['Pass'].sum(), 1))) /
72
+ (results_df.head(self.top_k)['Pass'].mean() + (results_df.head(self.top_k)['Pass'].sum() / max(results_df['Pass'].sum(), 1)))
73
+ if (results_df.head(self.top_k)['Pass'].mean() + (results_df.head(self.top_k)['Pass'].sum() / max(results_df['Pass'].sum(), 1))) > 0 else 0)
74
+
75
+ }
76
+
77
+ all_metrics[model_name] = metrics
78
+ results_status[model_name] = "Test Passed" if pass_rate > 0.5 else "Test Failed"
79
+
80
+ return results_status
81
+
82
+ evaluator = EnhancedSemanticSearchEvaluator()
83
+
84
+ @app.route('/evaluate', methods=['POST'])
85
+ def evaluate():
86
+ content = request.json
87
+ query = content['query']
88
+ results = content['results']
89
+ evaluator = EnhancedSemanticSearchEvaluator()
90
+ evaluation_result = evaluator.evaluate_results(query, results)
91
+ return jsonify(evaluation_result)
92
+
93
+ # if __name__ == '__main__':
94
+ # app.run(debug=True, host='0.0.0.0', port=8000)