Spaces:
Sleeping
Sleeping
レビューを元に修正
Browse files- .gitignore +1 -1
- README.md +2 -1
- main.py +3 -3
- src/aws/s3.py +6 -20
- src/database.py +40 -77
- src/forms/change_request.py +10 -12
- src/forms/database_check.py +4 -4
.gitignore
CHANGED
@@ -163,7 +163,7 @@ cython_debug/
|
|
163 |
.DS_Store
|
164 |
|
165 |
# 申請書/報告書はリポジトリにはアップロードしない。
|
166 |
-
data/
|
167 |
data/output.docx
|
168 |
data/output_deviation.docx
|
169 |
data/output_deviation_occurrence.docx
|
|
|
163 |
.DS_Store
|
164 |
|
165 |
# 申請書/報告書はリポジトリにはアップロードしない。
|
166 |
+
data/change_request_history.csv
|
167 |
data/output.docx
|
168 |
data/output_deviation.docx
|
169 |
data/output_deviation_occurrence.docx
|
README.md
CHANGED
@@ -14,7 +14,7 @@ license: other
|
|
14 |
製薬業務のドキュメント自動生成SaaSトライアル版
|
15 |
|
16 |
# 使い方
|
17 |
-
## 1. .env.exampleを参考に.envを作成し、OpenAIとPINECONEのAPIキーを設定
|
18 |
```
|
19 |
OPENAI_API_KEY =
|
20 |
PINECONE_API_KEY =
|
@@ -24,6 +24,7 @@ AWS_SECRET_ACCESS_KEY =
|
|
24 |
値はnotionで管理されているので、参照する。
|
25 |
[OpenAI API](https://www.notion.so/equesai/OpenAI-API-b2029c9b5d774eaebd7318a702ec31f1?pvs=4)
|
26 |
[PINECONE](https://www.notion.so/equesai/API-61268f5a9218495ca96ee0bb176fa13a?pvs=4)
|
|
|
27 |
|
28 |
## 2. 仮想環境を作成・プレコミットの導入
|
29 |
`pipenv install -r ./requirements.txt`
|
|
|
14 |
製薬業務のドキュメント自動生成SaaSトライアル版
|
15 |
|
16 |
# 使い方
|
17 |
+
## 1. .env.exampleを参考に.envを作成し、OpenAIとPINECONE、AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEYのAPIキーを設定
|
18 |
```
|
19 |
OPENAI_API_KEY =
|
20 |
PINECONE_API_KEY =
|
|
|
24 |
値はnotionで管理されているので、参照する。
|
25 |
[OpenAI API](https://www.notion.so/equesai/OpenAI-API-b2029c9b5d774eaebd7318a702ec31f1?pvs=4)
|
26 |
[PINECONE](https://www.notion.so/equesai/API-61268f5a9218495ca96ee0bb176fa13a?pvs=4)
|
27 |
+
[AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY](https://www.notion.so/equesai/API-61268f5a9218495ca96ee0bb176fa13a?pvs=4)
|
28 |
|
29 |
## 2. 仮想環境を作成・プレコミットの導入
|
30 |
`pipenv install -r ./requirements.txt`
|
main.py
CHANGED
@@ -9,7 +9,7 @@ pages = {
|
|
9 |
"変更申請書": change_request_form,
|
10 |
"逸脱発生報告書": deviation_occurrence_report_form,
|
11 |
"逸脱報告書": deviation_report_form,
|
12 |
-
"
|
13 |
}
|
14 |
|
15 |
selected_page = st.sidebar.selectbox(
|
@@ -22,5 +22,5 @@ match selected_page:
|
|
22 |
pages["逸脱発生報告書"]()
|
23 |
case "逸脱報告書":
|
24 |
pages["逸脱報告書"]()
|
25 |
-
case "
|
26 |
-
pages["
|
|
|
9 |
"変更申請書": change_request_form,
|
10 |
"逸脱発生報告書": deviation_occurrence_report_form,
|
11 |
"逸脱報告書": deviation_report_form,
|
12 |
+
"申請履歴": database_check_form,
|
13 |
}
|
14 |
|
15 |
selected_page = st.sidebar.selectbox(
|
|
|
22 |
pages["逸脱発生報告書"]()
|
23 |
case "逸脱報告書":
|
24 |
pages["逸脱報告書"]()
|
25 |
+
case "申請履歴":
|
26 |
+
pages["申請履歴"]()
|
src/aws/s3.py
CHANGED
@@ -1,37 +1,23 @@
|
|
1 |
from io import StringIO
|
2 |
-
from typing import Any, List
|
3 |
|
4 |
import boto3
|
5 |
import pandas as pd
|
6 |
|
7 |
s3 = boto3.client("s3")
|
8 |
-
bucket_name = "bankyo-pharmaceutical"
|
9 |
|
10 |
|
11 |
# Download the CSV file from S3
|
12 |
-
def
|
|
|
|
|
13 |
obj = s3.get_object(Bucket=bucket_name, Key=file_name)
|
14 |
data = pd.read_csv(obj["Body"])
|
15 |
return data
|
16 |
|
17 |
|
18 |
-
def
|
|
|
|
|
19 |
csv_buffer = StringIO()
|
20 |
data.to_csv(csv_buffer, index=False)
|
21 |
s3.put_object(Bucket=bucket_name, Key=file_name, Body=csv_buffer.getvalue())
|
22 |
-
|
23 |
-
|
24 |
-
def get_all_objects() -> List[str]:
|
25 |
-
response = s3.list_objects_v2(Bucket=bucket_name)
|
26 |
-
csv_files = [
|
27 |
-
obj["Key"]
|
28 |
-
for obj in response.get("Contents", [])
|
29 |
-
if obj["Key"].endswith(".csv")
|
30 |
-
]
|
31 |
-
return csv_files
|
32 |
-
|
33 |
-
|
34 |
-
def get_csv_content(file_name: str) -> Any:
|
35 |
-
obj = s3.get_object(Bucket=bucket_name, Key=file_name)
|
36 |
-
df = pd.read_csv(obj["Body"])
|
37 |
-
return df.iloc[0]
|
|
|
1 |
from io import StringIO
|
|
|
2 |
|
3 |
import boto3
|
4 |
import pandas as pd
|
5 |
|
6 |
s3 = boto3.client("s3")
|
|
|
7 |
|
8 |
|
9 |
# Download the CSV file from S3
|
10 |
+
def download_csv_panda_dataframe_from_s3(
|
11 |
+
bucket_name: str, file_name: str
|
12 |
+
) -> pd.DataFrame:
|
13 |
obj = s3.get_object(Bucket=bucket_name, Key=file_name)
|
14 |
data = pd.read_csv(obj["Body"])
|
15 |
return data
|
16 |
|
17 |
|
18 |
+
def save_csv_panda_dataframe_to_s3(
|
19 |
+
data: pd.DataFrame, bucket_name: str, file_name: str
|
20 |
+
) -> None:
|
21 |
csv_buffer = StringIO()
|
22 |
data.to_csv(csv_buffer, index=False)
|
23 |
s3.put_object(Bucket=bucket_name, Key=file_name, Body=csv_buffer.getvalue())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/database.py
CHANGED
@@ -1,12 +1,16 @@
|
|
1 |
-
import csv
|
2 |
from datetime import datetime
|
3 |
from typing import List
|
4 |
|
5 |
-
# import boto3
|
6 |
import pandas as pd
|
7 |
-
import streamlit
|
8 |
|
9 |
-
from src.aws.s3 import
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
|
12 |
def write_csv(
|
@@ -14,88 +18,47 @@ def write_csv(
|
|
14 |
change_type: List[str],
|
15 |
category: List[str],
|
16 |
subcategory: List[str],
|
17 |
-
|
18 |
-
|
19 |
-
output_username: str,
|
20 |
-
output_date: str,
|
21 |
-
output_change_target: str,
|
22 |
-
output_change_period: str,
|
23 |
output_change_content: str,
|
24 |
output_change_reason: str,
|
25 |
output_effect: str,
|
26 |
-
output_resource: str,
|
27 |
-
output_other: str,
|
28 |
) -> None:
|
29 |
all_types = []
|
30 |
for i in range(len(change_type)):
|
31 |
all_type = [i + 1, change_type[i], category[i], subcategory[i]]
|
32 |
all_types.append(all_type)
|
33 |
-
|
34 |
-
column_names = [
|
35 |
-
"申請者",
|
36 |
-
"全ての変更タイプ",
|
37 |
-
"入力",
|
38 |
-
"出力:工場",
|
39 |
-
"出力:申請者名",
|
40 |
-
"出力:申請日",
|
41 |
-
"出力:変更対象",
|
42 |
-
"出力:実施予定時期",
|
43 |
-
"出力:変更内容",
|
44 |
-
"出力:変更理由",
|
45 |
-
"出力:品質への影響",
|
46 |
-
"出力:参考資料",
|
47 |
-
"出力:備考",
|
48 |
-
]
|
49 |
-
new_data = pd.DataFrame(
|
50 |
-
[
|
51 |
-
[
|
52 |
-
applicant_name,
|
53 |
-
all_types,
|
54 |
-
input,
|
55 |
-
output_factory,
|
56 |
-
output_username,
|
57 |
-
output_date,
|
58 |
-
output_change_target,
|
59 |
-
output_change_period,
|
60 |
-
output_change_content,
|
61 |
-
output_change_reason,
|
62 |
-
output_effect,
|
63 |
-
output_resource,
|
64 |
-
output_other,
|
65 |
-
]
|
66 |
-
],
|
67 |
-
columns=column_names,
|
68 |
-
)
|
69 |
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
70 |
-
|
71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
"全ての変更タイプ",
|
79 |
-
"入力",
|
80 |
-
"出力:工場",
|
81 |
-
"出力:申請者名",
|
82 |
-
"出力:申請日",
|
83 |
-
"出力:変更対象",
|
84 |
-
"出力:実施予定時期",
|
85 |
-
"出力:変更内容",
|
86 |
-
"出力:変更理由",
|
87 |
-
"出力:品質への影響",
|
88 |
-
"出力:参考資料",
|
89 |
-
"出力:備考",
|
90 |
-
]
|
91 |
-
path = "data/inputsData.csv"
|
92 |
-
with open(path, mode="w", newline="") as file:
|
93 |
-
writer = csv.writer(file)
|
94 |
-
writer.writerow(header)
|
95 |
-
if datas:
|
96 |
-
for data in datas:
|
97 |
-
data = get_csv_content(data)
|
98 |
-
writer.writerow(data)
|
99 |
st.write("**データベース**")
|
100 |
-
|
101 |
-
st.dataframe(df)
|
|
|
|
|
1 |
from datetime import datetime
|
2 |
from typing import List
|
3 |
|
|
|
4 |
import pandas as pd
|
5 |
+
import streamlit
|
6 |
|
7 |
+
from src.aws.s3 import (
|
8 |
+
download_csv_panda_dataframe_from_s3,
|
9 |
+
save_csv_panda_dataframe_to_s3,
|
10 |
+
)
|
11 |
+
|
12 |
+
bucket_name = "pharma-doc-trials"
|
13 |
+
path_name = "bankyo/change_request_history.csv"
|
14 |
|
15 |
|
16 |
def write_csv(
|
|
|
18 |
change_type: List[str],
|
19 |
category: List[str],
|
20 |
subcategory: List[str],
|
21 |
+
questions: List[str],
|
22 |
+
input: List[str],
|
|
|
|
|
|
|
|
|
23 |
output_change_content: str,
|
24 |
output_change_reason: str,
|
25 |
output_effect: str,
|
|
|
|
|
26 |
) -> None:
|
27 |
all_types = []
|
28 |
for i in range(len(change_type)):
|
29 |
all_type = [i + 1, change_type[i], category[i], subcategory[i]]
|
30 |
all_types.append(all_type)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
32 |
+
data = download_csv_panda_dataframe_from_s3(bucket_name, path_name)
|
33 |
+
new_row = [
|
34 |
+
timestamp,
|
35 |
+
applicant_name,
|
36 |
+
all_types,
|
37 |
+
output_change_content,
|
38 |
+
output_change_reason,
|
39 |
+
output_effect,
|
40 |
+
]
|
41 |
+
for change_serial_number in range(len(questions)):
|
42 |
+
new_row.append(questions[change_serial_number])
|
43 |
+
new_row.append(input[change_serial_number])
|
44 |
|
45 |
+
max_length = max(len(data.columns), len(new_row))
|
46 |
+
number_of_qeustions = len(questions)
|
47 |
+
column_existed_number_of_question = (len(data.columns) - 6) // 2
|
48 |
+
if len(data.columns) < max_length:
|
49 |
+
for i in range(column_existed_number_of_question, number_of_qeustions):
|
50 |
+
data[f"質問{i+1}"] = None
|
51 |
+
data[f"回答{i+1}"] = None
|
52 |
+
new_columns = data.columns.tolist()
|
53 |
+
while len(new_row) < len(new_columns):
|
54 |
+
new_row.append("")
|
55 |
+
new_data = pd.DataFrame([new_row], columns=new_columns)
|
56 |
+
data = pd.concat([data, new_data], ignore_index=True)
|
57 |
+
save_csv_panda_dataframe_to_s3(data, bucket_name, path_name)
|
58 |
|
59 |
+
|
60 |
+
def display_csv(file_path: str, st: streamlit) -> None:
|
61 |
+
data = download_csv_panda_dataframe_from_s3(bucket_name, path_name)
|
62 |
+
data.to_csv(file_path, index=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
st.write("**データベース**")
|
64 |
+
st.dataframe(data)
|
|
src/forms/change_request.py
CHANGED
@@ -358,6 +358,9 @@ def change_request_form() -> None:
|
|
358 |
+ systemprompt_template_2
|
359 |
)
|
360 |
user_prompt = ""
|
|
|
|
|
|
|
361 |
for change_serial_number in range(
|
362 |
start_from_one, change_number + upper_bound_correction
|
363 |
):
|
@@ -380,6 +383,7 @@ def change_request_form() -> None:
|
|
380 |
# question は「Q1-12...」などの形式
|
381 |
answer_id = question.split(" : ")[0].replace("Q", "A")
|
382 |
user_prompt += f"{answer_id} : {answer}\n"
|
|
|
383 |
|
384 |
system_prompt += systemprompt_template_3
|
385 |
|
@@ -446,17 +450,11 @@ def change_request_form() -> None:
|
|
446 |
type,
|
447 |
category,
|
448 |
subcategory,
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
st.session_state["contents"]["実施予定時期"],
|
455 |
-
st.session_state["contents"]["変更内容"],
|
456 |
-
st.session_state["contents"]["変更理由"],
|
457 |
-
st.session_state["contents"]["品質への影響"],
|
458 |
-
st.session_state["contents"]["添付資料"],
|
459 |
-
st.session_state["contents"]["備考"],
|
460 |
)
|
461 |
st.session_state["document_generated"] = True
|
462 |
|
@@ -486,7 +484,7 @@ def change_request_form() -> None:
|
|
486 |
st.markdown(f'**備考** : {st.session_state["contents"]["備考"]}')
|
487 |
|
488 |
review_button = st.button("レビューする")
|
489 |
-
display_csv()
|
490 |
if review_button:
|
491 |
query_content = st.session_state["contents"]["変更内容"]
|
492 |
query_reason = st.session_state["contents"]["変更理由"]
|
|
|
358 |
+ systemprompt_template_2
|
359 |
)
|
360 |
user_prompt = ""
|
361 |
+
# db用
|
362 |
+
user_input = []
|
363 |
+
|
364 |
for change_serial_number in range(
|
365 |
start_from_one, change_number + upper_bound_correction
|
366 |
):
|
|
|
383 |
# question は「Q1-12...」などの形式
|
384 |
answer_id = question.split(" : ")[0].replace("Q", "A")
|
385 |
user_prompt += f"{answer_id} : {answer}\n"
|
386 |
+
user_input.append(f"{answer_id} : {answer}\n")
|
387 |
|
388 |
system_prompt += systemprompt_template_3
|
389 |
|
|
|
450 |
type,
|
451 |
category,
|
452 |
subcategory,
|
453 |
+
question_about_this_change,
|
454 |
+
user_input,
|
455 |
+
str(response_data["変更内容"]),
|
456 |
+
str(response_data["変更理由"]),
|
457 |
+
str(response_data["品質への影響"]),
|
|
|
|
|
|
|
|
|
|
|
|
|
458 |
)
|
459 |
st.session_state["document_generated"] = True
|
460 |
|
|
|
484 |
st.markdown(f'**備考** : {st.session_state["contents"]["備考"]}')
|
485 |
|
486 |
review_button = st.button("レビューする")
|
487 |
+
display_csv("data/change_request_history.csv", st)
|
488 |
if review_button:
|
489 |
query_content = st.session_state["contents"]["変更内容"]
|
490 |
query_reason = st.session_state["contents"]["変更理由"]
|
src/forms/database_check.py
CHANGED
@@ -6,14 +6,14 @@ from src.database import display_csv
|
|
6 |
|
7 |
|
8 |
def database_check_form() -> None:
|
9 |
-
|
10 |
-
file_path
|
11 |
file_exists = os.path.isfile(file_path)
|
12 |
if file_exists:
|
13 |
-
with open(
|
14 |
st.download_button(
|
15 |
label="ダウンロード",
|
16 |
data=file,
|
17 |
-
file_name="
|
18 |
mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
19 |
)
|
|
|
6 |
|
7 |
|
8 |
def database_check_form() -> None:
|
9 |
+
file_path = "data/change_request_history.csv"
|
10 |
+
display_csv(file_path, st)
|
11 |
file_exists = os.path.isfile(file_path)
|
12 |
if file_exists:
|
13 |
+
with open(file_path, "rb") as file:
|
14 |
st.download_button(
|
15 |
label="ダウンロード",
|
16 |
data=file,
|
17 |
+
file_name="change_request_history.csv",
|
18 |
mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
19 |
)
|