Satoc commited on
Commit
7ca4926
·
1 Parent(s): 6e966ed

after big change 20250723

Browse files
OpenAITools/CrinicalTrialTools.py CHANGED
@@ -2,35 +2,64 @@ from langchain_community.agent_toolkits import create_sql_agent
2
  from langchain_openai import ChatOpenAI
3
  from langchain_groq import ChatGroq
4
  from langchain_core.prompts import ChatPromptTemplate
5
- from langchain_core.pydantic_v1 import BaseModel, Field
 
 
 
 
 
6
  import pandas as pd
7
- from pydantic import BaseModel, Field
 
 
8
 
9
  from langchain.text_splitter import RecursiveCharacterTextSplitter
10
  from langchain_community.vectorstores import Chroma
11
- from langchain.embeddings import HuggingFaceEmbeddings
 
 
 
 
 
12
  from langchain_core.runnables import RunnablePassthrough
13
  from langchain_core.output_parsers import StrOutputParser
14
 
15
-
16
-
17
  gpt = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
18
- #agent_gpt_executor = create_sql_agent(gpt, db=db, agent_type="tool-calling", verbose=True)
19
 
20
- ## make database
21
  from langchain_community.utilities import SQLDatabase
22
  from sqlalchemy import create_engine
23
-
24
  from langchain.prompts import ChatPromptTemplate
25
  from langchain.schema import SystemMessage
26
  from langchain_core.prompts import MessagesPlaceholder
27
- #agent_groq_executor = create_sql_agent(llm, db=db, agent_type="tool-calling", verbose=True)
28
 
29
  from OpenAITools.FetchTools import fetch_clinical_trials, fetch_clinical_trials_jp
30
 
31
-
32
-
33
- ## Cancer Name の抽出
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  class ExtractTumorName(BaseModel):
35
  """Extract tumor name from the user's question."""
36
  tumor_name: str = Field(description="Extracted tumor name from the question, or 'None' if no tumor found")
@@ -38,16 +67,12 @@ class ExtractTumorName(BaseModel):
38
  class TumorNameExtractor:
39
  def __init__(self, llm):
40
  self.llm = llm
41
-
42
- # LLMの出力を構造化するための設定
43
  self.structured_llm_extractor = self.llm.with_structured_output(ExtractTumorName)
44
 
45
- # システムプロンプトを設定
46
- self.system_prompt = """あなたは、ユーザーの質問に基づいて腫瘍名を英語で抽出するシステムです。\n
47
- 質問文に腫瘍の種類や名前が含まれている場合、それを英語で返してください。\n
48
- 質問文に腫瘍名がない場合は 'None' と返答してください。"""
49
 
50
- # プロンプトテンプレート
51
  self.grade_prompt = ChatPromptTemplate.from_messages(
52
  [
53
  ("system", self.system_prompt),
@@ -55,20 +80,18 @@ class TumorNameExtractor:
55
  ]
56
  )
57
 
 
58
  def extract_tumor_name(self, question: str) -> str:
59
- """
60
- 腫瘍名を抽出するメソッド。
61
- :param question: 質問文
62
- :return: 抽出された腫瘍名
63
- """
64
- # 質問から腫瘍名を抽出する処理
65
- tumor_extractor = self.grade_prompt | self.structured_llm_extractor
66
- result = tumor_extractor.invoke({"question": question})
67
- return result.tumor_name
68
-
69
- ### 質問変更システム
70
 
71
- # ModifyQuestionの出力形式を定義
72
  class ModifyQuestion(BaseModel):
73
  """Class for modifying a question by inserting NCTID."""
74
  modified_question: str = Field(description="The modified question with the inserted NCTID.")
@@ -76,18 +99,15 @@ class ModifyQuestion(BaseModel):
76
  class QuestionModifier:
77
  def __init__(self, llm):
78
  self.llm = llm
79
-
80
- # LLMの出力を構造化するための設定
81
  self.structured_llm_modifier = self.llm.with_structured_output(ModifyQuestion)
82
 
83
- # システムプロンプトを設定
84
- self.system_prompt = """あなたは、ユーザーの質問に対して適切なNCTIDを挿入して質問を変更するシステムです。\n
85
- 質問文にNCTIDを挿入し、形式に基づいて新しい質問を生成してください。\n
86
- 例えば16歳男性の神経膠腫の患者さんが参加できる臨床治験を教えて下さいという質問に対しては\n
87
- 16歳男性の神経膠腫の患者さんは{nct_id}に参加できますか?と変更して下さい\n
88
- NCTIDは {nct_id} を使用してください。"""
89
 
90
- # プロンプトテンプレート
91
  self.modify_prompt = ChatPromptTemplate.from_messages(
92
  [
93
  ("system", self.system_prompt),
@@ -95,34 +115,27 @@ class QuestionModifier:
95
  ]
96
  )
97
 
 
98
  def modify_question(self, question: str, nct_id: str) -> str:
99
- """
100
- 質問を変更するメソッド。
101
- :param question: 質問文
102
- :param nct_id: NCTID
103
- :return: NCTIDを挿入した新しい質問
104
- """
105
- # 質問を変更するプロセス
106
- question_modifier = self.modify_prompt | self.structured_llm_modifier
107
- result = question_modifier.invoke({"question": question, "nct_id": nct_id})
108
- modify_question = result.modified_question
109
- return modify_question
110
 
111
  class QuestionModifierSecond:
112
  def __init__(self, llm):
113
  self.llm = llm
114
-
115
- # LLMの出力を構造化するための設定
116
  self.structured_llm_modifier = self.llm.with_structured_output(ModifyQuestion)
117
 
118
- # システムプロンプトを設定
119
- self.system_prompt = """あなたは、ユーザーの質問を変更するシステムです。\n
120
- 形式に基づいて新しい質問を生成してください。\n
121
- 例えば16歳男性の神経膠腫の患者さんが参加できる臨床治験を教えて下さいという質問に対しては\n
122
- 16歳男性の神経膠腫の患者さんはlこの治験に参加できますか?と変更して下さい\n
123
- """
124
 
125
- # プロンプトテンプレート
126
  self.modify_prompt = ChatPromptTemplate.from_messages(
127
  [
128
  ("system", self.system_prompt),
@@ -130,34 +143,27 @@ class QuestionModifierSecond:
130
  ]
131
  )
132
 
 
133
  def modify_question(self, question: str) -> str:
134
- """
135
- 質問を変更するメソッド。
136
- :param question: 質問文
137
- :param nct_id: NCTID
138
- :return: NCTIDを挿入した新しい質問
139
- """
140
- # 質問を変更するプロセス
141
- question_modifier = self.modify_prompt | self.structured_llm_modifier
142
- result = question_modifier.invoke({"question": question})
143
- modify_question = result.modified_question
144
- return modify_question
145
-
146
  class QuestionModifierEnglish:
147
  def __init__(self, llm):
148
  self.llm = llm
149
-
150
- # LLMの出力を構造化するための設定
151
  self.structured_llm_modifier = self.llm.with_structured_output(ModifyQuestion)
152
 
153
- # システムプロンプトを設定
154
- self.system_prompt = """あなたは、ユーザーの質問を変更し英語に翻訳するシステムです。\n
155
- 形式に基づいて新しい質問を生成してください。\n
156
- 例えば16歳男性の神経膠腫の患者さんが参加できる臨床治験を教えて下さいという質問に対しては\n
157
- Can a 16 year old male patient with glioma participate in this clinical trial?と変更して下さい\n
158
- """
159
 
160
- # プロンプトテンプレート
161
  self.modify_prompt = ChatPromptTemplate.from_messages(
162
  [
163
  ("system", self.system_prompt),
@@ -165,41 +171,34 @@ class QuestionModifierEnglish:
165
  ]
166
  )
167
 
 
168
  def modify_question(self, question: str) -> str:
169
- """
170
- 質問を変更するメソッド。
171
- :param question: 質問文
172
- :param nct_id: NCTID
173
- :return: NCTIDを挿入した新しい質問
174
- """
175
- # 質問を変更するプロセス
176
- question_modifier = self.modify_prompt | self.structured_llm_modifier
177
- result = question_modifier.invoke({"question": question})
178
- modify_question = result.modified_question
179
- return modify_question
180
-
181
-
182
- ### Make criteria check Agent
183
 
 
184
  class ClinicalTrialAgent:
185
  def __init__(self, llm, db):
186
  self.llm = llm
187
  self.db = db
188
 
189
- # システムプロンプトの定義
190
  self.system_prompt = """
191
  あなたは患者さんに適した治験を探すエージェントです。
192
  データベースのEligibility Criteriaをチェックして患者さんがその治験を受けることが可能かどうか答えて下さい
193
  """
194
 
195
- # プロンプトテンプレートを作成
196
  self.prompt = ChatPromptTemplate.from_messages(
197
  [("system", self.system_prompt),
198
  ("human", "{input}"),
199
  MessagesPlaceholder("agent_scratchpad")]
200
  )
201
 
202
- # SQL Agentの設定
203
  self.agent_executor = self.create_sql_agent(self.llm, self.db, self.prompt)
204
 
205
  def create_sql_agent(self, llm, db, prompt):
@@ -213,59 +212,56 @@ class ClinicalTrialAgent:
213
  )
214
  return agent_executor
215
 
 
216
  def get_agent_judgment(self, modify_question: str) -> str:
217
- """
218
- Modifyされた質問を元に、患者さんが治験に参加可能かどうかのエージェント判断を取得。
219
- :param modify_question: NCTIDが挿入された質問
220
- :return: エージェントの判断 (AgentJudgment)
221
- """
222
- # LLMに質問を投げて、判断を得る
223
- result = self.agent_executor.invoke({"input": modify_question})
224
- return result
225
-
226
 
227
  class SimpleClinicalTrialAgent:
228
  def __init__(self, llm):
229
  self.llm = llm
230
 
 
231
  def evaluate_eligibility(self, TargetCriteria: str, question: str) -> str:
232
- """
233
- 臨床試験の参加適格性を評価するメソッド。
234
- :param TargetCriteria: 試験基準 (Inclusion/Exclusion criteria)
235
- :param question: 患者の条件に関する質問
236
- :return: 臨床試験に参加可能かどうかのLLMからの応答
237
- """
238
-
239
- # プロンプトの定義
240
- prompt_template = """
241
- You are an agent looking for a suitable clinical trial for a patient.
242
- Please answer whether the patient is eligible for this clinical trial based on the following criteria. If you do not know the answer, say you do not know. Your answer should be brief, no more than 3 sentences.
243
- Question: {question}
244
- Criteria:
245
- """ + TargetCriteria
246
-
247
- # プロンプトテンプレートの作成
248
- criteria_prompt = ChatPromptTemplate.from_messages(
249
- [
250
- (
251
- "human",
252
- prompt_template
253
- )
254
- ]
255
- )
256
-
257
- # RAGチェーンの作成
258
- rag_chain = (
259
- {"question": RunnablePassthrough()}
260
- | criteria_prompt
261
- | self.llm
262
- | StrOutputParser()
263
- )
264
-
265
- # 質問をチェーンに渡して、応答を得る
266
- response = rag_chain.invoke(question)
267
- return response
268
-
269
 
270
  ### output 評価システム
271
  class TrialEligibilityGrader(BaseModel):
@@ -277,18 +273,14 @@ class TrialEligibilityGrader(BaseModel):
277
  class GraderAgent:
278
  def __init__(self, llm):
279
  self.llm = llm
280
-
281
- # LLMの出力を構造化するための設定
282
  self.structured_llm_grader = self.llm.with_structured_output(TrialEligibilityGrader)
283
 
284
- # Graderの入力プロンプト
285
  self.system_prompt = """
286
  あなたは治験に参加する患者の適合性を評価するGraderです。
287
  以下のドキュメントを読み、患者が治験に参加可能かどうかを判断してください。
288
  'yes'(参加可能)、'no'(参加不可能)、'unclear'(判断できない)の3値で答えてください。
289
  """
290
 
291
- # 評価のためのプロンプトを作成
292
  self.grade_prompt = ChatPromptTemplate.from_messages(
293
  [
294
  ("system", self.system_prompt),
@@ -299,34 +291,31 @@ class GraderAgent:
299
  ]
300
  )
301
 
 
302
  def evaluate_eligibility(self, AgentJudgment_output: str) -> str:
303
- """
304
- AgentJudgment['output']を基に患者が治験に参加可能かどうかを評価し、スコア(AgentGrade)を返す。
305
- :param AgentJudgment_output: エージェント判断の 'output' の値
306
- :return: 評価されたスコア (AgentGrade)
307
- """
308
- GraderAgent = self.grade_prompt | self.structured_llm_grader
309
- result = GraderAgent.invoke({"document": AgentJudgment_output})
310
- AgentGrade = result.score
311
- return AgentGrade
312
-
313
- import re
314
 
315
  class LLMTranslator:
316
  def __init__(self, llm):
317
  self.llm = llm
318
  self.structured_llm_modifier = self.llm.with_structured_output(ModifyQuestion)
319
 
320
- self.system_prompt = """あなたは、優秀な翻訳者です。\n
321
- 日本語を英語に翻訳して下さい。\n
322
- """
323
- self.system_prompt2 = """あなたは、優秀な翻訳者です。\n
324
- 日本語を英語に以下のフォーマットに従って翻訳して下さい。\n
325
- MainQuestion:
326
- Known gene mutation:
327
- Measurable tumour:
328
- Biopsiable tumour:
329
- """
330
 
331
  self.modify_prompt = ChatPromptTemplate.from_messages(
332
  [
@@ -343,81 +332,123 @@ class LLMTranslator:
343
  )
344
 
345
  def is_english(self, text: str) -> bool:
346
- """
347
- 簡易的にテキストが英語かどうかを判定する関数
348
- :param text: 判定するテキスト
349
- :return: 英語の場合True、日本語の場合False
350
- """
351
- # 英語のアルファベットが多く含まれているかを確認
352
  return bool(re.match(r'^[A-Za-z0-9\s.,?!]+$', text))
353
 
 
354
  def translate(self, question: str) -> str:
355
- """
356
- 質問を翻訳するメソッド。英語の質問はそのまま返す。
357
- :param question: 質問文
358
- :return: 翻訳済みの質問文、または元の質問文(英語の場合)
359
- """
360
- # 質問が英語の場合、そのまま返す
361
- if self.is_english(question):
 
 
 
362
  return question
363
-
364
- # 日本語の質問は翻訳プロセスにかける
365
- question_modifier = self.modify_prompt | self.structured_llm_modifier
366
- result = question_modifier.invoke({"question": question})
367
- modify_question = result.modified_question
368
- return modify_question
369
-
370
  def translateQuestion(self, question: str) -> str:
371
- """
372
- フォーマット付きで質問を翻訳するメソッド。
373
- :param question: 質問文
374
- :return: フォーマットに従った翻訳済みの質問
375
- """
376
- question_modifier = self.modify_prompt2 | self.structured_llm_modifier
377
- result = question_modifier.invoke({"question": question})
378
- modify_question = result.modified_question
379
- return modify_question
380
 
381
  def generate_ex_question(age, sex, tumor_type, GeneMutation, Meseable, Biopsiable):
382
- # GeneMutationが空の場合はUnknownに設定
383
- gene_mutation_text = GeneMutation if GeneMutation else "Unknown"
384
-
385
- # MeseableとBiopsiableの値をYes, No, Unknownに変換
386
- meseable_text = (
387
- "Yes" if Meseable == "有り" else "No" if Meseable == "無し" else "Unknown"
388
- )
389
- biopsiable_text = (
390
- "Yes" if Biopsiable == "有り" else "No" if Biopsiable == "無し" else "Unknown"
391
- )
392
-
393
- # 質問文の生成
394
- ex_question = f"""{age}歳{sex}の{tumor_type}患者さんはこの治験に参加することができますか?
 
 
395
  判明している遺伝子変異: {gene_mutation_text}
396
  Meseable tumor: {meseable_text}
397
  Biopsiable tumor: {biopsiable_text}
398
- です。
399
- """
400
- return ex_question
 
 
401
 
402
  def generate_ex_question_English(age, sex, tumor_type, GeneMutation, Meseable, Biopsiable):
403
- # GeneMutationが空の場合は"Unknown"に設定
404
- gene_mutation_text = GeneMutation if GeneMutation else "Unknown"
405
-
406
- # sexの値を male または female に変換
407
- sex_text = "male" if sex == "男性" else "female" if sex == "女性" else "Unknown"
408
-
409
- # MeseableとBiopsiableの値を "Yes", "No", "Unknown" に変換
410
- meseable_text = (
411
- "Yes" if Meseable == "有り" else "No" if Meseable == "無し" else "Unknown"
412
- )
413
- biopsiable_text = (
414
- "Yes" if Biopsiable == "有り" else "No" if Biopsiable == "無し" else "Unknown"
415
- )
416
-
417
- # 英語での質問文を生成
418
- ex_question = f"""Can a {age}-year-old {sex_text} patient with {tumor_type} participate in this clinical trial?
 
 
419
  Known gene mutation: {gene_mutation_text}
420
  Measurable tumor: {meseable_text}
421
- Biopsiable tumor: {biopsiable_text}
422
- """
423
- return ex_question
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  from langchain_openai import ChatOpenAI
3
  from langchain_groq import ChatGroq
4
  from langchain_core.prompts import ChatPromptTemplate
5
+ # 修正: pydantic v1の非推奨警告を解決
6
+ try:
7
+ from pydantic import BaseModel, Field
8
+ except ImportError:
9
+ from langchain_core.pydantic_v1 import BaseModel, Field
10
+
11
  import pandas as pd
12
+ import time
13
+ import re
14
+ from typing import Optional
15
 
16
  from langchain.text_splitter import RecursiveCharacterTextSplitter
17
  from langchain_community.vectorstores import Chroma
18
+ # 修正: HuggingFaceEmbeddingsの非推奨警告を解決
19
+ try:
20
+ from langchain_community.embeddings import HuggingFaceEmbeddings
21
+ except ImportError:
22
+ from langchain.embeddings import HuggingFaceEmbeddings
23
+
24
  from langchain_core.runnables import RunnablePassthrough
25
  from langchain_core.output_parsers import StrOutputParser
26
 
27
+ # GPT初期化
 
28
  gpt = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
 
29
 
30
+ ## Database関連のインポート
31
  from langchain_community.utilities import SQLDatabase
32
  from sqlalchemy import create_engine
 
33
  from langchain.prompts import ChatPromptTemplate
34
  from langchain.schema import SystemMessage
35
  from langchain_core.prompts import MessagesPlaceholder
 
36
 
37
  from OpenAITools.FetchTools import fetch_clinical_trials, fetch_clinical_trials_jp
38
 
39
+ # エラーハンドリング用のデコレータ
40
+ def retry_on_error(max_retries=3, delay=1):
41
+ """エラー時のリトライデコレータ"""
42
+ def decorator(func):
43
+ def wrapper(*args, **kwargs):
44
+ for attempt in range(max_retries):
45
+ try:
46
+ return func(*args, **kwargs)
47
+ except Exception as e:
48
+ if attempt < max_retries - 1:
49
+ print(f"エラーが発生しました (試行 {attempt + 1}/{max_retries}): {e}")
50
+ if "no healthy upstream" in str(e) or "InternalServerError" in str(e):
51
+ time.sleep(delay * 2) # サーバーエラーの場合は長めに待機
52
+ else:
53
+ time.sleep(delay)
54
+ continue
55
+ else:
56
+ print(f"最大リトライ回数に達しました: {e}")
57
+ raise e
58
+ return None
59
+ return wrapper
60
+ return decorator
61
+
62
+ ## Cancer Name の抽出
63
  class ExtractTumorName(BaseModel):
64
  """Extract tumor name from the user's question."""
65
  tumor_name: str = Field(description="Extracted tumor name from the question, or 'None' if no tumor found")
 
67
  class TumorNameExtractor:
68
  def __init__(self, llm):
69
  self.llm = llm
 
 
70
  self.structured_llm_extractor = self.llm.with_structured_output(ExtractTumorName)
71
 
72
+ self.system_prompt = """あなたは、ユーザーの質問に基づいて腫瘍名を英語で抽出するシステムです。
73
+ 質問文に腫瘍の種類や名前が含まれている場合、それを英語で返してください。
74
+ 質問文に腫瘍名がない場合は 'None' と返答してください。"""
 
75
 
 
76
  self.grade_prompt = ChatPromptTemplate.from_messages(
77
  [
78
  ("system", self.system_prompt),
 
80
  ]
81
  )
82
 
83
+ @retry_on_error(max_retries=3, delay=2)
84
  def extract_tumor_name(self, question: str) -> str:
85
+ """腫瘍名を抽出するメソッド"""
86
+ try:
87
+ tumor_extractor = self.grade_prompt | self.structured_llm_extractor
88
+ result = tumor_extractor.invoke({"question": question})
89
+ return result.tumor_name
90
+ except Exception as e:
91
+ print(f"腫瘍名抽出エラー: {e}")
92
+ return "None"
 
 
 
93
 
94
+ ### 質問変更システム
95
  class ModifyQuestion(BaseModel):
96
  """Class for modifying a question by inserting NCTID."""
97
  modified_question: str = Field(description="The modified question with the inserted NCTID.")
 
99
  class QuestionModifier:
100
  def __init__(self, llm):
101
  self.llm = llm
 
 
102
  self.structured_llm_modifier = self.llm.with_structured_output(ModifyQuestion)
103
 
104
+ # 修正: 中括弧をエスケープ
105
+ self.system_prompt = """あなたは、ユーザーの質問に対して適切なNCTIDを挿入して質問を変更するシステムです。
106
+ 質問文にNCTIDを挿入し、形式に基づいて新しい質問を生成してください。
107
+ 例えば16歳男性の神経膠腫の患者さんが参加できる臨床治験を教えて下さいという質問に対しては
108
+ 16歳男性の神経膠腫の患者さんは{{nct_id}}に参加できますか?と変更して下さい
109
+ NCTIDは {{nct_id}} を使用してください。"""
110
 
 
111
  self.modify_prompt = ChatPromptTemplate.from_messages(
112
  [
113
  ("system", self.system_prompt),
 
115
  ]
116
  )
117
 
118
+ @retry_on_error(max_retries=3, delay=2)
119
  def modify_question(self, question: str, nct_id: str) -> str:
120
+ """質問を変更するメソッド"""
121
+ try:
122
+ question_modifier = self.modify_prompt | self.structured_llm_modifier
123
+ result = question_modifier.invoke({"question": question, "nct_id": nct_id})
124
+ return result.modified_question
125
+ except Exception as e:
126
+ print(f"質問変更エラー: {e}")
127
+ return f"{question} (NCTID: {nct_id})"
 
 
 
128
 
129
  class QuestionModifierSecond:
130
  def __init__(self, llm):
131
  self.llm = llm
 
 
132
  self.structured_llm_modifier = self.llm.with_structured_output(ModifyQuestion)
133
 
134
+ self.system_prompt = """あなたは、ユーザーの質問を変更するシステムです。
135
+ 形式に基づいて新しい質問を生成してください。
136
+ 例えば16歳男性の神経膠腫の患者さんが参加できる臨床治験を教えて下さいという質問に対しては
137
+ 16歳男性の神経膠腫の患者さんはこの治験に参加できますか?と変更して下さい"""
 
 
138
 
 
139
  self.modify_prompt = ChatPromptTemplate.from_messages(
140
  [
141
  ("system", self.system_prompt),
 
143
  ]
144
  )
145
 
146
+ @retry_on_error(max_retries=3, delay=2)
147
  def modify_question(self, question: str) -> str:
148
+ """質問を変更するメソッド"""
149
+ try:
150
+ question_modifier = self.modify_prompt | self.structured_llm_modifier
151
+ result = question_modifier.invoke({"question": question})
152
+ return result.modified_question
153
+ except Exception as e:
154
+ print(f"質問変更エラー: {e}")
155
+ return question
156
+
 
 
 
157
  class QuestionModifierEnglish:
158
  def __init__(self, llm):
159
  self.llm = llm
 
 
160
  self.structured_llm_modifier = self.llm.with_structured_output(ModifyQuestion)
161
 
162
+ self.system_prompt = """あなたは、ユーザーの質問を変更し英語に翻訳するシステムです。
163
+ 形式に基づいて新しい質問を生成してください。
164
+ 例えば16歳男性の神経膠腫の患者さんが参加できる臨床治験を教えて下さいという質問に対しては
165
+ Can a 16 year old male patient with glioma participate in this clinical trial?と変更して下さい"""
 
 
166
 
 
167
  self.modify_prompt = ChatPromptTemplate.from_messages(
168
  [
169
  ("system", self.system_prompt),
 
171
  ]
172
  )
173
 
174
+ @retry_on_error(max_retries=3, delay=2)
175
  def modify_question(self, question: str) -> str:
176
+ """質問を変更するメソッド"""
177
+ try:
178
+ question_modifier = self.modify_prompt | self.structured_llm_modifier
179
+ result = question_modifier.invoke({"question": question})
180
+ return result.modified_question
181
+ except Exception as e:
182
+ print(f"英語質問変更エラー: {e}")
183
+ return question
 
 
 
 
 
 
184
 
185
+ ### Make criteria check Agent
186
  class ClinicalTrialAgent:
187
  def __init__(self, llm, db):
188
  self.llm = llm
189
  self.db = db
190
 
 
191
  self.system_prompt = """
192
  あなたは患者さんに適した治験を探すエージェントです。
193
  データベースのEligibility Criteriaをチェックして患者さんがその治験を受けることが可能かどうか答えて下さい
194
  """
195
 
 
196
  self.prompt = ChatPromptTemplate.from_messages(
197
  [("system", self.system_prompt),
198
  ("human", "{input}"),
199
  MessagesPlaceholder("agent_scratchpad")]
200
  )
201
 
 
202
  self.agent_executor = self.create_sql_agent(self.llm, self.db, self.prompt)
203
 
204
  def create_sql_agent(self, llm, db, prompt):
 
212
  )
213
  return agent_executor
214
 
215
+ @retry_on_error(max_retries=3, delay=2)
216
  def get_agent_judgment(self, modify_question: str) -> str:
217
+ """Modifyされた質問を元に、患者さんが治験に参加可能かどうかのエージェント判断を取得"""
218
+ try:
219
+ result = self.agent_executor.invoke({"input": modify_question})
220
+ return result
221
+ except Exception as e:
222
+ print(f"エージェント判断エラー: {e}")
223
+ return f"エラー: {str(e)}"
 
 
224
 
225
  class SimpleClinicalTrialAgent:
226
  def __init__(self, llm):
227
  self.llm = llm
228
 
229
+ @retry_on_error(max_retries=3, delay=2)
230
  def evaluate_eligibility(self, TargetCriteria: str, question: str) -> str:
231
+ """臨床試験の参加適格性を評価するメソッド"""
232
+ try:
233
+ # 修正: プロンプト内の中括弧を適切にエスケープ
234
+ prompt_template = """
235
+ You are an agent looking for a suitable clinical trial for a patient.
236
+ Please answer whether the patient is eligible for this clinical trial based on the following criteria. If you do not know the answer, say you do not know. Your answer should be brief, no more than 3 sentences.
237
+
238
+ Question: {{question}}
239
+
240
+ Criteria:
241
+ {criteria}""".format(criteria=TargetCriteria)
242
+
243
+ criteria_prompt = ChatPromptTemplate.from_messages(
244
+ [
245
+ (
246
+ "human",
247
+ prompt_template
248
+ )
249
+ ]
250
+ )
251
+
252
+ rag_chain = (
253
+ {"question": RunnablePassthrough()}
254
+ | criteria_prompt
255
+ | self.llm
256
+ | StrOutputParser()
257
+ )
258
+
259
+ response = rag_chain.invoke(question)
260
+ return response
261
+
262
+ except Exception as e:
263
+ print(f"適格性評価エラー: {e}")
264
+ return f"評価エラー: {str(e)}"
 
 
 
265
 
266
  ### output 評価システム
267
  class TrialEligibilityGrader(BaseModel):
 
273
  class GraderAgent:
274
  def __init__(self, llm):
275
  self.llm = llm
 
 
276
  self.structured_llm_grader = self.llm.with_structured_output(TrialEligibilityGrader)
277
 
 
278
  self.system_prompt = """
279
  あなたは治験に参加する患者の適合性を評価するGraderです。
280
  以下のドキュメントを読み、患者が治験に参加可能かどうかを判断してください。
281
  'yes'(参加可能)、'no'(参加不可能)、'unclear'(判断できない)の3値で答えてください。
282
  """
283
 
 
284
  self.grade_prompt = ChatPromptTemplate.from_messages(
285
  [
286
  ("system", self.system_prompt),
 
291
  ]
292
  )
293
 
294
+ @retry_on_error(max_retries=3, delay=2)
295
  def evaluate_eligibility(self, AgentJudgment_output: str) -> str:
296
+ """AgentJudgment['output']を基に患者が治験に参加可能かどうかを評価し、スコア(AgentGrade)を返す"""
297
+ try:
298
+ GraderAgent = self.grade_prompt | self.structured_llm_grader
299
+ result = GraderAgent.invoke({"document": AgentJudgment_output})
300
+ return result.score
301
+ except Exception as e:
302
+ print(f"グレード評価エラー: {e}")
303
+ return "unclear"
 
 
 
304
 
305
  class LLMTranslator:
306
  def __init__(self, llm):
307
  self.llm = llm
308
  self.structured_llm_modifier = self.llm.with_structured_output(ModifyQuestion)
309
 
310
+ self.system_prompt = """あなたは、優秀な翻訳者です。
311
+ 日本語を英語に翻訳して下さい。"""
312
+
313
+ self.system_prompt2 = """あなたは、優秀な翻訳者です。
314
+ 日本語を英語に以下のフォーマットに従って翻訳して下さい。
315
+ MainQuestion:
316
+ Known gene mutation:
317
+ Measurable tumour:
318
+ Biopsiable tumour:"""
 
319
 
320
  self.modify_prompt = ChatPromptTemplate.from_messages(
321
  [
 
332
  )
333
 
334
  def is_english(self, text: str) -> bool:
335
+ """簡易的にテキストが英語かどうかを判定する関数"""
 
 
 
 
 
336
  return bool(re.match(r'^[A-Za-z0-9\s.,?!]+$', text))
337
 
338
+ @retry_on_error(max_retries=3, delay=2)
339
  def translate(self, question: str) -> str:
340
+ """質問を翻訳するメソッド。英語の質問はそのまま返す。"""
341
+ try:
342
+ if self.is_english(question):
343
+ return question
344
+
345
+ question_modifier = self.modify_prompt | self.structured_llm_modifier
346
+ result = question_modifier.invoke({"question": question})
347
+ return result.modified_question
348
+ except Exception as e:
349
+ print(f"翻訳エラー: {e}")
350
  return question
351
+
352
+ @retry_on_error(max_retries=3, delay=2)
 
 
 
 
 
353
  def translateQuestion(self, question: str) -> str:
354
+ """フォーマット付きで質問を翻訳するメソッド"""
355
+ try:
356
+ question_modifier = self.modify_prompt2 | self.structured_llm_modifier
357
+ result = question_modifier.invoke({"question": question})
358
+ return result.modified_question
359
+ except Exception as e:
360
+ print(f"フォーマット翻訳エラー: {e}")
361
+ return question
 
362
 
363
  def generate_ex_question(age, sex, tumor_type, GeneMutation, Meseable, Biopsiable):
364
+ """日本語での質問文を生成"""
365
+ try:
366
+ # GeneMutationが空の場合はUnknownに設定
367
+ gene_mutation_text = GeneMutation if GeneMutation else "Unknown"
368
+
369
+ # MeseableとBiopsiableの値をYes, No, Unknownに変換
370
+ meseable_text = (
371
+ "Yes" if Meseable == "有り" else "No" if Meseable == "無し" else "Unknown"
372
+ )
373
+ biopsiable_text = (
374
+ "Yes" if Biopsiable == "有り" else "No" if Biopsiable == "無し" else "Unknown"
375
+ )
376
+
377
+ # 質問文の生成
378
+ ex_question = f"""{age}歳{sex}の{tumor_type}患者さんはこの治験に参加することができますか?
379
  判明している遺伝子変異: {gene_mutation_text}
380
  Meseable tumor: {meseable_text}
381
  Biopsiable tumor: {biopsiable_text}
382
+ です。"""
383
+ return ex_question
384
+ except Exception as e:
385
+ print(f"日本語質問生成エラー: {e}")
386
+ return f"{age}歳{sex}の{tumor_type}患者さんの治験参加について"
387
 
388
  def generate_ex_question_English(age, sex, tumor_type, GeneMutation, Meseable, Biopsiable):
389
+ """英語での質問文を生成"""
390
+ try:
391
+ # GeneMutationが空の場合は"Unknown"に設定
392
+ gene_mutation_text = GeneMutation if GeneMutation else "Unknown"
393
+
394
+ # sexの値を male または female に変換
395
+ sex_text = "male" if sex == "男性" else "female" if sex == "女性" else "Unknown"
396
+
397
+ # MeseableとBiopsiableの値を "Yes", "No", "Unknown" に変換
398
+ meseable_text = (
399
+ "Yes" if Meseable == "有り" else "No" if Meseable == "無し" else "Unknown"
400
+ )
401
+ biopsiable_text = (
402
+ "Yes" if Biopsiable == "有り" else "No" if Biopsiable == "無し" else "Unknown"
403
+ )
404
+
405
+ # 英語での質問文を生成
406
+ ex_question = f"""Can a {age}-year-old {sex_text} patient with {tumor_type} participate in this clinical trial?
407
  Known gene mutation: {gene_mutation_text}
408
  Measurable tumor: {meseable_text}
409
+ Biopsiable tumor: {biopsiable_text}"""
410
+ return ex_question
411
+ except Exception as e:
412
+ print(f"英語質問生成エラー: {e}")
413
+ return f"Can a {age}-year-old patient with {tumor_type} participate in this clinical trial?"
414
+
415
+ # テスト関数
416
+ def test_clinical_trial_tools():
417
+ """臨床試験ツールのテスト関数"""
418
+ try:
419
+ from langchain_groq import ChatGroq
420
+
421
+ # Groqクライアントの初期化
422
+ groq = ChatGroq(model_name="llama3-70b-8192", temperature=0)
423
+
424
+ # 各エージェントの初期化テスト
425
+ translator = LLMTranslator(groq)
426
+ criteria_agent = SimpleClinicalTrialAgent(groq)
427
+ grader_agent = GraderAgent(groq)
428
+
429
+ print("✅ 全てのエージェントが正常に初期化されました")
430
+
431
+ # サンプル質問の生成テスト
432
+ sample_question = generate_ex_question_English(
433
+ age="45",
434
+ sex="女性",
435
+ tumor_type="breast cancer",
436
+ GeneMutation="HER2",
437
+ Meseable="有り",
438
+ Biopsiable="有り"
439
+ )
440
+
441
+ print(f"✅ サンプル質問生成成功: {sample_question}")
442
+ return True
443
+
444
+ except Exception as e:
445
+ print(f"❌ テスト中にエラーが発生しました: {e}")
446
+ return False
447
+
448
+ if __name__ == "__main__":
449
+ print("ClinicalTrialTools のテストを開始します...")
450
+ success = test_clinical_trial_tools()
451
+ if success:
452
+ print("✅ テストが正常に完了しました。")
453
+ else:
454
+ print("❌ テストでエラーが発生しました。")
OpenAITools/CrinicalTrialTools_old.py ADDED
@@ -0,0 +1,423 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_community.agent_toolkits import create_sql_agent
2
+ from langchain_openai import ChatOpenAI
3
+ from langchain_groq import ChatGroq
4
+ from langchain_core.prompts import ChatPromptTemplate
5
+ from langchain_core.pydantic_v1 import BaseModel, Field
6
+ import pandas as pd
7
+ from pydantic import BaseModel, Field
8
+
9
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
10
+ from langchain_community.vectorstores import Chroma
11
+ from langchain.embeddings import HuggingFaceEmbeddings
12
+ from langchain_core.runnables import RunnablePassthrough
13
+ from langchain_core.output_parsers import StrOutputParser
14
+
15
+
16
+
17
+ gpt = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
18
+ #agent_gpt_executor = create_sql_agent(gpt, db=db, agent_type="tool-calling", verbose=True)
19
+
20
+ ## make database
21
+ from langchain_community.utilities import SQLDatabase
22
+ from sqlalchemy import create_engine
23
+
24
+ from langchain.prompts import ChatPromptTemplate
25
+ from langchain.schema import SystemMessage
26
+ from langchain_core.prompts import MessagesPlaceholder
27
+ #agent_groq_executor = create_sql_agent(llm, db=db, agent_type="tool-calling", verbose=True)
28
+
29
+ from OpenAITools.FetchTools import fetch_clinical_trials, fetch_clinical_trials_jp
30
+
31
+
32
+
33
+ ## Cancer Name の抽出
34
+ class ExtractTumorName(BaseModel):
35
+ """Extract tumor name from the user's question."""
36
+ tumor_name: str = Field(description="Extracted tumor name from the question, or 'None' if no tumor found")
37
+
38
+ class TumorNameExtractor:
39
+ def __init__(self, llm):
40
+ self.llm = llm
41
+
42
+ # LLMの出力を構造化するための設定
43
+ self.structured_llm_extractor = self.llm.with_structured_output(ExtractTumorName)
44
+
45
+ # システムプロンプトを設定
46
+ self.system_prompt = """あなたは、ユーザーの質問に基づいて腫瘍名を英語で抽出するシステムです。\n
47
+ 質問文に腫瘍の種類や名前が含まれている場合、それを英語で返してください。\n
48
+ 質問文に腫瘍名がない場合は 'None' と返答してください。"""
49
+
50
+ # プロンプトテンプレート
51
+ self.grade_prompt = ChatPromptTemplate.from_messages(
52
+ [
53
+ ("system", self.system_prompt),
54
+ ("human", "ユーザーの質問: {question}"),
55
+ ]
56
+ )
57
+
58
+ def extract_tumor_name(self, question: str) -> str:
59
+ """
60
+ 腫瘍名を抽出するメソッド。
61
+ :param question: 質問文
62
+ :return: 抽出された腫瘍名
63
+ """
64
+ # 質問から腫瘍名を抽出する処理
65
+ tumor_extractor = self.grade_prompt | self.structured_llm_extractor
66
+ result = tumor_extractor.invoke({"question": question})
67
+ return result.tumor_name
68
+
69
+ ### 質問変更システム
70
+
71
+ # ModifyQuestionの出力形式を定義
72
+ class ModifyQuestion(BaseModel):
73
+ """Class for modifying a question by inserting NCTID."""
74
+ modified_question: str = Field(description="The modified question with the inserted NCTID.")
75
+
76
+ class QuestionModifier:
77
+ def __init__(self, llm):
78
+ self.llm = llm
79
+
80
+ # LLMの出力を構造化するための設定
81
+ self.structured_llm_modifier = self.llm.with_structured_output(ModifyQuestion)
82
+
83
+ # システムプロンプトを設定
84
+ self.system_prompt = """あなたは、ユーザーの質問に対して適切なNCTIDを挿入して質問を変更するシステムです。\n
85
+ 質問文にNCTIDを挿入し、形式に基づいて新しい質問を生成してください。\n
86
+ 例えば16歳男性の神経膠腫の患者さんが参加できる臨床治験を教えて下さいという質問に対しては\n
87
+ 16歳男性の神経膠腫の患者さんは{nct_id}に参加できますか?と変更して下さい\n
88
+ NCTIDは {nct_id} を使用してください。"""
89
+
90
+ # プロンプトテンプレート
91
+ self.modify_prompt = ChatPromptTemplate.from_messages(
92
+ [
93
+ ("system", self.system_prompt),
94
+ ("human", "ユーザーの質問: {question}"),
95
+ ]
96
+ )
97
+
98
+ def modify_question(self, question: str, nct_id: str) -> str:
99
+ """
100
+ 質問を変更するメソッド。
101
+ :param question: 質問文
102
+ :param nct_id: NCTID
103
+ :return: NCTIDを挿入した新しい質問
104
+ """
105
+ # 質問を変更するプロセス
106
+ question_modifier = self.modify_prompt | self.structured_llm_modifier
107
+ result = question_modifier.invoke({"question": question, "nct_id": nct_id})
108
+ modify_question = result.modified_question
109
+ return modify_question
110
+
111
+ class QuestionModifierSecond:
112
+ def __init__(self, llm):
113
+ self.llm = llm
114
+
115
+ # LLMの出力を構造化するための設定
116
+ self.structured_llm_modifier = self.llm.with_structured_output(ModifyQuestion)
117
+
118
+ # システムプロンプトを設定
119
+ self.system_prompt = """あなたは、ユーザーの質問を変更するシステムです。\n
120
+ 形式に基づいて新しい質問を生成してください。\n
121
+ 例えば16歳男性の神経膠腫の患者さんが参加できる臨床治験を教えて下さいという質問に対しては\n
122
+ 16歳男性の神経膠腫の患者さんはlこの治験に参加できますか?と変更して下さい\n
123
+ """
124
+
125
+ # プロンプトテンプレート
126
+ self.modify_prompt = ChatPromptTemplate.from_messages(
127
+ [
128
+ ("system", self.system_prompt),
129
+ ("human", "ユーザーの質問: {question}"),
130
+ ]
131
+ )
132
+
133
+ def modify_question(self, question: str) -> str:
134
+ """
135
+ 質問を変更するメソッド。
136
+ :param question: 質問文
137
+ :param nct_id: NCTID
138
+ :return: NCTIDを挿入した新しい質問
139
+ """
140
+ # 質問を変更するプロセス
141
+ question_modifier = self.modify_prompt | self.structured_llm_modifier
142
+ result = question_modifier.invoke({"question": question})
143
+ modify_question = result.modified_question
144
+ return modify_question
145
+
146
+ class QuestionModifierEnglish:
147
+ def __init__(self, llm):
148
+ self.llm = llm
149
+
150
+ # LLMの出力を構造化するための設定
151
+ self.structured_llm_modifier = self.llm.with_structured_output(ModifyQuestion)
152
+
153
+ # システムプロンプトを設定
154
+ self.system_prompt = """あなたは、ユーザーの質問を変更し英語に翻訳するシステムです。\n
155
+ 形式に基づいて新しい質問を生成してください。\n
156
+ 例えば16歳男性の神経膠腫の患者さんが参加できる臨床治験を教えて下さいという質問に対しては\n
157
+ Can a 16 year old male patient with glioma participate in this clinical trial?と変更して下さい\n
158
+ """
159
+
160
+ # プロンプトテンプレート
161
+ self.modify_prompt = ChatPromptTemplate.from_messages(
162
+ [
163
+ ("system", self.system_prompt),
164
+ ("human", "ユーザーの質問: {question}"),
165
+ ]
166
+ )
167
+
168
+ def modify_question(self, question: str) -> str:
169
+ """
170
+ 質問を変更するメソッド。
171
+ :param question: 質問文
172
+ :param nct_id: NCTID
173
+ :return: NCTIDを挿入した新しい質問
174
+ """
175
+ # 質問を変更するプロセス
176
+ question_modifier = self.modify_prompt | self.structured_llm_modifier
177
+ result = question_modifier.invoke({"question": question})
178
+ modify_question = result.modified_question
179
+ return modify_question
180
+
181
+
182
+ ### Make criteria check Agent
183
+
184
+ class ClinicalTrialAgent:
185
+ def __init__(self, llm, db):
186
+ self.llm = llm
187
+ self.db = db
188
+
189
+ # システムプロンプトの定義
190
+ self.system_prompt = """
191
+ あなたは患者さんに適した治験を探すエージェントです。
192
+ データベースのEligibility Criteriaをチェックして患者さんがその治験を受けることが可能かどうか答えて下さい
193
+ """
194
+
195
+ # プロンプトテンプレートを作成
196
+ self.prompt = ChatPromptTemplate.from_messages(
197
+ [("system", self.system_prompt),
198
+ ("human", "{input}"),
199
+ MessagesPlaceholder("agent_scratchpad")]
200
+ )
201
+
202
+ # SQL Agentの設定
203
+ self.agent_executor = self.create_sql_agent(self.llm, self.db, self.prompt)
204
+
205
+ def create_sql_agent(self, llm, db, prompt):
206
+ """SQLエージェントを作成するメソッド"""
207
+ agent_executor = create_sql_agent(
208
+ llm,
209
+ db=db,
210
+ prompt=prompt,
211
+ agent_type="tool-calling",
212
+ verbose=True
213
+ )
214
+ return agent_executor
215
+
216
+ def get_agent_judgment(self, modify_question: str) -> str:
217
+ """
218
+ Modifyされた質問を元に、患者さんが治験に参加可能かどうかのエージェント判断を取得。
219
+ :param modify_question: NCTIDが挿入された質問
220
+ :return: エージェントの判断 (AgentJudgment)
221
+ """
222
+ # LLMに質問を投げて、判断を得る
223
+ result = self.agent_executor.invoke({"input": modify_question})
224
+ return result
225
+
226
+
227
+ class SimpleClinicalTrialAgent:
228
+ def __init__(self, llm):
229
+ self.llm = llm
230
+
231
+ def evaluate_eligibility(self, TargetCriteria: str, question: str) -> str:
232
+ """
233
+ 臨床試験の参加適格性を評価するメソッド。
234
+ :param TargetCriteria: 試験基準 (Inclusion/Exclusion criteria)
235
+ :param question: 患者の条件に関する質問
236
+ :return: 臨床試験に参加可能かどうかのLLMからの応答
237
+ """
238
+
239
+ # プロンプトの定義
240
+ prompt_template = """
241
+ You are an agent looking for a suitable clinical trial for a patient.
242
+ Please answer whether the patient is eligible for this clinical trial based on the following criteria. If you do not know the answer, say you do not know. Your answer should be brief, no more than 3 sentences.
243
+ Question: {question}
244
+ Criteria:
245
+ """ + TargetCriteria
246
+
247
+ # プロンプトテンプレートの作成
248
+ criteria_prompt = ChatPromptTemplate.from_messages(
249
+ [
250
+ (
251
+ "human",
252
+ prompt_template
253
+ )
254
+ ]
255
+ )
256
+
257
+ # RAGチェーンの作成
258
+ rag_chain = (
259
+ {"question": RunnablePassthrough()}
260
+ | criteria_prompt
261
+ | self.llm
262
+ | StrOutputParser()
263
+ )
264
+
265
+ # 質問をチェーンに渡して、応答を得る
266
+ response = rag_chain.invoke(question)
267
+ return response
268
+
269
+
270
+ ### output 評価システム
271
+ class TrialEligibilityGrader(BaseModel):
272
+ """3値評価: yes, no, unclear"""
273
+ score: str = Field(
274
+ description="The eligibility of the patient for the clinical trial based on the document. Options are: 'yes', 'no', or 'unclear'."
275
+ )
276
+
277
+ class GraderAgent:
278
+ def __init__(self, llm):
279
+ self.llm = llm
280
+
281
+ # LLMの出力を構造化するための設定
282
+ self.structured_llm_grader = self.llm.with_structured_output(TrialEligibilityGrader)
283
+
284
+ # Graderの入力プロンプト
285
+ self.system_prompt = """
286
+ あなたは治験に参加する患者の適合性を評価するGraderです。
287
+ 以下のドキュメントを読み、患者が治験に参加可能かどうかを判断してください。
288
+ 'yes'(参加可能)、'no'(参加不可能)、'unclear'(判断できない)の3値で答えてください。
289
+ """
290
+
291
+ # 評価のためのプロンプトを作成
292
+ self.grade_prompt = ChatPromptTemplate.from_messages(
293
+ [
294
+ ("system", self.system_prompt),
295
+ (
296
+ "human",
297
+ "取得したドキュメント: \n\n {document} ",
298
+ ),
299
+ ]
300
+ )
301
+
302
+ def evaluate_eligibility(self, AgentJudgment_output: str) -> str:
303
+ """
304
+ AgentJudgment['output']を基に患者が治験に参加可能かどうかを評価し、スコア(AgentGrade)を返す。
305
+ :param AgentJudgment_output: エージェント判断の 'output' の値
306
+ :return: 評価されたスコア (AgentGrade)
307
+ """
308
+ GraderAgent = self.grade_prompt | self.structured_llm_grader
309
+ result = GraderAgent.invoke({"document": AgentJudgment_output})
310
+ AgentGrade = result.score
311
+ return AgentGrade
312
+
313
+ import re
314
+
315
+ class LLMTranslator:
316
+ def __init__(self, llm):
317
+ self.llm = llm
318
+ self.structured_llm_modifier = self.llm.with_structured_output(ModifyQuestion)
319
+
320
+ self.system_prompt = """あなたは、優秀な翻訳者です。\n
321
+ 日本語を英語に翻訳して下さい。\n
322
+ """
323
+ self.system_prompt2 = """あなたは、優秀な翻訳者です。\n
324
+ 日本語を英語に以下のフォーマットに従って翻訳して下さい。\n
325
+ MainQuestion:
326
+ Known gene mutation:
327
+ Measurable tumour:
328
+ Biopsiable tumour:
329
+ """
330
+
331
+ self.modify_prompt = ChatPromptTemplate.from_messages(
332
+ [
333
+ ("system", self.system_prompt),
334
+ ("human", "ユーザーの質問: {question}"),
335
+ ]
336
+ )
337
+
338
+ self.modify_prompt2 = ChatPromptTemplate.from_messages(
339
+ [
340
+ ("system", self.system_prompt2),
341
+ ("human", "ユーザーの質問: {question}"),
342
+ ]
343
+ )
344
+
345
+ def is_english(self, text: str) -> bool:
346
+ """
347
+ 簡易的にテキストが英語かどうかを判定する関数
348
+ :param text: 判定するテキスト
349
+ :return: 英語の場合True、日本語の場合False
350
+ """
351
+ # 英語のアルファベットが多く含まれているかを確認
352
+ return bool(re.match(r'^[A-Za-z0-9\s.,?!]+$', text))
353
+
354
+ def translate(self, question: str) -> str:
355
+ """
356
+ 質問を翻訳するメソッド。英語の質問はそのまま返す。
357
+ :param question: 質問文
358
+ :return: 翻訳済みの質問文、または元の質問文(英語の場合)
359
+ """
360
+ # 質問が英語の場合、そのまま返す
361
+ if self.is_english(question):
362
+ return question
363
+
364
+ # 日本語の質問は翻訳プロセスにかける
365
+ question_modifier = self.modify_prompt | self.structured_llm_modifier
366
+ result = question_modifier.invoke({"question": question})
367
+ modify_question = result.modified_question
368
+ return modify_question
369
+
370
+ def translateQuestion(self, question: str) -> str:
371
+ """
372
+ フォーマット付きで質問を翻訳するメソッド。
373
+ :param question: 質問文
374
+ :return: フォーマットに従った翻訳済みの質問
375
+ """
376
+ question_modifier = self.modify_prompt2 | self.structured_llm_modifier
377
+ result = question_modifier.invoke({"question": question})
378
+ modify_question = result.modified_question
379
+ return modify_question
380
+
381
+ def generate_ex_question(age, sex, tumor_type, GeneMutation, Meseable, Biopsiable):
382
+ # GeneMutationが空の場合はUnknownに設定
383
+ gene_mutation_text = GeneMutation if GeneMutation else "Unknown"
384
+
385
+ # MeseableとBiopsiableの値をYes, No, Unknownに変換
386
+ meseable_text = (
387
+ "Yes" if Meseable == "有り" else "No" if Meseable == "無し" else "Unknown"
388
+ )
389
+ biopsiable_text = (
390
+ "Yes" if Biopsiable == "有り" else "No" if Biopsiable == "無し" else "Unknown"
391
+ )
392
+
393
+ # 質問文の生成
394
+ ex_question = f"""{age}歳{sex}の{tumor_type}患者さんはこの治験に参加することができますか?
395
+ 判明している遺伝子変異: {gene_mutation_text}
396
+ Meseable tumor: {meseable_text}
397
+ Biopsiable tumor: {biopsiable_text}
398
+ です。
399
+ """
400
+ return ex_question
401
+
402
+ def generate_ex_question_English(age, sex, tumor_type, GeneMutation, Meseable, Biopsiable):
403
+ # GeneMutationが空の場合は"Unknown"に設定
404
+ gene_mutation_text = GeneMutation if GeneMutation else "Unknown"
405
+
406
+ # sexの値を male または female に変換
407
+ sex_text = "male" if sex == "男性" else "female" if sex == "女性" else "Unknown"
408
+
409
+ # MeseableとBiopsiableの値を "Yes", "No", "Unknown" に変換
410
+ meseable_text = (
411
+ "Yes" if Meseable == "有り" else "No" if Meseable == "無し" else "Unknown"
412
+ )
413
+ biopsiable_text = (
414
+ "Yes" if Biopsiable == "有り" else "No" if Biopsiable == "無し" else "Unknown"
415
+ )
416
+
417
+ # 英語での質問文を生成
418
+ ex_question = f"""Can a {age}-year-old {sex_text} patient with {tumor_type} participate in this clinical trial?
419
+ Known gene mutation: {gene_mutation_text}
420
+ Measurable tumor: {meseable_text}
421
+ Biopsiable tumor: {biopsiable_text}
422
+ """
423
+ return ex_question
app.py CHANGED
@@ -1,5 +1,7 @@
1
  import gradio as gr
2
  import pandas as pd
 
 
3
  from OpenAITools.FetchTools import fetch_clinical_trials
4
  from langchain_openai import ChatOpenAI
5
  from langchain_groq import ChatGroq
@@ -11,59 +13,167 @@ translator = LLMTranslator(groq)
11
  CriteriaCheckAgent = SimpleClinicalTrialAgent(groq)
12
  grader_agent = GraderAgent(groq)
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  # データフレームを生成する関数
15
  def generate_dataframe(age, sex, tumor_type, GeneMutation, Meseable, Biopsiable):
16
- # 日本語の腫瘍タイプを英語に翻訳
17
- TumorName = translator.translate(tumor_type)
 
 
 
 
 
 
 
 
 
18
 
19
- # 質問文を生成
20
- ex_question = generate_ex_question_English(age, sex, TumorName, GeneMutation, Meseable, Biopsiable)
21
-
22
- # 臨床試験データの取得
23
- df = fetch_clinical_trials(TumorName)
24
- df['AgentJudgment'] = None
25
- df['AgentGrade'] = None
26
-
27
- # 臨床試験の適格性の評価
28
- NCTIDs = list(df['NCTID'])
29
- progress = gr.Progress(track_tqdm=True)
30
- for i, nct_id in enumerate(NCTIDs):
31
- target_criteria = df.loc[df['NCTID'] == nct_id, 'Eligibility Criteria'].values[0]
32
- agent_judgment = CriteriaCheckAgent.evaluate_eligibility(target_criteria, ex_question)
33
- agent_grade = grader_agent.evaluate_eligibility(agent_judgment)
34
 
35
- # データフレームの更新
36
- df.loc[df['NCTID'] == nct_id, 'AgentJudgment'] = agent_judgment
37
- df.loc[df['NCTID'] == nct_id, 'AgentGrade'] = agent_grade
38
- progress((i + 1) / len(NCTIDs))
39
-
40
- # 列を指定した順に並び替え
41
- columns_order = ['NCTID', 'AgentGrade', 'Title', 'AgentJudgment', 'Japanes Locations',
42
- 'Primary Completion Date', 'Cancer', 'Summary', 'Eligibility Criteria']
43
- df = df[columns_order]
44
 
45
- return df, df # フィルタ用と表示用にデータフレームを返す
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  # 特定のAgentGrade(yes, no, unclear)に基づいて行をフィルタリングする関数
48
  def filter_rows_by_grade(original_df, grade):
49
- df_filtered = original_df[original_df['AgentGrade'] == grade]
50
- return df_filtered, df_filtered
 
 
 
 
 
 
51
 
52
  # CSVとして保存しダウンロードする関数
53
  def download_filtered_csv(df):
54
- file_path = "filtered_data.csv"
55
- df.to_csv(file_path, index=False)
56
- return file_path
 
 
 
 
 
 
57
 
58
  # 全体結果をCSVとして保存しダウンロードする関数
59
  def download_full_csv(df):
60
- file_path = "full_data.csv"
61
- df.to_csv(file_path, index=False)
62
- return file_path
 
 
 
 
 
 
63
 
64
  # Gradioインターフェースの作成
65
  with gr.Blocks() as demo:
66
  gr.Markdown("## 臨床試験適格性評価インターフェース")
 
67
 
68
  # 各種入力フィールド
69
  age_input = gr.Textbox(label="Age", placeholder="例: 65")
@@ -93,14 +203,37 @@ with gr.Blocks() as demo:
93
  download_full_button = gr.Button("Download Full Data")
94
  download_full_output = gr.File(label="Download Full Data")
95
 
96
-
97
  # ボタン動作の設定
98
- generate_button.click(fn=generate_dataframe, inputs=[age_input, sex_input, tumor_type_input, gene_mutation_input, measurable_input, biopsiable_input], outputs=[dataframe_output, original_df])
99
- yes_button.click(fn=filter_rows_by_grade, inputs=[original_df, gr.State("yes")], outputs=[dataframe_output, filtered_df])
100
- no_button.click(fn=filter_rows_by_grade, inputs=[original_df, gr.State("no")], outputs=[dataframe_output, filtered_df])
101
- unclear_button.click(fn=filter_rows_by_grade, inputs=[original_df, gr.State("unclear")], outputs=[dataframe_output, filtered_df])
102
- download_filtered_button.click(fn=download_filtered_csv, inputs=filtered_df, outputs=download_filtered_output)
103
- download_full_button.click(fn=download_full_csv, inputs=original_df, outputs=download_full_output)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
  if __name__ == "__main__":
106
- demo.launch()
 
1
  import gradio as gr
2
  import pandas as pd
3
+ import time
4
+ import traceback
5
  from OpenAITools.FetchTools import fetch_clinical_trials
6
  from langchain_openai import ChatOpenAI
7
  from langchain_groq import ChatGroq
 
13
  CriteriaCheckAgent = SimpleClinicalTrialAgent(groq)
14
  grader_agent = GraderAgent(groq)
15
 
16
+ # エラーハンドリング付きでエージェント評価を実行する関数
17
+ def evaluate_with_retry(agent, criteria, question, max_retries=3):
18
+ """エラーハンドリング付きでエージェント評価を実行"""
19
+ for attempt in range(max_retries):
20
+ try:
21
+ return agent.evaluate_eligibility(criteria, question)
22
+ except Exception as e:
23
+ if "missing variables" in str(e):
24
+ # プロンプトテンプレートの変数エラーの場合
25
+ print(f"プロンプトテンプレートエラー (試行 {attempt + 1}/{max_retries}): {e}")
26
+ return "評価エラー: プロンプトテンプレートの設定に問題があります"
27
+ elif "no healthy upstream" in str(e) or "InternalServerError" in str(e):
28
+ # Groqサーバーエラーの場合
29
+ print(f"Groqサーバーエラー (試行 {attempt + 1}/{max_retries}): {e}")
30
+ if attempt < max_retries - 1:
31
+ time.sleep(2) # 2秒待機してリトライ
32
+ continue
33
+ else:
34
+ return "評価エラー: サーバーに接続できませんでした"
35
+ else:
36
+ print(f"予期しないエラー (試行 {attempt + 1}/{max_retries}): {e}")
37
+ if attempt < max_retries - 1:
38
+ time.sleep(1)
39
+ continue
40
+ else:
41
+ return f"評価エラー: {str(e)}"
42
+ return "評価エラー: 最大リトライ回数に達しました"
43
+
44
+ def evaluate_grade_with_retry(agent, judgment, max_retries=3):
45
+ """エラーハンドリング付きでグレード評価を実行"""
46
+ for attempt in range(max_retries):
47
+ try:
48
+ return agent.evaluate_eligibility(judgment)
49
+ except Exception as e:
50
+ if "no healthy upstream" in str(e) or "InternalServerError" in str(e):
51
+ print(f"Groqサーバーエラー (グレード評価 - 試行 {attempt + 1}/{max_retries}): {e}")
52
+ if attempt < max_retries - 1:
53
+ time.sleep(2)
54
+ continue
55
+ else:
56
+ return "unclear"
57
+ else:
58
+ print(f"予期しないエラー (グレード評価 - 試行 {attempt + 1}/{max_retries}): {e}")
59
+ if attempt < max_retries - 1:
60
+ time.sleep(1)
61
+ continue
62
+ else:
63
+ return "unclear"
64
+ return "unclear"
65
+
66
  # データフレームを生成する関数
67
  def generate_dataframe(age, sex, tumor_type, GeneMutation, Meseable, Biopsiable):
68
+ try:
69
+ # 入力検証
70
+ if not all([age, sex, tumor_type]):
71
+ return pd.DataFrame(), pd.DataFrame()
72
+
73
+ # 日本語の腫瘍タイプを英語に翻訳
74
+ try:
75
+ TumorName = translator.translate(tumor_type)
76
+ except Exception as e:
77
+ print(f"翻訳エラー: {e}")
78
+ TumorName = tumor_type # 翻訳に失敗した場合は元の値を使用
79
 
80
+ # 質問文を生成
81
+ try:
82
+ ex_question = generate_ex_question_English(age, sex, TumorName, GeneMutation, Meseable, Biopsiable)
83
+ except Exception as e:
84
+ print(f"質問生成エラー: {e}")
85
+ return pd.DataFrame(), pd.DataFrame()
 
 
 
 
 
 
 
 
 
86
 
87
+ # 臨床試験データの取得
88
+ try:
89
+ df = fetch_clinical_trials(TumorName)
90
+ if df.empty:
91
+ print("臨床試験データが見つかりませんでした")
92
+ return pd.DataFrame(), pd.DataFrame()
93
+ except Exception as e:
94
+ print(f"臨床試験データ取得エラー: {e}")
95
+ return pd.DataFrame(), pd.DataFrame()
96
 
97
+ df['AgentJudgment'] = None
98
+ df['AgentGrade'] = None
99
+
100
+ # 臨床試験の適格性の評価
101
+ NCTIDs = list(df['NCTID'])
102
+ progress = gr.Progress(track_tqdm=True)
103
+
104
+ for i, nct_id in enumerate(NCTIDs):
105
+ try:
106
+ target_criteria = df.loc[df['NCTID'] == nct_id, 'Eligibility Criteria'].values[0]
107
+
108
+ # エラーハンドリング付きで評価実行
109
+ agent_judgment = evaluate_with_retry(CriteriaCheckAgent, target_criteria, ex_question)
110
+ agent_grade = evaluate_grade_with_retry(grader_agent, agent_judgment)
111
+
112
+ # データフレームの更新
113
+ df.loc[df['NCTID'] == nct_id, 'AgentJudgment'] = agent_judgment
114
+ df.loc[df['NCTID'] == nct_id, 'AgentGrade'] = agent_grade
115
+
116
+ except Exception as e:
117
+ print(f"NCTID {nct_id} の評価中にエラー: {e}")
118
+ df.loc[df['NCTID'] == nct_id, 'AgentJudgment'] = f"エラー: {str(e)}"
119
+ df.loc[df['NCTID'] == nct_id, 'AgentGrade'] = "unclear"
120
+
121
+ progress((i + 1) / len(NCTIDs))
122
+
123
+ # 列を指定した順に並び替え
124
+ columns_order = ['NCTID', 'AgentGrade', 'Title', 'AgentJudgment', 'Japanes Locations',
125
+ 'Primary Completion Date', 'Cancer', 'Summary', 'Eligibility Criteria']
126
+
127
+ # 存在する列のみを選択
128
+ available_columns = [col for col in columns_order if col in df.columns]
129
+ df = df[available_columns]
130
+
131
+ return df, df # フィルタ用と表示用にデータフレームを返す
132
+
133
+ except Exception as e:
134
+ print(f"データフレーム生成中に予期しないエラー: {e}")
135
+ traceback.print_exc()
136
+ return pd.DataFrame(), pd.DataFrame()
137
 
138
  # 特定のAgentGrade(yes, no, unclear)に基づいて行をフィルタリングする関数
139
  def filter_rows_by_grade(original_df, grade):
140
+ try:
141
+ if original_df is None or original_df.empty:
142
+ return pd.DataFrame(), pd.DataFrame()
143
+ df_filtered = original_df[original_df['AgentGrade'] == grade]
144
+ return df_filtered, df_filtered
145
+ except Exception as e:
146
+ print(f"フィルタリングエラー: {e}")
147
+ return pd.DataFrame(), pd.DataFrame()
148
 
149
  # CSVとして保存しダウンロードする関数
150
  def download_filtered_csv(df):
151
+ try:
152
+ if df is None or df.empty:
153
+ return None
154
+ file_path = "filtered_data.csv"
155
+ df.to_csv(file_path, index=False)
156
+ return file_path
157
+ except Exception as e:
158
+ print(f"CSV保存エラー: {e}")
159
+ return None
160
 
161
  # 全体結果をCSVとして保存しダウンロードする関数
162
  def download_full_csv(df):
163
+ try:
164
+ if df is None or df.empty:
165
+ return None
166
+ file_path = "full_data.csv"
167
+ df.to_csv(file_path, index=False)
168
+ return file_path
169
+ except Exception as e:
170
+ print(f"CSV保存エラー: {e}")
171
+ return None
172
 
173
  # Gradioインターフェースの作成
174
  with gr.Blocks() as demo:
175
  gr.Markdown("## 臨床試験適格性評価インターフェース")
176
+ gr.Markdown("⚠️ **注意**: サーバーエラーが発生する場合があります。エラーが続く場合は少し時間をおいてから再試行してください。")
177
 
178
  # 各種入力フィールド
179
  age_input = gr.Textbox(label="Age", placeholder="例: 65")
 
203
  download_full_button = gr.Button("Download Full Data")
204
  download_full_output = gr.File(label="Download Full Data")
205
 
 
206
  # ボタン動作の設定
207
+ generate_button.click(
208
+ fn=generate_dataframe,
209
+ inputs=[age_input, sex_input, tumor_type_input, gene_mutation_input, measurable_input, biopsiable_input],
210
+ outputs=[dataframe_output, original_df]
211
+ )
212
+ yes_button.click(
213
+ fn=filter_rows_by_grade,
214
+ inputs=[original_df, gr.State("yes")],
215
+ outputs=[dataframe_output, filtered_df]
216
+ )
217
+ no_button.click(
218
+ fn=filter_rows_by_grade,
219
+ inputs=[original_df, gr.State("no")],
220
+ outputs=[dataframe_output, filtered_df]
221
+ )
222
+ unclear_button.click(
223
+ fn=filter_rows_by_grade,
224
+ inputs=[original_df, gr.State("unclear")],
225
+ outputs=[dataframe_output, filtered_df]
226
+ )
227
+ download_filtered_button.click(
228
+ fn=download_filtered_csv,
229
+ inputs=filtered_df,
230
+ outputs=download_filtered_output
231
+ )
232
+ download_full_button.click(
233
+ fn=download_full_csv,
234
+ inputs=original_df,
235
+ outputs=download_full_output
236
+ )
237
 
238
  if __name__ == "__main__":
239
+ demo.launch()
requirements.txt CHANGED
@@ -1,76 +1,57 @@
1
- aiohttp==3.9.5
2
- aiosignal==1.3.1
3
- bio==1.7.1
4
- biopython==1.83
5
- biothings-client==0.3.1
6
- dataclasses-json==0.6.6
7
- Deprecated==1.2.14
8
- dirtyjson==1.0.8
9
- diskcache==5.6.3
10
- distro==1.9.0
11
- frozenlist==1.4.1
12
- gprofiler-official==1.0.0
13
- greenlet==3.0.3
14
- hpack==4.0.0
15
- jsonpatch==1.33
16
- langchain==0.3.2
17
- langchain-community==0.3.1
18
- langchain-core==0.3.9
19
- langchain-experimental==0.3.2
20
- langchain-groq==0.2.0
21
- langchain-openai==0.2.2
22
- langchain-text-splitters==0.3.0
23
- langchainhub==0.1.21
24
- langgraph==0.2.34
25
- langgraph-checkpoint==2.0.1
26
- langsmith==0.1.131
27
- llama-index==0.10.43
28
- llama-index-agent-openai==0.2.7
29
- llama-index-cli==0.1.12
30
- llama-index-core==0.10.43
31
- llama-index-embeddings-openai==0.1.10
32
- llama-index-indices-managed-llama-cloud==0.1.6
33
- llama-index-legacy==0.9.48
34
- llama-index-llms-groq==0.1.4
35
- llama-index-llms-llama-cpp==0.1.3
36
- llama-index-llms-openai==0.1.22
37
- llama-index-llms-openai-like==0.1.3
38
- llama-index-llms-replicate==0.1.3
39
- llama-index-multi-modal-llms-openai==0.1.6
40
- llama-index-program-openai==0.1.6
41
- llama-index-question-gen-openai==0.1.3
42
- llama-index-readers-file==0.1.23
43
- llama-index-readers-llama-parse==0.1.4
44
- llama-parse==0.4.4
45
- llama_cpp_python==0.2.77
46
- llamaindex-py-client==0.1.19
47
- marshmallow==3.21.2
48
- multidict==6.0.5
49
- munkres==1.1.4
50
- mygene==3.2.2
51
- mypy-extensions==1.0.0
52
- natsort==8.4.0
53
- networkx==3.3
54
- nltk
55
- openai
56
- packaging==23.2
57
- pooch==1.8.1
58
- pypdf==4.2.0
59
- pytrials==1.0.0
60
- regex==2024.5.15
61
- replicate==0.26.0
62
- safetensors
63
- setuptools==70.0.0
64
- SQLAlchemy==2.0.30
65
- striprtf==0.0.26
66
- tenacity==8.3.0
67
- tiktoken==0.7.0
68
- tokenizers==0.19.1
69
- transformers==4.41.2
70
- typer==0.12.3
71
- typer-slim==0.12.3
72
- typing-inspect==0.9.0
73
- wheel==0.43.0
74
- wikipedia==1.4.0
75
- wrapt==1.16.0
76
- yarl==1.9.4
 
1
+ # Core web framework
2
+ gradio>=4.0.0
3
+
4
+ # Data processing
5
+ pandas>=1.5.0
6
+ numpy>=1.21.0
7
+ requests>=2.25.0
8
+
9
+ # LangChain ecosystem (compatible versions)
10
+ langchain>=0.3.0,<0.4.0
11
+ langchain-community>=0.3.0,<0.4.0
12
+ langchain-core>=0.3.0,<0.4.0
13
+ langchain-openai>=0.2.0,<0.3.0
14
+ langchain-groq>=0.2.0,<0.3.0
15
+ langchain-text-splitters>=0.3.0,<0.4.0
16
+
17
+ # LLM providers
18
+ openai>=1.0.0
19
+ groq>=0.4.0
20
+
21
+ # Vector databases and embeddings
22
+ chromadb>=0.4.0
23
+ sentence-transformers>=2.2.0
24
+
25
+ # Database utilities
26
+ SQLAlchemy>=2.0.0,<3.0.0
27
+
28
+ # Pydantic (for compatibility)
29
+ pydantic>=2.0.0,<3.0.0
30
+
31
+ # Text processing
32
+ tiktoken>=0.4.0
33
+ tokenizers>=0.19.0
34
+ transformers>=4.40.0
35
+
36
+ # Utilities
37
+ tenacity>=8.0.0
38
+ packaging>=23.0.0
39
+ setuptools>=70.0.0
40
+
41
+ # Optional: Bio-related libraries (if needed for your specific use case)
42
+ # Uncomment the following lines if bio-processing is required
43
+ # biopython>=1.83
44
+ # bio>=1.7.1
45
+ # biothings-client>=0.3.1
46
+ # mygene>=3.2.2
47
+
48
+ # Optional: Advanced LangChain features (if needed)
49
+ # langchainhub>=0.1.20
50
+ # langgraph>=0.2.30
51
+
52
+ # Optional: Additional LLama Index support (if needed)
53
+ # Uncomment if you're using LlamaIndex in addition to LangChain
54
+ # llama-index>=0.10.0
55
+ # llama-index-core>=0.10.0
56
+ # llama-index-llms-openai>=0.1.20
57
+ # llama-index-llms-groq>=0.1.4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirements_old.txt ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiohttp==3.9.5
2
+ aiosignal==1.3.1
3
+ bio==1.7.1
4
+ biopython==1.83
5
+ biothings-client==0.3.1
6
+ dataclasses-json==0.6.6
7
+ Deprecated==1.2.14
8
+ dirtyjson==1.0.8
9
+ diskcache==5.6.3
10
+ distro==1.9.0
11
+ frozenlist==1.4.1
12
+ gprofiler-official==1.0.0
13
+ greenlet==3.0.3
14
+ hpack==4.0.0
15
+ jsonpatch==1.33
16
+ langchain==0.3.2
17
+ langchain-community==0.3.1
18
+ langchain-core==0.3.9
19
+ langchain-experimental==0.3.2
20
+ langchain-groq==0.2.0
21
+ langchain-openai==0.2.2
22
+ langchain-text-splitters==0.3.0
23
+ langchainhub==0.1.21
24
+ langgraph==0.2.34
25
+ langgraph-checkpoint==2.0.1
26
+ langsmith==0.1.131
27
+ llama-index==0.10.43
28
+ llama-index-agent-openai==0.2.7
29
+ llama-index-cli==0.1.12
30
+ llama-index-core==0.10.43
31
+ llama-index-embeddings-openai==0.1.10
32
+ llama-index-indices-managed-llama-cloud==0.1.6
33
+ llama-index-legacy==0.9.48
34
+ llama-index-llms-groq==0.1.4
35
+ llama-index-llms-llama-cpp==0.1.3
36
+ llama-index-llms-openai==0.1.22
37
+ llama-index-llms-openai-like==0.1.3
38
+ llama-index-llms-replicate==0.1.3
39
+ llama-index-multi-modal-llms-openai==0.1.6
40
+ llama-index-program-openai==0.1.6
41
+ llama-index-question-gen-openai==0.1.3
42
+ llama-index-readers-file==0.1.23
43
+ llama-index-readers-llama-parse==0.1.4
44
+ llama-parse==0.4.4
45
+ llama_cpp_python==0.2.77
46
+ llamaindex-py-client==0.1.19
47
+ marshmallow==3.21.2
48
+ multidict==6.0.5
49
+ munkres==1.1.4
50
+ mygene==3.2.2
51
+ mypy-extensions==1.0.0
52
+ natsort==8.4.0
53
+ networkx==3.3
54
+ nltk
55
+ openai
56
+ packaging==23.2
57
+ pooch==1.8.1
58
+ pypdf==4.2.0
59
+ pytrials==1.0.0
60
+ regex==2024.5.15
61
+ replicate==0.26.0
62
+ safetensors
63
+ setuptools==70.0.0
64
+ SQLAlchemy==2.0.30
65
+ striprtf==0.0.26
66
+ tenacity==8.3.0
67
+ tiktoken==0.7.0
68
+ tokenizers==0.19.1
69
+ transformers==4.41.2
70
+ typer==0.12.3
71
+ typer-slim==0.12.3
72
+ typing-inspect==0.9.0
73
+ wheel==0.43.0
74
+ wikipedia==1.4.0
75
+ wrapt==1.16.0
76
+ yarl==1.9.4