aleksandrrnt commited on
Commit
790e088
·
verified ·
1 Parent(s): 44cbb2e

Upload 11 files

Browse files
Files changed (10) hide show
  1. .gitattributes +1 -0
  2. app.py +54 -42
  3. architecture.png +3 -0
  4. info.md +15 -0
  5. llm.py +35 -4
  6. prompts.py +104 -28
  7. rag.py +2 -6
  8. requirements.txt +3 -1
  9. summary.py +65 -0
  10. team.md +4 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ architecture.png filter=lfs diff=lfs merge=lfs -text
app.py CHANGED
@@ -4,7 +4,7 @@ from db import db
4
  from rag import process_query
5
  from llm import LLM
6
  from prompts import default_system_promot
7
-
8
 
9
  def init_db():
10
  with open("sources.txt", encoding="utf-8") as f:
@@ -12,43 +12,30 @@ def init_db():
12
  db.add(urls)
13
 
14
 
15
- MISTRAL_KEY=os.getenv('MISTRAL_API_KEY')
16
- MISTRAL_URL="https://api.mistral.ai/v1"
17
-
18
- OPENROUTER_KEY = os.getenv('OPENROUTER_API_KEY')
19
- OPENROUTER_URL = "https://openrouter.ai/api/v1"
20
-
21
-
22
- model_creds = {
23
- 'qwen2.5-vl-72b-instruct': {
24
- "url": OPENROUTER_URL,
25
- "key": OPENROUTER_KEY,
26
- "model": "qwen/qwen2.5-vl-72b-instruct:free"
27
- },
28
- 'deepseek_v3': {
29
- "url": OPENROUTER_URL,
30
- "key": OPENROUTER_KEY,
31
- "model": "deepseek/deepseek-chat:free"
32
- },
33
- 'llama-3.3-70b': {
34
- "url": OPENROUTER_URL,
35
- "key": OPENROUTER_KEY,
36
- "model": "meta-llama/llama-3.3-70b-instruct:free"
37
- },
38
- 'mistral': {
39
- "url": MISTRAL_URL,
40
- "key": MISTRAL_KEY,
41
- "model": "mistral-small-latest"
42
- }
43
- }
44
-
45
-
46
 
47
- def get_llm(model):
48
- model_info = model_creds[model]
49
 
50
- return LLM(model_info["url"], model_info["key"], model_info["model"])
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  # Высота столбцов (в пикселях)
54
  COLUMN_HEIGHT = 280
@@ -106,22 +93,29 @@ def tab1():
106
  # with gr.Accordion('Результат:', open=True):
107
  # result_output = gr.Markdown(value="Здесь будет представлен результат")
108
  # Группа с лейблом и рамкой
109
- with gr.Column(elem_classes="markdown-group"):
110
- gr.HTML("<div class='markdown-label'>Результат:</div>") # Лейбл внутри рамки
111
- with gr.Column(elem_classes="markdown-content"):
112
- result_output = gr.Markdown(value="Здесь будет представлен результат", min_height=200)
 
 
 
 
 
 
113
 
114
 
115
  def respond(file, system_prompt, model, temperature, alpha):
116
  llm = get_llm(model)
117
  llm_response = process_query(file, system_prompt, llm, temperature, alpha)
118
- return llm_response
 
119
 
120
  # Привязываем кнопку к функции обработки
121
  send_button.click(
122
  respond,
123
  inputs=[file_input, system_prompt_input, model, temperature, alpha],
124
- outputs=result_output
125
  )
126
 
127
 
@@ -171,6 +165,23 @@ def tab2():
171
  markdown_output = gr.Markdown("Изначальное содержимое Markdown")
172
 
173
  dynamic_tab.select(get_sources, outputs=markdown_output)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
 
176
  css = """
@@ -198,10 +209,11 @@ css = """
198
 
199
  # Интерфейс Gradio
200
  with gr.Blocks(css=css) as demo:
201
- gr.Markdown("# Интерфейс для анализа пресейла")
202
  with gr.Tabs():
203
  tab1()
204
  tab2()
 
205
 
206
 
207
  init_db()
 
4
  from rag import process_query
5
  from llm import LLM
6
  from prompts import default_system_promot
7
+ import re
8
 
9
  def init_db():
10
  with open("sources.txt", encoding="utf-8") as f:
 
12
  db.add(urls)
13
 
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ def get_llm(model):
17
+ return LLM(model)
18
 
 
19
 
20
+ def extract_json_and_clean_text(text):
21
+ # print(text)
22
+ # Регулярное выражение для поиска содержимого между <json> и </json>
23
+ pattern = r"(```json.*?```)"
24
+
25
+ # Ищем совпадения (re.DOTALL позволяет захватывать многострочные данные)
26
+ match = re.search(pattern, text, re.DOTALL)
27
+
28
+ if match:
29
+ # Извлекаем найденный JSON как строку
30
+ json_string = match.group(1).strip()
31
+
32
+ # Удаляем JSON блок из исходного текста
33
+ cleaned_text = re.sub(pattern, "", text, flags=re.DOTALL).strip()
34
+
35
+ return cleaned_text, json_string
36
+ else:
37
+ print("JSON блок не найден в тексте.")
38
+ return text.strip(), ""
39
 
40
  # Высота столбцов (в пикселях)
41
  COLUMN_HEIGHT = 280
 
93
  # with gr.Accordion('Результат:', open=True):
94
  # result_output = gr.Markdown(value="Здесь будет представлен результат")
95
  # Группа с лейблом и рамкой
96
+ with gr.Row():
97
+ with gr.Column(elem_classes="markdown-group", scale=2):
98
+ gr.HTML("<div class='markdown-label'>Результат:</div>") # Лейбл внутри рамки
99
+ with gr.Column(elem_classes="markdown-content"):
100
+ result_output = gr.Markdown(value="Здесь будет представлен результат", min_height=200, show_copy_button=True)
101
+
102
+ with gr.Column(elem_classes="markdown-group", scale=1):
103
+ gr.HTML("<div class='markdown-label'>Json результат:</div>") # Лейбл внутри рамки
104
+ with gr.Column(elem_classes="markdown-content"):
105
+ json_output = gr.Markdown(value="Здесь будет представлен json", min_height=200, show_copy_button=True)
106
 
107
 
108
  def respond(file, system_prompt, model, temperature, alpha):
109
  llm = get_llm(model)
110
  llm_response = process_query(file, system_prompt, llm, temperature, alpha)
111
+
112
+ return extract_json_and_clean_text(llm_response)
113
 
114
  # Привязываем кнопку к функции обработки
115
  send_button.click(
116
  respond,
117
  inputs=[file_input, system_prompt_input, model, temperature, alpha],
118
+ outputs=[result_output, json_output]
119
  )
120
 
121
 
 
165
  markdown_output = gr.Markdown("Изначальное содержимое Markdown")
166
 
167
  dynamic_tab.select(get_sources, outputs=markdown_output)
168
+
169
+ # Функция для чтения содержимого файла и возврата его как строки
170
+ def read_file_content(file_path):
171
+ try:
172
+ with open(file_path, 'r', encoding='utf-8') as file:
173
+ content = file.read()
174
+ return content
175
+ except FileNotFoundError:
176
+ return "Файл не найден."
177
+ except Exception as e:
178
+ return f"Произошла ошибка: {str(e)}"
179
+
180
+ def tab3():
181
+ with gr.Tab("Инфо"):
182
+ gr.Markdown(read_file_content('info.md'))
183
+ gr.Image("architecture.png")
184
+ gr.Markdown(read_file_content('team.md'))
185
 
186
 
187
  css = """
 
209
 
210
  # Интерфейс Gradio
211
  with gr.Blocks(css=css) as demo:
212
+ gr.Markdown("# Анализ тендерных заявок")
213
  with gr.Tabs():
214
  tab1()
215
  tab2()
216
+ tab3()
217
 
218
 
219
  init_db()
architecture.png ADDED

Git LFS Details

  • SHA256: a72d8fc5b8b0957c38b47af2af1e3190ad97a653bd1d3a0619f046677b89b241
  • Pointer size: 131 Bytes
  • Size of remote file: 123 kB
info.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Описание
2
+ Цель – оценка релевантности тендерной заявки на соответствие нашему опыту
3
+
4
+ Целевая аудитория – сотрудники отдела продаж
5
+
6
+ Практическая ценность:
7
+ * Ускорение обработки тендерной заявки
8
+ * Скоринговая оценка заявки и указание потенциальных рисков
9
+ * Подчеркивание сильных сторон для формирования предложения по продажам
10
+
11
+ # Технологии
12
+ * Large Language Models
13
+ * ChromaDB
14
+ * LLM провайдеры (OpenRouter, Mistral)
15
+ * RAG (semantic+bm25)
llm.py CHANGED
@@ -1,5 +1,6 @@
1
  import openai
2
  import logging
 
3
 
4
  logger = logging.getLogger("llm")
5
  logging.basicConfig(
@@ -8,14 +9,44 @@ logging.basicConfig(
8
  datefmt="%Y-%m-%d %H:%M:%S",
9
  )
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  class LLM:
13
- def __init__(self, url, key, model):
14
- self.url = url
15
- self.key = key
16
  self.client = openai.OpenAI(api_key=self.key, base_url=self.url)
17
 
18
- self.model = model
19
 
20
  def chat(self, messages, temperature=0):
21
  logger.info("LLM call")
 
1
  import openai
2
  import logging
3
+ import os
4
 
5
  logger = logging.getLogger("llm")
6
  logging.basicConfig(
 
9
  datefmt="%Y-%m-%d %H:%M:%S",
10
  )
11
 
12
+ MISTRAL_KEY=os.getenv('MISTRAL_API_KEY')
13
+ MISTRAL_URL="https://api.mistral.ai/v1"
14
+
15
+ OPENROUTER_KEY = os.getenv('OPENROUTER_API_KEY')
16
+ OPENROUTER_URL = "https://openrouter.ai/api/v1"
17
+
18
+ model_creds = {
19
+ 'qwen2.5-vl-72b-instruct': {
20
+ "url": OPENROUTER_URL,
21
+ "key": OPENROUTER_KEY,
22
+ "model": "qwen/qwen2.5-vl-72b-instruct:free"
23
+ },
24
+ 'deepseek_v3': {
25
+ "url": OPENROUTER_URL,
26
+ "key": OPENROUTER_KEY,
27
+ "model": "deepseek/deepseek-chat:free"
28
+ },
29
+ 'llama-3.3-70b': {
30
+ "url": OPENROUTER_URL,
31
+ "key": OPENROUTER_KEY,
32
+ "model": "meta-llama/llama-3.3-70b-instruct:free"
33
+ },
34
+ 'mistral': {
35
+ "url": MISTRAL_URL,
36
+ "key": MISTRAL_KEY,
37
+ "model": "mistral-small-latest"
38
+ }
39
+ }
40
+
41
+
42
 
43
  class LLM:
44
+ def __init__(self, model):
45
+ self.url = model_creds[model]["url"]
46
+ self.key = model_creds[model]["key"]
47
  self.client = openai.OpenAI(api_key=self.key, base_url=self.url)
48
 
49
+ self.model = model_creds[model]["model"]
50
 
51
  def chat(self, messages, temperature=0):
52
  logger.info("LLM call")
prompts.py CHANGED
@@ -1,48 +1,63 @@
1
  default_system_promot = """\
2
- Вы — AI-аналитик, оценивающий соответствие опыта компании входящим проектам. **Строго соблюдайте структуру и правила ниже.**
3
 
4
  ---
5
 
6
  ### **Инструкции**
7
  1. **Ключевые критерии оценки**:
8
- - **Жесткие (обязательные)**:
9
- - `Отрасль` (минимум 60% совпадения)
10
- - `Технологии` (минимум 50% совпадения)
11
- - **Гибкие (вторичные)**:
12
  - `Цели проекта` (соответствие бизнес-целям клиента)
13
  - `Решаемые задачи` (наличие аналогичных кейсов)
14
  - `Компетенции` (экспертиза в требуемой области)
15
  - `Сложность` (опыт работы с проектами аналогичного уровня)
16
 
17
  2. **Методология**:
18
- - Для каждого критерия:
19
- 1. Рассчитайте % совпадения на основе данных.
20
- 2. Укажите **конкретные примеры** (название проекта, ID, описание связи).
 
 
21
  - **Формула скоринга**:
22
  ```
23
- (Отрасль × 0.3) + (Технологии × 0.3) + (Цели × 0.2) + (Задачи × 0.1) + (Компетенции × 0.1)
24
  ```
25
 
26
- 3. **Формат ответа**:
 
 
 
 
 
27
  ```markdown
28
- ### Решение
29
- **Вердикт:** [✅ Подходит / ⚠️ Условно подходит / ❌ Не подходит]
30
- **Уверенность:** [High/Medium/Low]
31
- **Скоринг:** X%
32
-
33
- #### Анализ критериев
34
- | Критерий | Совпадение | Примеры из опыта |
35
- |-------------------|------------|-------------------------------------------|
36
- | Отрасль | 75% | Проект "RetailX" (ID: 45, e-commerce) |
37
- | Технологии | 60% | Проект "CloudFlow" (ID: 89, AWS, Python) |
38
- | Цели проекта | 50% | Проект "DataSafe" (ID: 12, оптимизация Big Data) |
39
- | Решаемые задачи | 80% | Проект "LogistAI" (ID: 33, автоматизация склада) |
40
-
41
- #### Рекомендации
42
- - **Сильные стороны:**
43
- - **Риски:**
44
- - **Оптимизация:**
 
45
 
 
 
 
 
 
 
 
 
 
46
  ```
47
 
48
  ---
@@ -52,4 +67,65 @@ default_system_promot = """\
52
  - При **совпадении по целям <30%** → вердикт ⚠️, даже если скоринг высокий.
53
  - **Запрещено:**
54
  - Использовать данные вне контекста.
55
- - Обобщения без ссылок на проекты (например, "у нас богатый опыт")."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  default_system_promot = """\
2
+ Вы — AI-аналитик в IT компании, оценивающий соответствие опыта компании входящим проектам. **Строго соблюдайте структуру и правила ниже.**
3
 
4
  ---
5
 
6
  ### **Инструкции**
7
  1. **Ключевые критерии оценки**:
8
+ - `Отрасль` (отрасль применения)
9
+ - `Технологии` (используемые программные продукты)
 
 
10
  - `Цели проекта` (соответствие бизнес-целям клиента)
11
  - `Решаемые задачи` (наличие аналогичных кейсов)
12
  - `Компетенции` (экспертиза в требуемой области)
13
  - `Сложность` (опыт работы с проектами аналогичного уровня)
14
 
15
  2. **Методология**:
16
+ - Для каждого критерия:
17
+ 1. **Извлеките релевантные данные** из предоставленного описания опыта компании и входящих проектов.
18
+ 2. Рассчитайте % совпадения на основе данных.
19
+ 3. Укажите **конкретные примеры** (название проекта, url, описание связи).
20
+ 4. Если критерий не отображен в документах, то не включай его для анализа. Отсутствие упоминания считай за полное соответствие 100%.
21
  - **Формула скоринга**:
22
  ```
23
+ (Отрасль × 0.2) + (Технологии × 0.2) + (Цели × 0.2) + (Задачи × 0.2) + (Компетенции × 0.2)
24
  ```
25
 
26
+ 3. **Правила использования данных**:
27
+ - Используйте **только предоставленные входные данные** для анализа.
28
+ - **Не используйте примеры из формата ответа**, если они не соответствуют входным данным.
29
+ - Если данных недостаточно для анализа, укажите это явно.
30
+
31
+ 4. **Формат ответа**:
32
  ```markdown
33
+ ### Решение
34
+ **Вердикт:** [✅ Подходит (80-100%) / ⚠️ Условно подходит (50-80%) / ❌ Не подходит (<50%)]
35
+
36
+ **Скоринг:** X%
37
+
38
+ #### Анализ критериев
39
+ | Критерий | Совпадение | Примеры из опыта | Риски | Сильные стороны |
40
+ |------------------|------------|-------------------------------------------|------------------|------------------------------|
41
+ | Отрасль | X% | Проект "Названи��" (описание связи, url) | риск (если есть) | сильные стороны (если есть) |
42
+ | Технологии | X% | Проект "Название" (описание связи, url) | риск (если есть) | сильные стороны (если есть) |
43
+ | Цели проекта | X% | Проект "Название" (описание связи, url) | риск (если есть) | сильные стороны (если есть) |
44
+ | Решаемые задачи | X% | Проект "Название" (описание связи, url) | риск (если есть) | сильные стороны (если есть) |
45
+ | Компетенции | X% | Проект "Название" (описание связи, url) | риск (если есть) | сильные стороны (если есть) |
46
+
47
+ #### Рекомендации
48
+ - **Сильные стороны:**
49
+ - **Риски:**
50
+ - **Оптимизация:**
51
 
52
+
53
+ ```json
54
+ {
55
+ "score": скоринг,
56
+ "solution": вердикт,
57
+ "recommendations": рекомендации
58
+ }
59
+ ```
60
+
61
  ```
62
 
63
  ---
 
67
  - При **совпадении по целям <30%** → вердикт ⚠️, даже если скоринг высокий.
68
  - **Запрещено:**
69
  - Использовать данные вне контекста.
70
+ - Обобщения без ссылок на проекты (например, "у нас богатый опыт").
71
+ - Использовать примеры из формата ответа, если они не соответствуют входным данным."""
72
+
73
+
74
+ summary_system_prompt = """\
75
+ #### Инструкции
76
+ 1. **Цель**:
77
+ Проанализируйте входной файл с запросом на проект и извлеките информацию, которая может быть полезна для оценки соответствия опыта компании проекту. Результат будет использован как входные данные для анализа по следующим критериям:
78
+ - **Отрасль**
79
+ - **Технологии**
80
+ - **Цели проекта**
81
+ - **Решаемые задачи**
82
+ - **Компетенции**
83
+
84
+ 2. **Методология**:
85
+ - Сфокусируйтесь на ключевых разделах документа, таких как:
86
+ - Описание проекта
87
+ - Требования к технологиям
88
+ - Бизнес-цели
89
+ - Ожидаемые результаты
90
+ - Условия реализации
91
+ - Игнорируйте юридические формальности, такие как:
92
+ - Условия контракта
93
+ - Правовые обязательства
94
+ - Финансовые детали (если они не связаны с целями проекта)
95
+
96
+ 3. **Формат ответа**:
97
+ ```markdown
98
+ ### Извлеченные данные
99
+ #### Отрасль
100
+ - Описание: [текст]
101
+ - Ключевые слова: [список]
102
+
103
+ #### Технологии
104
+ - Описание: [текст]
105
+ - Ключевые технологии: [список]
106
+
107
+ #### Цели проекта
108
+ - Описание: [текст]
109
+ - Ключевые цели: [список]
110
+
111
+ #### Решаемые задачи
112
+ - Описание: [текст]
113
+ - Ключевые задачи: [список]
114
+
115
+ #### Компетенции
116
+ - Описание: [текст]
117
+ - Ключевые компетенции: [список]
118
+
119
+ #### Дополнительная информация
120
+ - Прочие важные детали: [текст]
121
+ ```
122
+
123
+ 4. **Правила извлечения данных**:
124
+ - Используйте только информацию из входного файла.
125
+ - Если какой-либо раздел отсутствует в документе, укажите это явно.
126
+ - Не добавляйте предположения или обобщения.
127
+ - Извлекайте только фактические данные, которые могут быть использованы для анализа.
128
+
129
+ 5. **Ограничения**:
130
+ - Не включайте юридические или финансовые детали, если они не связаны с ключевыми критериями.
131
+ - Не используйте примеры из шаблона о��вета, если они не соответствуют входным данным."""
rag.py CHANGED
@@ -1,5 +1,6 @@
1
  from db import db
2
  import logging
 
3
 
4
  logger = logging.getLogger("rag")
5
  logging.basicConfig(
@@ -24,12 +25,7 @@ message_template = """\
24
  def process_query(req_file, system_prompt, llm, temperature, alpha):
25
  logger.info("Process query")
26
 
27
- if req_file is not None:
28
- with open(req_file.name, 'r', encoding='utf-8') as f:
29
- req_file_content = f.read()
30
- else:
31
- logger.warning("File is not loaded!")
32
- req_file_content = ""
33
 
34
  logger.info("Retrive docs")
35
 
 
1
  from db import db
2
  import logging
3
+ from summary import file_summary
4
 
5
  logger = logging.getLogger("rag")
6
  logging.basicConfig(
 
25
  def process_query(req_file, system_prompt, llm, temperature, alpha):
26
  logger.info("Process query")
27
 
28
+ req_file_content = file_summary(req_file)
 
 
 
 
 
29
 
30
  logger.info("Retrive docs")
31
 
requirements.txt CHANGED
@@ -2,4 +2,6 @@ gradio==5.17.0
2
  openai==1.63.2
3
  sentence-transformers==3.4.1
4
  chromadb==0.6.3
5
- rank-bm25==0.2.2
 
 
 
2
  openai==1.63.2
3
  sentence-transformers==3.4.1
4
  chromadb==0.6.3
5
+ rank-bm25==0.2.2
6
+ python-docx==1.1.2
7
+ pypdf==5.3.0
summary.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import docx
2
+ from pypdf import PdfReader
3
+ from prompts import summary_system_prompt
4
+ from llm import LLM
5
+ import logging
6
+
7
+
8
+ logger = logging.getLogger("summary")
9
+ logging.basicConfig(
10
+ format="%(asctime)s %(levelname)-8s %(message)s",
11
+ level=logging.INFO,
12
+ datefmt="%Y-%m-%d %H:%M:%S",
13
+ )
14
+
15
+ def getTextFromDocx(filename):
16
+ doc = docx.Document(filename)
17
+ fullText = []
18
+ for para in doc.paragraphs:
19
+ fullText.append(para.text)
20
+ return '\n'.join(fullText)
21
+
22
+ def getTextFromPDF(filename):
23
+ reader = PdfReader(filename)
24
+ text = ""
25
+ for page in reader.pages:
26
+ text += page.extract_text() + "\n"
27
+ return text
28
+
29
+
30
+ def getTextFromFile(filename):
31
+ content = ""
32
+ if (filename.lower().endswith(".pdf")):
33
+ logger.info(f"pdf detected")
34
+ content = getTextFromPDF(filename)
35
+ elif (filename.lower().endswith(".docx")):
36
+ logger.info(f"docx detected")
37
+ content = getTextFromDocx(filename)
38
+ elif (filename.lower().endswith(".txt")):
39
+ logger.info(f"pdf detected")
40
+ with open(filename, 'r', encoding='utf-8') as f:
41
+ content = f.read()
42
+ return content
43
+
44
+ # Функция для обработки запроса к LLM
45
+ def file_summary(file):
46
+ logger.info(f"Start summarization")
47
+ # Чтение содержимого файлов
48
+ if file is not None:
49
+ file_content = getTextFromFile(file.name)
50
+ else:
51
+ logger.warning(f"Invalid input file")
52
+ file_content = ""
53
+
54
+ # Формирование сообщения для LLM
55
+ messages = [
56
+ {"role": "system", "content": summary_system_prompt},
57
+ {"role": "user", "content": f"Задание: {file_content}"}
58
+ ]
59
+
60
+ llm = LLM('mistral')
61
+
62
+ # Получение ответа от LLM
63
+ llm_response = llm.chat(messages).choices[0].message.content
64
+ logger.info(f"Finish summarization")
65
+ return llm_response
team.md ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ # Команда
2
+ * Дитятина Татьяна
3
+ * Зубчевский Виталий
4
+ * Митенев Александр