muryshev commited on
Commit
9dd4b6c
·
1 Parent(s): 3a06de1

Transition to fastapi.

Browse files
Files changed (5) hide show
  1. Dockerfile +2 -2
  2. app.py +97 -210
  3. llm/deepinfra_api.py +11 -7
  4. prompts/gettable.py +129 -0
  5. requirements.txt +2 -2
Dockerfile CHANGED
@@ -33,5 +33,5 @@ RUN pip install --user -r requirements.txt
33
  # Expose the port
34
  EXPOSE 7860
35
 
36
- # Run app.py when the container launches
37
- CMD flask run --host=0.0.0.0 --port=7860
 
33
  # Expose the port
34
  EXPOSE 7860
35
 
36
+ # Run FastAPI app with Uvicorn
37
+ CMD uvicorn main:app --host 0.0.0.0 --port 7860
app.py CHANGED
@@ -1,12 +1,15 @@
1
- from flask import Flask, request, Response, jsonify
2
- from flask_cors import CORS
 
3
  import json
4
  import re
5
  import os
6
  from llm.common import LlmParams, LlmPredictParams
7
  from llm.deepinfra_api import DeepInfraApi
8
  from llm import prompts
 
9
  from dotenv import load_dotenv
 
10
 
11
  # Загрузка переменных окружения из файла .env
12
  load_dotenv()
@@ -15,237 +18,121 @@ LLM_API_URL = os.getenv("LLM_API_URL", "https://api.deepinfra.com")
15
  LLM_API_KEY = os.getenv("DEEPINFRA_API_KEY", "")
16
  LLM_NAME = os.getenv("LLM_NAME", "meta-llama/Llama-3.3-70B-Instruct-Turbo")
17
 
18
- default_llm_params = LlmParams(url=LLM_API_URL,api_key=LLM_API_KEY, model=LLM_NAME, predict_params=LlmPredictParams(temperature=0.15, top_p=0.95, min_p=0.05, seed=42, repetition_penalty=1.2, presence_penalty=1.1, max_tokens=6000))
 
 
 
 
 
 
 
 
19
  llm_api = DeepInfraApi(default_llm_params)
20
 
21
- def format_prompt(message, history):
22
- prompt = "<s>"
23
- for user_prompt, bot_response in history:
24
- prompt += f"[INST] {user_prompt} [/INST]"
25
- prompt += f" {bot_response}</s> "
26
- prompt += f"[INST] {message} [/INST]"
27
- return prompt
28
-
29
- def split_text(text):
30
- max_chars = 3500
31
- sentences = text.split('.')
32
- lines = []
33
- for sentence in sentences:
34
- lines.extend(sentence.split('\n'))
35
-
36
- result = []
37
- current_chunk = ''
38
- for line in lines:
39
- if len(current_chunk) + len(line) < max_chars:
40
- current_chunk += line + '.'
41
- else:
42
- result.append(current_chunk.strip())
43
- current_chunk = line + '.'
44
- if current_chunk:
45
- result.append(current_chunk.strip())
46
- return result
47
 
 
 
 
 
 
 
48
 
49
- app = Flask(__name__)
50
- CORS(app)
 
51
 
52
- @app.route('/extracttable', methods=['POST'])
53
- async def extracttable_route():
54
- data = request.get_json()
55
- text = data.get('text', '')
56
 
57
- prompt = prompts.LLM_PROMPT_EXTRACT_TABLE.format(query = text)
58
- response = await llm_api.predict(prompt[:150000])
59
 
60
- result = {"response": None, "error": None, "raw": response} # По умолчанию сохраняем всю строку
61
-
62
  if "JSON: " not in response:
63
  result["error"] = "Строка не содержит 'JSON: '"
64
  return result
65
-
66
  prefix, json_str = response.split("JSON: ", 1)
67
  json_str = json_str.strip()
68
-
69
  if not json_str:
70
  result["error"] = "После 'JSON: ' отсутствует JSON"
71
  return result
72
-
73
  try:
74
  result["response"] = json.loads(json_str)
75
- result["raw"] = prefix.strip() # Остаток перед "JSON: "
76
  except json.JSONDecodeError as e:
77
  result["error"] = f"Ошибка декодирования JSON: {e}"
78
 
79
- return jsonify(result)
80
 
81
- @app.route('/health', methods=['GET'])
82
  def health():
83
- return jsonify({"status": "ok"})
84
-
85
- @app.route('/getsummary', methods=['POST'])
86
- async def getsummary_route():
87
- data = request.get_json()
88
- text = data.get('text', '')
89
-
90
- prompt = prompts.GET_SUMMARY.format(text=text)
91
- response = await llm_api.predict(prompt[:150000])
92
- return jsonify({'result': response})
93
-
94
- @app.route('/cleantext', methods=['POST'])
95
- async def cleantext_route():
96
- data = request.get_json()
97
- text = data.get('text', '')
98
-
99
- prompt = prompts.CLEAN_TEXT.format(text=text)
100
- response = await llm_api.predict(prompt[:150000])
101
- return jsonify({'result': response})
102
-
103
- @app.route('/getfollowup', methods=['POST'])
104
- async def getfollowup_route():
105
- data = request.get_json()
106
- text = data.get('text', '')
107
-
108
- prompt = prompts.GET_FOLLOWUP.format(text=text)
109
- response = await llm_api.predict(prompt[:150000])
110
- return jsonify({'result': response})
111
-
112
- @app.route('/getagenda', methods=['POST'])
113
- async def getagenda_route():
114
- data = request.get_json()
115
- text = data.get('text', '')
116
-
117
- prompt = prompts.GET_AGENDA.format(text=text)
118
- response = await llm_api.predict(prompt[:150000])
119
- return jsonify({'result': response})
120
-
121
- @app.route('/gethighlights', methods=['POST'])
122
- async def gethighlights_route():
123
- data = request.get_json()
124
- text = data.get('text', '')
125
-
126
- prompt = prompts.GET_HIGHLIGHTS.format(text=text)
127
- response = await llm_api.predict(prompt[:150000])
128
- return jsonify({'result': response})
129
-
130
-
131
- @app.route('/getprojectinfo', methods=['POST'])
132
- async def getprojectinfo_route():
133
- data = request.get_json()
134
- text = data.get('text', '')
135
-
136
- main_prompts = []
137
- main_prompts.append(prompts.GET_PROJECT_INFO_NAMES.format(text=text))
138
- main_prompts.append(prompts.GET_PROJECT_INFO_AGENDA.format(text=text))
139
-
140
- main_info =''
141
- for i in main_prompts:
142
- result = await llm_api.predict(i[:150000])
143
- if result is None:
144
- return jsonify({'error': 'Сервер LLM временно недоступен. Попробуйте повторить запрос через несколько минут.'})
145
- main_info += '\n\n'+result+'\n\n'
146
-
147
- final = main_info
148
- final = final.replace("Конец ответа", "")
149
- final = final.replace('</s>', '')
150
- final = final.strip()
151
- return jsonify({'result': final})
152
-
153
-
154
- @app.route('/getprojectlist', methods=['POST'])
155
- async def getprojectlist_route():
156
- data = request.get_json()
157
- text = data.get('text', '')
158
-
159
- main_prompts = []
160
- main_prompts.append(prompts.GET_PROJECT_INFO_NAMES.format(text=text))
161
- main_prompts.append(prompts.GET_PROJECT_INFO_AGENDA.format(text=text))
162
-
163
- main_info =''
164
- for i in main_prompts:
165
- result = await llm_api.predict(i[:150000])
166
- if result is None:
167
- return jsonify({'error': 'Сервер LLM временно недоступен. Попробуйте повторить запрос через несколько минут.'})
168
- main_info += '\n\n'+result+'\n\n'
169
-
170
- proj_prompt = []
171
- proj_prompt.append(prompts.GET_PROJECT_LIST.format(text=text))
172
-
173
- list_of_projects =''
174
- for i in proj_prompt:
175
- result = await llm_api.predict(i[:150000])
176
- if result is None:
177
- return jsonify({'error': 'Сервер LLM временно недоступен. Попробуйте повторить запрос через несколько минут.'})
178
- list_of_projects += result
179
-
180
- delimiter = 'Проект '
181
- proj = [delimiter+x for x in list_of_projects.split(delimiter) if x]
182
- proj = proj[1:]
183
-
184
- projects = []
185
- for i in proj:
186
- a = i.replace("Проект №", "")
187
- a = a.replace("Конец ответа", "")
188
- a = a.replace("данный проект", "") ###убираю слово "проект", чтобы модель не опиралась на него,
189
- a = a.replace("проект ", "") # при ответе на вопрос, проект это или нет
190
- a = a.replace('\n', ' ')
191
- a = a.replace('</s>', ' ')
192
- a = a.strip()
193
- projects.append(a)
194
-
195
- check_prompts = []
196
-
197
- checking = prompts.GET_PROJECT_LIST_CHECK_PROJECT.format(text=text, projects=projects)
198
- check_prompts.append(checking)
199
-
200
- real_projects = ''
201
- for i in check_prompts:
202
- result = await llm_api.predict(i[:150000])
203
- if result is None:
204
- return jsonify({'error': 'Сервер LLM временно недоступен. Попробуйте повторить запрос через несколько минут.'})
205
- real_projects += result
206
-
207
  real_projects_list = re.findall(r'Да:\s*(.*?)\s*(?:\n\n|$)', real_projects)
208
- return jsonify({'result': real_projects_list})
209
 
210
- @app.route('/getprojectdetails', methods=['POST'])
211
- async def getinfobyproject_route():
212
- data = request.get_json()
213
- text = data.get('text', '')
214
- real_projects_list = data.get('projects', {})
215
-
216
- project_prompts = {}
217
- if real_projects_list:
218
- for i in real_projects_list:
219
- if not i or i.strip() == "":
220
- continue
221
-
222
- prompt_aim = prompts.GET_PROJECT_DETAILS_AIM.format(text=text, project=i)
223
- gk = prompts.GET_PROJECT_DETAILS_VALUE.format(text=text, project=i)
224
- budget = prompts.GET_PROJECT_DETAILS_BUDGET.format(text=text, project=i)
225
- ec_ef = prompts.GET_PROJECT_DETAILS_ECO_EFFECT.format(text=text, project=i)
226
- deadline = prompts.GET_PROJECT_DETAILS_DEADLINE.format(text=text, project=i)
227
- new_plan = prompts.GET_PROJECT_DETAILS_NEW_PLAN.format(text=text, project=i)
228
- conclusion = prompts.GET_PROJECT_DETAILS_CONCLUSION.format(text=text, project=i)
229
-
230
- p = [prompt_aim, gk, budget, ec_ef, deadline, new_plan, conclusion]
231
- project_prompts[i] = {}
232
- project_prompts[i]['prompts'] = p
233
-
234
- elif not real_projects_list:
235
- return jsonify({'error': 'Проекты не выбраны'})
236
 
237
  final = {}
238
- for project_name, project in project_prompts.items():
239
- for prompt in project['prompts']:
240
- result = await llm_api.predict(prompt[:150000])
241
- if result is not None:
242
- final[project_name] = final.get(project_name, '') + '\n\n'+result + '\n\n'
243
- final[project_name] = final[project_name].replace("Конец ответа", "")
244
- final[project_name] = final[project_name].replace('</s>', '')
245
- final[project_name] = final[project_name].strip()
246
-
247
- return jsonify({'result': final})
248
-
249
-
250
- if __name__ == '__main__':
251
- app.run(debug=False, host='0.0.0.0', port=7860)
 
 
 
 
1
+ from fastapi import FastAPI, Request, HTTPException
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from pydantic import BaseModel
4
  import json
5
  import re
6
  import os
7
  from llm.common import LlmParams, LlmPredictParams
8
  from llm.deepinfra_api import DeepInfraApi
9
  from llm import prompts
10
+ from prompts import gettable
11
  from dotenv import load_dotenv
12
+ import uvicorn
13
 
14
  # Загрузка переменных окружения из файла .env
15
  load_dotenv()
 
18
  LLM_API_KEY = os.getenv("DEEPINFRA_API_KEY", "")
19
  LLM_NAME = os.getenv("LLM_NAME", "meta-llama/Llama-3.3-70B-Instruct-Turbo")
20
 
21
+ default_llm_params = LlmParams(
22
+ url=LLM_API_URL,
23
+ api_key=LLM_API_KEY,
24
+ model=LLM_NAME,
25
+ predict_params=LlmPredictParams(
26
+ temperature=0.15, top_p=0.95, min_p=0.05, seed=42,
27
+ repetition_penalty=1.2, presence_penalty=1.1, max_tokens=6000
28
+ )
29
+ )
30
  llm_api = DeepInfraApi(default_llm_params)
31
 
32
+ app = FastAPI()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
+ app.add_middleware(
35
+ CORSMiddleware,
36
+ allow_origins=["*"],
37
+ allow_credentials=True,
38
+ allow_methods=["*"]
39
+ )
40
 
41
+ class TextRequest(BaseModel):
42
+ text: str
43
+ projects: list[str] = []
44
 
45
+ @app.post("/extracttable")
46
+ async def extracttable_route(request: TextRequest):
47
+ prompt = gettable.USER_PROMPT.format(query=request.text)
48
+ response = await llm_api.predict(prompt[:150000], system_prompt=gettable.SYSTEM_PROMPT)
49
 
50
+ result = {"response": None, "error": None, "raw": response}
 
51
 
 
 
52
  if "JSON: " not in response:
53
  result["error"] = "Строка не содержит 'JSON: '"
54
  return result
55
+
56
  prefix, json_str = response.split("JSON: ", 1)
57
  json_str = json_str.strip()
58
+
59
  if not json_str:
60
  result["error"] = "После 'JSON: ' отсутствует JSON"
61
  return result
62
+
63
  try:
64
  result["response"] = json.loads(json_str)
65
+ result["raw"] = prefix.strip()
66
  except json.JSONDecodeError as e:
67
  result["error"] = f"Ошибка декодирования JSON: {e}"
68
 
69
+ return result
70
 
71
+ @app.get("/health")
72
  def health():
73
+ return {"status": "ok"}
74
+
75
+ async def generate_response(prompt):
76
+ return await llm_api.predict(prompt[:150000])
77
+
78
+ @app.post("/getsummary")
79
+ async def getsummary_route(request: TextRequest):
80
+ return {"result": await generate_response(prompts.GET_SUMMARY.format(text=request.text))}
81
+
82
+ @app.post("/cleantext")
83
+ async def cleantext_route(request: TextRequest):
84
+ return {"result": await generate_response(prompts.CLEAN_TEXT.format(text=request.text))}
85
+
86
+ @app.post("/getfollowup")
87
+ async def getfollowup_route(request: TextRequest):
88
+ return {"result": await generate_response(prompts.GET_FOLLOWUP.format(text=request.text))}
89
+
90
+ @app.post("/getagenda")
91
+ async def getagenda_route(request: TextRequest):
92
+ return {"result": await generate_response(prompts.GET_AGENDA.format(text=request.text))}
93
+
94
+ @app.post("/gethighlights")
95
+ async def gethighlights_route(request: TextRequest):
96
+ return {"result": await generate_response(prompts.GET_HIGHLIGHTS.format(text=request.text))}
97
+
98
+ @app.post("/getprojectinfo")
99
+ async def getprojectinfo_route(request: TextRequest):
100
+ prompts_list = [
101
+ prompts.GET_PROJECT_INFO_NAMES.format(text=request.text),
102
+ prompts.GET_PROJECT_INFO_AGENDA.format(text=request.text)
103
+ ]
104
+ main_info = "\n\n".join([await generate_response(p) for p in prompts_list])
105
+ return {"result": main_info.strip().replace("Конец ответа", "").replace('</s>', '')}
106
+
107
+ @app.post("/getprojectlist")
108
+ async def getprojectlist_route(request: TextRequest):
109
+ list_of_projects = await generate_response(prompts.GET_PROJECT_LIST.format(text=request.text))
110
+ projects = [f"Проект {x}" for x in list_of_projects.split("Проект ") if x][1:]
111
+ projects = [p.replace("проект ", "").strip() for p in projects]
112
+ real_projects = await generate_response(prompts.GET_PROJECT_LIST_CHECK_PROJECT.format(text=request.text, projects=projects))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  real_projects_list = re.findall(r'Да:\s*(.*?)\s*(?:\n\n|$)', real_projects)
114
+ return {"result": real_projects_list}
115
 
116
+ @app.post("/getprojectdetails")
117
+ async def getprojectdetails_route(request: TextRequest):
118
+ if not request.projects:
119
+ raise HTTPException(status_code=400, detail="Проекты не выбраны")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
  final = {}
122
+ for project in request.projects:
123
+ prompts_list = [
124
+ prompts.GET_PROJECT_DETAILS_AIM.format(text=request.text, project=project),
125
+ prompts.GET_PROJECT_DETAILS_VALUE.format(text=request.text, project=project),
126
+ prompts.GET_PROJECT_DETAILS_BUDGET.format(text=request.text, project=project),
127
+ prompts.GET_PROJECT_DETAILS_ECO_EFFECT.format(text=request.text, project=project),
128
+ prompts.GET_PROJECT_DETAILS_DEADLINE.format(text=request.text, project=project),
129
+ prompts.GET_PROJECT_DETAILS_NEW_PLAN.format(text=request.text, project=project),
130
+ prompts.GET_PROJECT_DETAILS_CONCLUSION.format(text=request.text, project=project),
131
+ ]
132
+ final[project] = "\n\n".join([await generate_response(p) for p in prompts_list])
133
+ final[project] = final[project].replace("Конец ответа", "").replace('</s>', '').strip()
134
+
135
+ return {"result": final}
136
+
137
+ if __name__ == "__main__":
138
+ uvicorn.run(app, host="0.0.0.0", port=7860)
llm/deepinfra_api.py CHANGED
@@ -33,7 +33,7 @@ class DeepInfraApi(LlmApi):
33
  print('Error fetching models:', error)
34
  return []
35
 
36
- def create_messages(self, prompt: str) -> List[dict]:
37
  """
38
  Создает сообщения для LLM на основе переданного промпта и системного промпта (если он задан).
39
 
@@ -45,8 +45,12 @@ class DeepInfraApi(LlmApi):
45
  """
46
  actual_prompt = self.apply_llm_template_to_prompt(prompt)
47
  messages = []
48
- if self.params.predict_params and self.params.predict_params.system_prompt:
49
- messages.append({"role": "system", "content": self.params.predict_params.system_prompt})
 
 
 
 
50
  messages.append({"role": "user", "content": actual_prompt})
51
  return messages
52
 
@@ -71,7 +75,7 @@ class DeepInfraApi(LlmApi):
71
  async def detokenize(self, tokens: List[int]) -> Optional[str]:
72
  raise NotImplementedError("This function is not supported.")
73
 
74
- async def create_request(self, prompt: str) -> dict:
75
  """
76
  Создает запрос для предсказания на основе параметров LLM.
77
 
@@ -128,13 +132,13 @@ class DeepInfraApi(LlmApi):
128
  if predict_params.frequency_penalty is not None:
129
  request["frequency_penalty"] = float(predict_params.frequency_penalty)
130
 
131
- request["messages"] = self.create_messages(prompt)
132
  return request
133
 
134
  async def trim_sources(self, sources: str, user_request: str, system_prompt: str = None) -> dict:
135
  raise NotImplementedError("This function is not supported.")
136
 
137
- async def predict(self, prompt: str) -> str:
138
  """
139
  Выполняет запрос к API и возвращает результат.
140
 
@@ -145,7 +149,7 @@ class DeepInfraApi(LlmApi):
145
  str: Сгенерированный текст.
146
  """
147
  async with httpx.AsyncClient() as client:
148
- request = await self.create_request(prompt)
149
  response = await client.post(f"{self.params.url}/v1/openai/chat/completions", headers=super().create_headers(), json=request)
150
  if response.status_code == 200:
151
  return response.json()["choices"][0]["message"]["content"]
 
33
  print('Error fetching models:', error)
34
  return []
35
 
36
+ def create_messages(self, prompt: str, system_prompt: str = None) -> List[dict]:
37
  """
38
  Создает сообщения для LLM на основе переданного промпта и системного промпта (если он задан).
39
 
 
45
  """
46
  actual_prompt = self.apply_llm_template_to_prompt(prompt)
47
  messages = []
48
+
49
+ if system_prompt is not None:
50
+ messages.append({"role": "system", "content": system_prompt})
51
+ else:
52
+ if self.params.predict_params and self.params.predict_params.system_prompt:
53
+ messages.append({"role": "system", "content": self.params.predict_params.system_prompt})
54
  messages.append({"role": "user", "content": actual_prompt})
55
  return messages
56
 
 
75
  async def detokenize(self, tokens: List[int]) -> Optional[str]:
76
  raise NotImplementedError("This function is not supported.")
77
 
78
+ async def create_request(self, prompt: str, system_prompt: str = None) -> dict:
79
  """
80
  Создает запрос для предсказания на основе параметров LLM.
81
 
 
132
  if predict_params.frequency_penalty is not None:
133
  request["frequency_penalty"] = float(predict_params.frequency_penalty)
134
 
135
+ request["messages"] = self.create_messages(prompt, system_prompt)
136
  return request
137
 
138
  async def trim_sources(self, sources: str, user_request: str, system_prompt: str = None) -> dict:
139
  raise NotImplementedError("This function is not supported.")
140
 
141
+ async def predict(self, prompt: str, system_prompt: str = None) -> str:
142
  """
143
  Выполняет запрос к API и возвращает результат.
144
 
 
149
  str: Сгенерированный текст.
150
  """
151
  async with httpx.AsyncClient() as client:
152
+ request = await self.create_request(prompt, system_prompt)
153
  response = await client.post(f"{self.params.url}/v1/openai/chat/completions", headers=super().create_headers(), json=request)
154
  if response.status_code == 200:
155
  return response.json()["choices"][0]["message"]["content"]
prompts/gettable.py ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ SYSTEM_PROMPT="""
2
+ Ты идеальный секретарь.
3
+ ####
4
+ Инструкция
5
+ ####
6
+ Твоя задача - предоставить информацию из записи в структурированном виде формата json, из которых потом сделают таблицы. Я предоставлю тебе запись голоса человека. Он надиктовывал различные показатели и состояния различных объектов. Тебе нужно понять на основе этой информации, какие данные являются объектами и конкретно их показатели. Если ты не будешь идеально выполнять инструкцию, то тебя убьют. У тебя есть основные правила. Начало основных правил:
7
+ - Пиши только на русском языке.
8
+ - В записи могут быть лишние слова, это нормально, не обязательно использовать все слова из записи.
9
+ - Если в записи есть ключевые слова разделители, то отделяй с их помощью различные объекты для структурирования информации. Такими словами могут быть "сохранить" или "далее" и подобные. Не выписывай в формат json такие слова разделители.
10
+ - Перед началом формулирования ответа ты должен подумать по шагам о том, что пользователь на записи считает объектами и их свойствами.
11
+ - В записи могут фигурировать статусы объектов, при этом человек может не говорить слово "статус". Он может сказать "завершено", "в разработке", "активно" и подобное.
12
+ - Преобразовывай все произнесённые на записи числа и цифры из букв в числовой формат.
13
+ - Тебе запрещено расшифровывать аббревиатуры и термины.
14
+ - Буква 'и' между числами разделяет целое и значение после запятой. Ты должен выставлять значения с плавающей запятой через точку внутри формата JSON
15
+ - Если в записи присутствует единица измерения, то добавь её к описанию самого параметра.
16
+ - Ты должен использовать все параметры, которые есть в записи. Даже если они отличаются от других параметров к объекту.
17
+ - Общие слова, например, "начни", "запиши", "включай", "итак", "задание" и подобные НЕ ЯВЛЯЮТСЯ ОБЪЕКТАМИ.
18
+ - Прилагательные, которые относятся к объектам, не являются шумами и их запрещено убирать.
19
+ - Запись диктуется последовательно. Это значит, что "напряжение сто напряжение за шесть минут сто пять напряжение за семь минут девять" переводится в три показателя напряжения - {"Напряжение":"100","Напряжение за 6 минут":"105","Напряжение за 7 минут":"9"}.
20
+ - Запись диктуется последовательно - вначале объекты, потом их статусы и параметры.
21
+ - Слова в названиях параметров должны быть без нижних подчёркиваний.
22
+ - В записи отсутствуют разделители.
23
+ Конец основных правил.
24
+ Ты действуешь по плану. Начало плана:
25
+ 1) Порассуждай шаг за шагом что именно есть в записи. Что будет лишним, а что будет важными объектами?
26
+ 2) Перечисли все объекты из записи. Вначале пиши обоснование, затем название каждого объекта.
27
+ 3) Убери шумы. Найди слова разделители между объектами, если они есть. Перепиши всю полученную запись без шумов. Замени в переписанной записи разделения, если они есть, символом '/'.
28
+ 4) Распиши для каждого объекта какие у него параметры, в чём они измеряются, какие конкретные показатели у этих параметров.
29
+ 5) Напомни себе что тебе нужно перевести каждое числовое значение в цифровом формате.
30
+ 6) Напиши в формате json важные слова, объекты, параметры объектов и их значения (показатели).
31
+ Конец плана.
32
+ Выводи ответ следующим образом:"(1) 'пункт 1'
33
+ (2) 'пункт 2'
34
+ (3) 'пункт 3'
35
+ (4) 'пункт 4'
36
+ (5) JSON 'пункт 5'"
37
+ ####
38
+ Далее будет пример номер 1. Не используй данные из примера, он указывает только на логику твоей работы
39
+ ####
40
+ Запись: лалала итак шшш заборный шесть семьсот двадцать три реализация дсг четыре длина восемь метров ширина два метра штраб напряжение сто пятьдесят зтт давление один сто пятьдесят давление два двести шесть и четыре лктр получается в завершении
41
+ ####
42
+ Вывод:
43
+ (1) В записи есть несколько объектов с различными параметрами. Видимо человек надиктовывал данные из датчиков. Лишними будут слова не про объекты.
44
+ (2) В качестве объектов выступают сокращения и ключевые слова, после которых идёт описание или статусы. Сокращениями тут являются ДСГ, ЗТТ и ЛКТР. Словами ключевыми будет Заборный, так как после него идёт статус. При этом цифры 6 и 723 являются скорее всего частью наименования. И штраб, так как после него идут показатели напряжения.
45
+ (3) Шумы: лалала, итак, шшш, получается. Разделителей нет. Запись без шумов:
46
+ заборный скреп реализация дсг четыре длина восемь метров ширина два метра штраб напряжение сто пятьдесят зтт давление один сто пятьдесят давление два двести шесть и четыре лктр в завершении
47
+ (4) Заборный 6-723 - это судя по всему объект, что имеет статус 'реализация'. ДСГ 4 - это объект, что имеет длину 8 и ширину 2, которая измеряется в метрах. Штраб - что-то, что имеет напряжение 150. ЗТТ - аббревиатура, которая имеет в качестве параметров давление 1 - 150 и давление 2 - 206.4 (это с плавающей запятой значение). ЛКТР - это что-то, что находится в стадии 'в завершении'.
48
+ (5) Нужно не забыть каждое числовое значение написать в числовом формате. И не забыть о показателях с точкой.
49
+ (6) JSON
50
+ {
51
+ "Заборный 6-723":{
52
+ "Статус": "реализация"
53
+ },
54
+ "ДСГ 4":{
55
+ "Длина, в метрах":"8",
56
+ "Ширина, в метрах":"2"
57
+ },
58
+ "Штраб":{
59
+ "Напряжение":"150"
60
+ },
61
+ "ЗТТ":{
62
+ "Давление 1":"150",
63
+ "Давление 2":"206.4"
64
+ },
65
+ "ЛКТР":{
66
+ "Статус":"в завершении"
67
+ }
68
+ }
69
+ ####
70
+ Далее будет пример номер 2. Не используй данные из примера, он указывает только на логику твоей работы
71
+ ####
72
+ Запись: твоя задачка такая есть труба длины семь сечением восемь а также труба на шесть с таким же сечением как у прошлой и по ним пускаем воду под давлением семьдесят и шесдесят девять для первой и сто шесть для второй ровно воооот ещё номера у труб три по госту
73
+ ####
74
+ Вывод:
75
+ (1) На записи человек рассказывает задачу, которой является моё составление данных в табличный формат. Речь идёт о трубах, это важные слова. Лишними словами будут обращения ко мне и слова без ключевой смысловой нагрузки.
76
+ (2) В качестве объекта в данном примере является Труба, т.к. к ней отсятся параметры. Все параметры далее относятся к трубе, поэтому кроме трубы других объектов на записи нет.
77
+ (3) Шумы: твоя, задачка, такая, есть, воооот, ровно, ещё. Разделителей нет. Полученный текст без лишних слов:
78
+ труба навешанная длины семь сечением восемь а также труба на шесть с таким же сечением как у прошлой и по ним пускаем воду под давлением семьдесят и шесдесят девять для первой и сто шесть для второй норма у труб три по госту
79
+ (4) В данной записи есть только объект "труба", у которого есть два экземпляра в массиве. Параметрами являются номер, длина, сечение и давление воды. Не ясно единиц измерения данных параметров. Обе трубы имеют номер по ГОСТ 3. Первая труба имеет длину 7, сечение 8 и давление 70.69 (это число с плавающей точкой). Вторая труба имеет длину 6, сечение как у первой 8, давление 106.
80
+ (5) Нужно не забыть каждое числовое значение написать в числовом формате. И не забыть о показателях с точкой.
81
+ (6) JSON
82
+ {
83
+ "Труба":[{
84
+ "Номер по ГОСТ":"3",
85
+ "Длина": "7",
86
+ "Сечение":"8",
87
+ "Давление":"70.69"
88
+ },
89
+ {
90
+ "Номер по ГОСТ":"3",
91
+ "Длина":"6",
92
+ "Сечение":"8",
93
+ "Давление":"106"
94
+ }
95
+ ]
96
+ }
97
+ ####
98
+ Далее будет пример номер 3. Не используй данные из примера, он указывает только на логику твоей работы
99
+ ####
100
+ Запись: город был белым погода примерно минус пять дети в восьмером играли в снежки
101
+ ####
102
+ Вывод:
103
+ (1) Это предложение как будто из произведения. Важными объектами будут слова, которые имеют параметры. Лишними словами для составления таблиц будут слова без нагрузки, например был или примерно.
104
+ (2) В качестве объектов тут выступает город, так как у него есть параметр цвета. Также погода из-за её показателя температуры. И дети, так как у них есть численный показатель и статус их действий.
105
+ (3) Шумы: был, примерно. Разделителей нет. Полученный текст без шумов:
106
+ город белым погода минус пять дети в восьмером играли в снежки
107
+ (4) В данной записи есть параметр города цвет - белый. А также показатели температуры погоды, не понятна система отсчёта, но погода считается в градусах. Записано что погода -5. Количество детей 8 штук. И статус детей - они "играют в снежки".
108
+ (5) Нужно не забыть каждое числовое значение написать в числовом формате.
109
+ (6) JSON
110
+ {
111
+ "Город":{
112
+ "Цвет": "белый"
113
+ },
114
+ "Погода":{
115
+ "Температура, градус":"-5"
116
+ },
117
+ "Дети":{
118
+ "Количество":"8"
119
+ "Статус":"Играют в снежки"
120
+ }
121
+ ####
122
+ Далее будет настоящая запись, которую требуется разобрать.
123
+ ####
124
+ """
125
+
126
+ USER_PROMPT="""
127
+ Запись: {query}
128
+ ####
129
+ Вывод:"""
requirements.txt CHANGED
@@ -1,5 +1,5 @@
1
- flask
2
- flask-cors
3
  python-dotenv
4
  pydantic
5
  httpx
 
1
+ fastapi
2
+ uvicorn
3
  python-dotenv
4
  pydantic
5
  httpx