DocUA commited on
Commit
a8c7830
·
1 Parent(s): c212462

Add python-dotenv to requirements

Browse files
Files changed (2) hide show
  1. main_new.py +0 -264
  2. requirements.txt +2 -1
main_new.py DELETED
@@ -1,264 +0,0 @@
1
- import os
2
- import re
3
- import gradio as gr
4
- import pandas as pd
5
- import requests
6
- import json
7
- import faiss
8
- import nest_asyncio
9
- import sys
10
- from pathlib import Path
11
- from bs4 import BeautifulSoup
12
- from typing import Union, List
13
- import asyncio
14
- from llama_index.core import (
15
- StorageContext,
16
- ServiceContext,
17
- VectorStoreIndex,
18
- Settings,
19
- load_index_from_storage
20
- )
21
- from llama_index.llms.openai import OpenAI
22
- from llama_index.core.llms import ChatMessage
23
- from llama_index.core.schema import IndexNode
24
- from llama_index.core.storage.docstore import SimpleDocumentStore
25
- from llama_index.retrievers.bm25 import BM25Retriever
26
- from llama_index.embeddings.openai import OpenAIEmbedding
27
- from llama_index.core.retrievers import QueryFusionRetriever
28
- from llama_index.core.workflow import Event, Context, Workflow, StartEvent, StopEvent, step
29
- from llama_index.core.schema import NodeWithScore
30
- from llama_index.core.prompts import PromptTemplate
31
- from llama_index.core.response_synthesizers import ResponseMode, get_response_synthesizer
32
-
33
- from prompts import CITATION_QA_TEMPLATE, CITATION_REFINE_TEMPLATE
34
-
35
- from dotenv import load_dotenv
36
-
37
- load_dotenv()
38
-
39
- OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
40
- os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
41
-
42
- embed_model = OpenAIEmbedding(model_name="text-embedding-3-small")
43
- Settings.embed_model = embed_model
44
- Settings.context_window = 20000
45
- Settings.chunk_size = 2048
46
- Settings.similarity_top_k = 20
47
-
48
- PERSIST_DIR = "/home/docsa/Legal_Position/Save_index"
49
-
50
- # Apply nest_asyncio to handle nested async calls
51
- nest_asyncio.apply()
52
-
53
-
54
- def parse_doc_ids(doc_ids):
55
- if doc_ids is None:
56
- return []
57
- if isinstance(doc_ids, list):
58
- return [str(id).strip('[]') for id in doc_ids]
59
- if isinstance(doc_ids, str):
60
- cleaned = doc_ids.strip('[]').replace(' ', '')
61
- if cleaned:
62
- return [id.strip() for id in cleaned.split(',')]
63
- return []
64
-
65
-
66
- def get_links_html(doc_ids):
67
- parsed_ids = parse_doc_ids(doc_ids)
68
- if not parsed_ids:
69
- return ""
70
- links = [f"[Рішення ВСУ: {doc_id}](https://reyestr.court.gov.ua/Review/{doc_id})"
71
- for doc_id in parsed_ids]
72
- return ", ".join(links)
73
-
74
-
75
- def initialize_components():
76
- try:
77
- persist_path = Path(PERSIST_DIR)
78
-
79
- if not persist_path.exists():
80
- raise FileNotFoundError(f"Directory not found: {persist_path}")
81
-
82
- required_files = ['docstore_es_filter.json', 'bm25_retriever']
83
-
84
- missing_files = [f for f in required_files if not (persist_path / f).exists()]
85
-
86
- if missing_files:
87
- raise FileNotFoundError(f"Missing required files: {', '.join(missing_files)}")
88
-
89
- global retriever_bm25
90
-
91
- docstore = SimpleDocumentStore.from_persist_path(str(persist_path / "docstore_es_filter.json"))
92
- bm25_retriever = BM25Retriever.from_persist_dir(str(persist_path / "bm25_retriever_es"))
93
-
94
- retriever_bm25 = QueryFusionRetriever(
95
- [
96
- bm25_retriever,
97
- ],
98
- similarity_top_k=Settings.similarity_top_k,
99
- num_queries=1,
100
- use_async=True,
101
- )
102
- return True
103
- except Exception as e:
104
- print(f"Error initializing components: {str(e)}", file=sys.stderr)
105
- return False
106
-
107
-
108
- def extract_court_decision_text(url):
109
- response = requests.get(url)
110
- soup = BeautifulSoup(response.content, 'html.parser')
111
-
112
- unwanted_texts = [
113
- "Доступ до Реєстру здійснюється в тестовому (обмеженому) режимі.",
114
- "З метою упередження перешкоджанню стабільній роботі Реєстру"
115
- ]
116
-
117
- decision_text = ""
118
- for paragraph in soup.find_all('p'):
119
- text = paragraph.get_text(separator="\n").strip()
120
- if not any(unwanted_text in text for unwanted_text in unwanted_texts):
121
- decision_text += text + "\n"
122
- return decision_text.strip()
123
-
124
-
125
- def generate_legal_position(court_decision_text, user_question):
126
- llm_lp = OpenAI(model="gpt-4o-mini", temperature=0)
127
-
128
- response_format = {
129
- "type": "json_schema",
130
- "json_schema": {
131
- "name": "lp_schema",
132
- "schema": {
133
- "type": "object",
134
- "properties": {
135
- "title": {"type": "string", "description": "Title of the legal position"},
136
- "text": {"type": "string", "description": "Text of the legal position"},
137
- },
138
- "required": ["title", "text"],
139
- "additionalProperties": False
140
- },
141
- "strict": True
142
- }
143
- }
144
-
145
- system_prompt = """
146
- Ви кваліфікований юрист, якому доручено сформулювати правову позицію на основі судового рішення.
147
- """
148
-
149
- prompt = f"""Дотримуйтесь цих інструкцій уважно:
150
-
151
- 1. Спочатку вам буде надано текст судового рішення:
152
-
153
- <court_decision>
154
- {court_decision_text}
155
- </court_decision>
156
-
157
- 2. Уважно прочитайте та проаналізуйте текст судового рішення. Зверніть увагу на:
158
- - Юридичну суть рішення
159
- - Основне правове обґрунтування
160
- - Головні юридичні міркування
161
-
162
- 3. На основі вашого аналізу сформулюйте правову позицію, дотримуючись таких вказівок:
163
- - Будьте чіткими, точними та обґрунтованими
164
- - Використовуйте відповідну юридичну термінологію
165
- - Зберігайте стислість, але повністю передайте суть судового рішення
166
- - Уникайте додаткових пояснень чи коментарів
167
- - Спробуйте узагальнювати та уникати специфічної інформації (наприклад, імен або назв) під час подачі результатів
168
- - Використовуйте лише українську мову
169
-
170
- 4. Окрім правової позиції, створіть короткий заголовок, який відображає основну її думку.
171
-
172
- 5. Відформатуйте вашу відповідь у форматі JSON
173
-
174
- <examples>
175
- {{
176
- "title": "Заголовок правової позиції",
177
- "text": "Текст правової позиції"
178
- }}
179
- </examples>
180
-
181
- Переконайтеся, що ваша відповідь відповідає цьому формату та вказівкам. Надайте лише один JSON-вихід без будь-яких додаткових коментарів.
182
- """
183
-
184
- messages = [
185
- ChatMessage(role="system", content=system_prompt),
186
- ChatMessage(role="user", content=prompt),
187
- ]
188
-
189
- response = llm_lp.chat(messages, response_format=response_format)
190
-
191
- try:
192
- parsed_response = json.loads(response.message.content)
193
- if "title" in parsed_response and "text" in parsed_response:
194
- return parsed_response
195
- else:
196
- return {
197
- "title": "Error: Missing required fields in response",
198
- "text": response.message.content
199
- }
200
-
201
- except json.JSONDecodeError:
202
- return {
203
- "title": "Error parsing response",
204
- "text": response.message.content
205
- }
206
-
207
-
208
- def create_gradio_interface():
209
- with gr.Blocks() as app:
210
- gr.Markdown("# Аналізатор судових рішень на основі правових позицій Верховного Суду")
211
-
212
- with gr.Row():
213
- url_input = gr.Textbox(label="URL судового рішення:")
214
- question_input = gr.Textbox(label="Ваше питання:")
215
-
216
- with gr.Row():
217
- generate_position_button = gr.Button("Генерувати правову позицію")
218
- search_with_ai_button = gr.Button("Пошук із ШІ", interactive=False)
219
-
220
- position_output = gr.Markdown(label="Короткий зміст позиції суду за введеним рішенням")
221
- search_output = gr.Markdown(label="Результат пошуку")
222
- analysis_output = gr.Markdown(label="Результат аналізу")
223
-
224
- state = gr.State()
225
-
226
- async def generate_position_action(url):
227
- try:
228
- court_decision_text = extract_court_decision_text(url)
229
- legal_position_json = generate_legal_position(court_decision_text, "")
230
- position_output_content = f"**Короткий зміст позиції суду за введеним рішенням:**\n *{legal_position_json['title']}*: \n{legal_position_json['text']}\n\n"
231
- return position_output_content, legal_position_json
232
- except Exception as e:
233
- return f"Error during position generation: {str(e)}", None
234
-
235
- async def search_with_ai_action(legal_position_json):
236
- try:
237
- nodes = await retriever_bm25.aretrieve(legal_position_json["text"])
238
- sources_output = "\n **Результати пошуку (наявні правові позиції ВСУ):** \n\n"
239
- for index, node in enumerate(nodes, start=1):
240
- source_title = node.node.metadata.get('title', 'Невідомий заголовок')
241
- doc_ids = node.node.metadata.get('doc_id')
242
- links = get_links_html(doc_ids)
243
- sources_output += f"\n[{index}] *{source_title}* 👉 Score: {node.score} {links}\n"
244
-
245
- return sources_output
246
- except Exception as e:
247
- return f"Error during search: {str(e)}"
248
-
249
- generate_position_button.click(fn=generate_position_action, inputs=url_input, outputs=[position_output, state])
250
- generate_position_button.click(fn=lambda: gr.update(interactive=True), inputs=None,
251
- outputs=search_with_ai_button)
252
- search_with_ai_button.click(fn=search_with_ai_action, inputs=state, outputs=search_output)
253
-
254
- return app
255
-
256
-
257
- if __name__ == "__main__":
258
- if initialize_components():
259
- print("Components initialized successfully!")
260
- app = create_gradio_interface()
261
- app.launch(share=True)
262
- else:
263
- print("Failed to initialize components. Please check the paths and try again.", file=sys.stderr)
264
- sys.exit(1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -9,4 +9,5 @@ llama-index-llms-openai
9
  gradio
10
  beautifulsoup4
11
  nest-asyncio
12
- boto3
 
 
9
  gradio
10
  beautifulsoup4
11
  nest-asyncio
12
+ boto3
13
+ python-dotenv