tejastake commited on
Commit
7e60cc0
·
verified ·
1 Parent(s): 160c119

Upload 3 files

Browse files
Files changed (3) hide show
  1. Dockerfile +20 -0
  2. app.py +128 -0
  3. requirements.txt +6 -0
Dockerfile ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9
2
+
3
+ WORKDIR /code
4
+
5
+ COPY ./requirements.txt /code/requirements.txt
6
+
7
+ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
8
+
9
+ RUN useradd -m -u 1000 user
10
+
11
+ USER user
12
+
13
+ ENV HOME=/home/user \
14
+ PATH=/home/user/.local/bin:$PATH
15
+
16
+ WORKDIR $HOME/app
17
+
18
+ COPY --chown=user . $HOME/app
19
+
20
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, Depends, HTTPException
2
+ from pydantic import BaseModel
3
+ import torch
4
+ import torch.nn.functional as F
5
+ import logging
6
+ import sys
7
+ from pinecone_text.sparse import SpladeEncoder
8
+ import re
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+ logging.basicConfig(
13
+ level=logging.getLevelName("INFO"),
14
+ handlers=[logging.StreamHandler(sys.stdout)],
15
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
16
+ logging.info('Logging module started')
17
+
18
+ def get_session():
19
+ return True
20
+
21
+ def is_database_online(session: bool = Depends(get_session)):
22
+ return session
23
+
24
+ app = FastAPI()
25
+ # app.add_api_route("/healthz", health([is_database_online]))
26
+
27
+ class EmbeddingModels:
28
+ def __init__(self, device="cuda" if torch.cuda.is_available() else "cpu"):
29
+ self.device = device
30
+ logging.info(f'Using Device {self.device}')
31
+ self.sparse_model = SpladeEncoder(device=self.device)
32
+
33
+ def preprocessing_patent_data(self,text):
34
+ # Removing Common tags in patent
35
+ pattern0 = r'\b(SUBSTITUTE SHEET RULE 2 SUMMARY OF THE INVENTION|BRIEF DESCRIPTION OF PREFERRED EMBODIMENTS|BRIEF DESCRIPTION OF THE DRAWINGS/FIGURES|BEST MODE FOR CARRYING OUT THE INVENTION|BACKGROUND AND SUMMARY OF THE INVENTION|FIELD AND BACKGROUND OF THE INVENTION|BACKGROUND OF THE PRESENT INVENTION|FIELD AND BACKGROUND OF INVENTION|STAND DER TECHNIK- BACKGROUND ART|BRIEF DESCRIPTION OF THE DRAWINGS|DESCRIPTION OF THE RELATED ART|BRIEF SUMMARY OF THE INVENTION|UTILITY MODEL CLAIMS A CONTENT|DESCRIPTION OF BACKGROUND ART|BRIEF DESCRIPTION OF DRAWINGS|BACKGROUND OF THE INVENTION|BACKGROUND TO THE INVENTION|TÉCNICA ANTERIOR- PRIOR ART|DISCLOSURE OF THE INVENTION|BRIEF SUMMARY OF INVENTION|BACKGROUND OF RELATED ART|SUMMARY OF THE DISCLOSURE|SUMMARY OF THE INVENTIONS|SUMMARY OF THE INVENTION|OBJECTS OF THE INVENTION|THE CONTENT OF INVENTION|DISCLOSURE OF INVENTION|Disclosure of Invention|Complete Specification|RELATED BACKGROUND ART|BACKGROUND INFORMATION|BACKGROUND TECHNOLOGY|DETAILED DESCRIPTION|SUMMARY OF INVENTION|DETAILED DESCRIPTION|PROBLEM TO BE SOLVED|EFFECT OF INVENTION|WHAT IS CLAIMED IS|What is claimed is|What is Claim is|SUBSTITUTE SHEET|SELECTED DRAWING|BACK GROUND ART|BACKGROUND ART|Background Art|JPO&INPIT|CONSTITUTION|DEFINITIONS|Related Art|BACKGROUND|JPO&INPIT|JPO&NCIPI|COPYRIGHT|SOLUTION|SUMMARY)\b'
36
+ text = re.sub(pattern0, '[SEP]', text, flags=re.IGNORECASE)
37
+ text = ' '.join(text.split())
38
+ # Removing all tags between Heading to /Heading and id=
39
+ regex = r'<\s*heading[^>]*>(.*?)<\s*/\s*heading>|<[^<]+>|id=\"p-\d+\"|:'
40
+ result = re.sub(regex, '[SEP]', text, flags=re.IGNORECASE)
41
+ # find_formula_names from pat text to exclude it from below logic regex
42
+ chemical_list = []
43
+ pattern1 = r'\b((?:(?:H|He|Li|Be|B|C|N|O|F|Ne|Na|Mg|Al|Si|P|S|Cl|Ar|K|Ca|Sc|Ti|V|Cr|Mn|Fe|Co|Ni|Cu|Zn|Ga|Ge|As|Se|Br|Kr|Rb|Sr|Y|Zr|Nb|Mo|Tc|Ru|Rh|Pd|Ag|Cd|In|Sn|Sb|Te|I|Xe|Cs|Ba|La|Hf|Ta|W|Re|Os|Ir|Pt|Au|Hg|Tl|Pb|Bi|Po|At|Rn|Fr|Ra|Ac|Rf|Db|Sg|Bh|Hs|Mt|Ds|Rg|Cn|Nh|Fl|Mc|Lv|Ts|Og|Ce|Pr|Nd|Pm|Sm|Eu|Gd|Tb|Dy|Ho|Er|Tm|Yb|Lu|Th|Pa|U|Np|Pu|Am|Cm|Bk|Cf|Es|Fm|Md|No|Lr)\d*)+)\b'
44
+
45
+ formula_names = re.findall(pattern1, result)
46
+ for formula in formula_names:
47
+ if len(formula)>=2:
48
+ chemical_list.append(formula)
49
+ # print("chemical_list:", chemical_list)
50
+
51
+ # Remove numbers and alphanum inside brackets excluding chemical forms
52
+ pattern2 = r"\((?![A-Za-z]+\))[\w\d\s,-]+\)|\([A-Za-z]\)"
53
+ def keep_strings(text):
54
+ matched = text.group(0)
55
+ if any(item in matched for item in chemical_list):
56
+ return matched
57
+ return ' '
58
+ cleaned_text = re.sub(pattern2, keep_strings, result)
59
+ cleaned_text = ' '.join(cleaned_text.split())
60
+ cleaned_text= re.sub("(\[SEP\]+\s*)+", ' ', cleaned_text, flags=re.IGNORECASE)
61
+ # below new logic to remove chemical compounds (eg.chemical- polymerizable compounds)
62
+ p_text2=re.sub('[\—\-\═\=]', ' ', cleaned_text)
63
+ pattern1 = r'\b((?:(?:H|He|Li|Be|B|C|N|O|F|Ne|Na|Mg|Al|Si|P|S|Cl|Ar|K|Ca|Sc|Ti|V|Cr|Mn|Fe|Co|Ni|Cu|Zn|Ga|Ge|As|Se|Br|Kr|Rb|Sr|Y|Zr|Nb|Mo|Tc|Ru|Rh|Pd|Ag|Cd|In|Sn|Sb|Te|I|Xe|Cs|Ba|La|Hf|Ta|W|Re|Os|Ir|Pt|Au|Hg|Tl|Pb|Bi|Po|At|Rn|Fr|Ra|Ac|Rf|Db|Sg|Bh|Hs|Mt|Ds|Rg|Cn|Nh|Fl|Mc|Lv|Ts|Og|Ce|Pr|Nd|Pm|Sm|Eu|Gd|Tb|Dy|Ho|Er|Tm|Yb|Lu|Th|Pa|U|Np|Pu|Am|Cm|Bk|Cf|Es|Fm|Md|No|Lr)\d*)+)\b'
64
+ cleaned_text = re.sub(pattern1, "", p_text2)
65
+ cleaned_text = re.sub(' ,+|, +', ' ', cleaned_text)
66
+ cleaned_text = re.sub(' +', ' ', cleaned_text)
67
+ cleaned_text = re.sub('\.+', '.', cleaned_text)
68
+ cleaned_text = re.sub('[0-9] [0-9] +', ' ', cleaned_text)
69
+ cleaned_text = re.sub('( )', ' ', cleaned_text)
70
+ cleaned_text=cleaned_text.strip()
71
+ return cleaned_text
72
+
73
+ def get_single_sparse_text_embedding(self, df_chunk):
74
+ df_chunk = self.preprocessing_patent_data(df_chunk)
75
+ txt_sp = self.sparse_model.encode_documents(df_chunk)
76
+
77
+ # tensor = torch.tensor(txt_sp['values'])
78
+ # normalized_tensor = F.normalize(tensor, p=2.0, dim=0, eps=1e-12)
79
+ # values = normalized_tensor.tolist()
80
+
81
+ # # Update the sparse_vector with normalized values
82
+ # normalized_sparse_vector = {
83
+ # 'indices': txt_sp['indices'],
84
+ # 'values': values
85
+ # }
86
+ return txt_sp
87
+
88
+ def normalize_sparse_vector_values(self,sparse_vector):
89
+ """
90
+ Normalize the values of a sparse vector to a 0-1 range using min-max scaling,
91
+ considering a known range of sparse scores.
92
+ Args:
93
+ sparse_vector: A dict representing a sparse vector with 'indices' and 'values'
94
+ min_score: The minimum score in the range of sparse scores (default is 0)
95
+ max_score: The maximum score in the range of sparse scores (default is 6000)
96
+ Returns:
97
+ A dict representing the sparse vector with normalized 'values'.
98
+ """
99
+ # normalized_values = [(value - min_score) / (max_score - min_score) for value in sparse_vector['values']]
100
+ self.tensor = torch.tensor(sparse_vector['values'])
101
+ self.normalized_tensor = F.normalize(self.tensor, p=2.0, dim=0, eps=1e-12)
102
+ values = self.normalized_tensor.tolist()
103
+
104
+ # Update the sparse_vector with normalized values
105
+ self.normalized_sparse_vector = {
106
+ 'indices': sparse_vector['indices'],
107
+ 'values': values
108
+ }
109
+ return self.normalized_sparse_vector
110
+
111
+ model = EmbeddingModels()
112
+
113
+ class TextInput(BaseModel):
114
+ text: str
115
+
116
+
117
+ @app.post("/sparse/")
118
+ async def embed_text(item: TextInput):
119
+ try:
120
+ logging.info(f'Received text for embedding: {item.text}')
121
+ embeddings = model.get_single_sparse_text_embedding(item.text)
122
+ logging.info('Embedding process completed')
123
+ return embeddings
124
+ except Exception as e:
125
+ logging.error(f'Error during embedding process: {e}')
126
+ raise HTTPException(status_code=500, detail=str(e))
127
+
128
+
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ torch
4
+ pinecone_text
5
+ fastapi_health
6
+ pinecone-text[splade]