Shenuki commited on
Commit
5bf38c0
Β·
verified Β·
1 Parent(s): afcbbbf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +105 -43
app.py CHANGED
@@ -1,86 +1,148 @@
1
  # app.py
2
 
 
3
  import requests
4
  import wikipedia
5
  import gradio as gr
6
- from transformers import pipeline
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
- # 1) Load the BERT NER pipeline
9
- ner = pipeline(
 
10
  "ner",
11
  model="dslim/bert-base-NER-uncased",
12
  grouped_entities=True
13
  )
14
 
15
- # 2) Geocode via Nominatim
 
16
  def geocode(place: str):
17
  resp = requests.get(
18
  "https://nominatim.openstreetmap.org/search",
19
  params={"q": place, "format": "json", "limit": 1},
20
- headers={"User-Agent": "iVoiceContext/1.0"}
21
- )
22
- data = resp.json()
23
- if not data:
24
- return None
25
- return float(data[0]["lat"]), float(data[0]["lon"])
26
 
27
- # 3) Fetch POIs via Overpass
28
  def fetch_osm(lat, lon, osm_filter, limit=5):
29
  query = f"""
30
  [out:json][timeout:25];
31
  (
32
  node{osm_filter}(around:1000,{lat},{lon});
33
  way{osm_filter}(around:1000,{lat},{lon});
34
- rel{osm_filter}(around:1000,{lat},{lon});
35
  );
36
  out center {limit};
37
  """
38
  r = requests.post("https://overpass-api.de/api/interpreter", data={"data": query})
39
  elems = r.json().get("elements", [])
40
- items = []
41
- for e in elems:
42
- name = e.get("tags", {}).get("name")
43
- if name:
44
- items.append({"name": name})
45
- return items
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
- # 4) Main function
48
- def get_context(text: str):
49
- results = ner(text)
50
- # de-duplicate entities by text
51
- ents = {ent["word"]: ent["entity_group"] for ent in results}
52
- out = {}
53
- for word, label in ents.items():
54
  if label == "LOC":
55
- geo = geocode(word)
56
  if not geo:
57
- out[word] = {"type":"location", "error":"could not geocode"}
58
  else:
59
  lat, lon = geo
60
- out[word] = {
61
- "type": "location",
62
- "restaurants": fetch_osm(lat, lon, '["amenity"="restaurant"]'),
63
- "attractions": fetch_osm(lat, lon, '["tourism"="attraction"]'),
 
 
64
  }
65
  else:
66
- # for PERSON, ORG, MISC, etc β†’ Wikipedia
67
  try:
68
- summary = wikipedia.summary(word, sentences=2)
69
  except Exception:
70
  summary = "No summary available."
71
- out[word] = {"type": "wiki", "summary": summary}
72
- if not out:
73
- return {"error": "No entities found"}
74
- return out
75
 
76
- # 5) Gradio UI
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  iface = gr.Interface(
78
  fn=get_context,
79
- inputs=gr.Textbox(lines=3, placeholder="Paste your translated text…"),
 
 
 
 
 
80
  outputs="json",
81
- title="iVoice Context-Aware",
82
- description="BERT NER β†’ geocode LOC β†’ Overpass POIs β†’ Wikipedia for others"
83
- )
 
 
 
 
 
 
84
 
85
  if __name__ == "__main__":
86
- iface.launch()
 
 
 
 
 
1
  # app.py
2
 
3
+ import os
4
  import requests
5
  import wikipedia
6
  import gradio as gr
7
+ import torch
8
+ from transformers import (
9
+ SeamlessM4TProcessor,
10
+ SeamlessM4TForTextToText,
11
+ pipeline as hf_pipeline
12
+ )
13
+
14
+ # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
15
+ # 1) SeamlessM4T Text2Text
16
+ MODEL_NAME = "facebook/hf-seamless-m4t-medium"
17
+ device = "cuda" if torch.cuda.is_available() else "cpu"
18
+ processor = SeamlessM4TProcessor.from_pretrained(MODEL_NAME)
19
+ m4t_model = SeamlessM4TForTextToText.from_pretrained(MODEL_NAME).to(device).eval()
20
+
21
+ def translate_m4t(text, src_iso3, tgt_iso3, auto_detect=False):
22
+ # src_iso3: e.g. "eng", "fra", etc. If auto_detect=True, pass None
23
+ src = None if auto_detect else src_iso3
24
+ inputs = processor(text=text, src_lang=src, return_tensors="pt").to(device)
25
+ tokens = m4t_model.generate(**inputs, tgt_lang=tgt_iso3)
26
+ return processor.decode(tokens[0].tolist(), skip_special_tokens=True)
27
 
28
+ # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
29
+ # 2) BERT‐based NER
30
+ ner = hf_pipeline(
31
  "ner",
32
  model="dslim/bert-base-NER-uncased",
33
  grouped_entities=True
34
  )
35
 
36
+ # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
37
+ # 3) Geocoding & POIs via OpenStreetMap
38
  def geocode(place: str):
39
  resp = requests.get(
40
  "https://nominatim.openstreetmap.org/search",
41
  params={"q": place, "format": "json", "limit": 1},
42
+ headers={"User-Agent":"iVoiceContext/1.0"}
43
+ ).json()
44
+ if not resp: return None
45
+ return float(resp[0]["lat"]), float(resp[0]["lon"])
 
 
46
 
 
47
  def fetch_osm(lat, lon, osm_filter, limit=5):
48
  query = f"""
49
  [out:json][timeout:25];
50
  (
51
  node{osm_filter}(around:1000,{lat},{lon});
52
  way{osm_filter}(around:1000,{lat},{lon});
 
53
  );
54
  out center {limit};
55
  """
56
  r = requests.post("https://overpass-api.de/api/interpreter", data={"data": query})
57
  elems = r.json().get("elements", [])
58
+ return [
59
+ {"name": e["tags"].get("name", "")}
60
+ for e in elems
61
+ if e.get("tags", {}).get("name")
62
+ ]
63
+
64
+ # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
65
+ def get_context(text: str,
66
+ source_lang: str, # always 3-letter, e.g. "eng"
67
+ output_lang: str, # always 3-letter, e.g. "fra"
68
+ auto_detect: bool):
69
+ # 1) Ensure English for NER
70
+ if auto_detect or source_lang != "eng":
71
+ en_text = translate_m4t(text, source_lang, "eng", auto_detect=auto_detect)
72
+ else:
73
+ en_text = text
74
+
75
+ # 2) Extract entities
76
+ ner_out = ner(en_text)
77
+ ents = { ent["word"]: ent["entity_group"] for ent in ner_out }
78
 
79
+ results = {}
80
+ for ent_text, label in ents.items():
 
 
 
 
 
81
  if label == "LOC":
82
+ geo = geocode(ent_text)
83
  if not geo:
84
+ results[ent_text] = {"type":"location","error":"could not geocode"}
85
  else:
86
  lat, lon = geo
87
+ rest = fetch_osm(lat, lon, '["amenity"="restaurant"]')
88
+ attr = fetch_osm(lat, lon, '["tourism"="attraction"]')
89
+ results[ent_text] = {
90
+ "type": "location",
91
+ "restaurants": rest,
92
+ "attractions": attr
93
  }
94
  else:
95
+ # PERSON, ORG, MISC β†’ Wikipedia
96
  try:
97
+ summary = wikipedia.summary(ent_text, sentences=2)
98
  except Exception:
99
  summary = "No summary available."
100
+ results[ent_text] = {"type":"wiki","summary": summary}
 
 
 
101
 
102
+ if not results:
103
+ return {"error":"no entities found"}
104
+
105
+ # 3) Translate **all** text fields β†’ output_lang
106
+ if output_lang != "eng":
107
+ for info in results.values():
108
+ if info["type"] == "wiki":
109
+ info["summary"] = translate_m4t(
110
+ info["summary"], "eng", output_lang, auto_detect=False
111
+ )
112
+ elif info["type"] == "location":
113
+ for poi_list in ("restaurants","attractions"):
114
+ translated = []
115
+ for item in info[poi_list]:
116
+ name = item["name"]
117
+ tr = translate_m4t(name, "eng", output_lang, auto_detect=False)
118
+ translated.append({"name": tr})
119
+ info[poi_list] = translated
120
+
121
+ return results
122
+
123
+ # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
124
  iface = gr.Interface(
125
  fn=get_context,
126
+ inputs=[
127
+ gr.Textbox(lines=3, placeholder="Enter text…"),
128
+ gr.Textbox(label="Source Language (ISO 639-3)"),
129
+ gr.Textbox(label="Target Language (ISO 639-3)"),
130
+ gr.Checkbox(label="Auto-detect source language")
131
+ ],
132
  outputs="json",
133
+ title="iVoice Translate + Context-Aware",
134
+ description=(
135
+ "1) Translate your text β†’ English (if needed)\n"
136
+ "2) Run BERT-NER on English to find LOC/PERSON/ORG\n"
137
+ "3) Geocode LOC β†’ fetch nearby restaurants & attractions\n"
138
+ "4) Fetch Wikipedia summaries for PERSON/ORG\n"
139
+ "5) Translate **all** results β†’ your target language"
140
+ )
141
+ ).queue()
142
 
143
  if __name__ == "__main__":
144
+ iface.launch(
145
+ server_name="0.0.0.0",
146
+ server_port=int(os.environ.get("PORT", 7860)),
147
+ share=True
148
+ )