pollitoconpapass commited on
Commit
528f18a
·
1 Parent(s): 6505ee1

Add application file

Browse files
Files changed (4) hide show
  1. Dockerfile +34 -0
  2. README.md +2 -2
  3. app.py +85 -0
  4. requirements.txt +5 -0
Dockerfile ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use the official Python base image
2
+ FROM python:3.9-slim
3
+
4
+ # Set environment variables for predictable container behavior
5
+ ENV PYTHONDONTWRITEBYTECODE 1
6
+ ENV PYTHONUNBUFFERED 1
7
+
8
+ # Set a working directory in the container
9
+ WORKDIR /app
10
+
11
+ # Install system dependencies required for SentencePiece
12
+ RUN apt-get update && apt-get install -y --no-install-recommends \
13
+ build-essential \
14
+ cmake \
15
+ libprotobuf-dev \
16
+ protobuf-compiler \
17
+ libsentencepiece-dev \
18
+ libsentencepiece0 \
19
+ && rm -rf /var/lib/apt/lists/*
20
+
21
+ # Copy the requirements file
22
+ COPY requirements.txt /app/
23
+
24
+ # Install Python dependencies
25
+ RUN pip install --no-cache-dir -r requirements.txt
26
+
27
+ # Copy the app source code into the container
28
+ COPY app.py /app/
29
+
30
+ # Expose the port the app runs on
31
+ EXPOSE 7860
32
+
33
+ # Run the application
34
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,7 +1,7 @@
1
  ---
2
  title: QnIA Translator API
3
- emoji: 📊
4
- colorFrom: gray
5
  colorTo: indigo
6
  sdk: docker
7
  pinned: false
 
1
  ---
2
  title: QnIA Translator API
3
+ emoji: 🦙🤖
4
+ colorFrom: purple
5
  colorTo: indigo
6
  sdk: docker
7
  pinned: false
app.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import uvicorn
3
+ from typing import Dict
4
+ from fastapi import FastAPI
5
+ from transformers import NllbTokenizer, AutoModelForSeq2SeqLM
6
+
7
+ app = FastAPI()
8
+
9
+ def fix_tokenizer(tokenizer, new_lang='quz_Latn'):
10
+ """
11
+ Add a new language token to the tokenizer vocabulary and update language mappings.
12
+ """
13
+ # First ensure we're working with an NLLB tokenizer
14
+ if not hasattr(tokenizer, 'sp_model'):
15
+ raise ValueError("This function expects an NLLB tokenizer")
16
+
17
+ # Add the new language token if it's not already present
18
+ if new_lang not in tokenizer.additional_special_tokens:
19
+ tokenizer.add_special_tokens({
20
+ 'additional_special_tokens': [new_lang]
21
+ })
22
+
23
+ # Initialize lang_code_to_id if it doesn't exist
24
+ if not hasattr(tokenizer, 'lang_code_to_id'):
25
+ tokenizer.lang_code_to_id = {}
26
+
27
+ # Add the new language to lang_code_to_id mapping
28
+ if new_lang not in tokenizer.lang_code_to_id:
29
+ # Get the ID for the new language token
30
+ new_lang_id = tokenizer.convert_tokens_to_ids(new_lang)
31
+ tokenizer.lang_code_to_id[new_lang] = new_lang_id
32
+
33
+ # Initialize id_to_lang_code if it doesn't exist
34
+ if not hasattr(tokenizer, 'id_to_lang_code'):
35
+ tokenizer.id_to_lang_code = {}
36
+
37
+ # Update the reverse mapping
38
+ tokenizer.id_to_lang_code[tokenizer.lang_code_to_id[new_lang]] = new_lang
39
+
40
+ return tokenizer
41
+
42
+
43
+ MODEL_URL = "pollitoconpapass/QnIA-translation-model"
44
+ model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_URL)
45
+ tokenizer = NllbTokenizer.from_pretrained(MODEL_URL)
46
+ fix_tokenizer(tokenizer)
47
+
48
+
49
+ # === HEALTH CHECK ===
50
+ @app.get("/_health")
51
+ async def health_check():
52
+ return {'status': 'ok'}
53
+
54
+
55
+ # === TRANSLATION ===
56
+ @app.post("/qnia-translate")
57
+ async def translate(data: Dict, a=32, b=3, max_input_length=1024, num_beams=4):
58
+ start = time.time()
59
+
60
+ text = data['text']
61
+ src_lang = data['src_lang']
62
+ tgt_lang = data['tgt_lang']
63
+
64
+ tokenizer.src_lang = src_lang
65
+ tokenizer.tgt_lang = tgt_lang
66
+ inputs = tokenizer(text, return_tensors='pt', padding=True, truncation=True, max_length=max_input_length)
67
+
68
+ result = model.generate(
69
+ **inputs.to(model.device),
70
+ forced_bos_token_id=tokenizer.convert_tokens_to_ids(tgt_lang),
71
+ max_new_tokens=int(a + b * inputs.input_ids.shape[1]),
72
+ num_beams=num_beams,
73
+ )
74
+
75
+ translation = tokenizer.batch_decode(result, skip_special_tokens=True)
76
+ translation = translation[0]
77
+
78
+ end = time.time()
79
+ print(f"\nTime: {end - start}")
80
+
81
+ return {'translation': translation}
82
+
83
+
84
+ if __name__ == "__main__":
85
+ uvicorn.run(app, host="0.0.0.0", port=7860)
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ fastapi==0.115.6
2
+ sentencepiece==0.2.0
3
+ torch==2.4.0
4
+ transformers==4.46.1
5
+ uvicorn==0.34.0