Spaces:
Runtime error
Runtime error
123
Browse files- app.py +21 -14
- data.py +11 -0
- data_experiments.py +55 -0
- data_photos.py +87 -0
- experiments.jsonl +0 -0
- llm_messages_v1.py +75 -0
- llm_messages_v2.py +68 -0
- llm_messages_v3.py +73 -0
app.py
CHANGED
|
@@ -22,6 +22,8 @@ from transformers import (
|
|
| 22 |
)
|
| 23 |
from transformers.image_utils import load_image
|
| 24 |
|
|
|
|
|
|
|
| 25 |
# Constants for text generation
|
| 26 |
MAX_MAX_NEW_TOKENS = 2048
|
| 27 |
DEFAULT_MAX_NEW_TOKENS = 1024
|
|
@@ -103,11 +105,16 @@ def process_image(
|
|
| 103 |
yield buffer, buffer
|
| 104 |
|
| 105 |
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
|
| 112 |
css = """
|
| 113 |
.submit-btn {
|
|
@@ -129,12 +136,18 @@ with gr.Blocks(css=css, theme="bethecloud/storj_theme") as demo:
|
|
| 129 |
gr.Markdown("# **Experiments photo moderation**")
|
| 130 |
with gr.Row():
|
| 131 |
with gr.Column():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
image_query = gr.Textbox(label="Query Input", placeholder="Enter your query here...")
|
| 133 |
image_upload = gr.Image(type="pil", label="Image")
|
| 134 |
image_submit = gr.Button("Submit", elem_classes="submit-btn")
|
| 135 |
-
gr.
|
| 136 |
-
|
| 137 |
-
|
|
|
|
| 138 |
)
|
| 139 |
with gr.Accordion("Advanced options", open=False):
|
| 140 |
max_new_tokens = gr.Slider(label="Max new tokens", minimum=1, maximum=MAX_MAX_NEW_TOKENS, step=1, value=DEFAULT_MAX_NEW_TOKENS)
|
|
@@ -150,12 +163,6 @@ with gr.Blocks(css=css, theme="bethecloud/storj_theme") as demo:
|
|
| 150 |
|
| 151 |
with gr.Accordion("(Result.md)", open=False):
|
| 152 |
markdown_output = gr.Markdown()
|
| 153 |
-
|
| 154 |
-
model_choice = gr.Radio(
|
| 155 |
-
choices=["Qwen2.5-VL-7B-Instruct", "Qwen2.5-VL-3B-Instruct"],
|
| 156 |
-
label="Select Model",
|
| 157 |
-
value="Qwen2.5-VL-7B-Instruct"
|
| 158 |
-
)
|
| 159 |
|
| 160 |
image_submit.click(
|
| 161 |
fn=process_image,
|
|
|
|
| 22 |
)
|
| 23 |
from transformers.image_utils import load_image
|
| 24 |
|
| 25 |
+
from data_experiments import filter_experiments
|
| 26 |
+
|
| 27 |
# Constants for text generation
|
| 28 |
MAX_MAX_NEW_TOKENS = 2048
|
| 29 |
DEFAULT_MAX_NEW_TOKENS = 1024
|
|
|
|
| 105 |
yield buffer, buffer
|
| 106 |
|
| 107 |
|
| 108 |
+
experiments_to_select = filter_experiments(
|
| 109 |
+
product_id="chemistry",
|
| 110 |
+
)
|
| 111 |
+
experiments_to_select = sorted(experiments_to_select, key=lambda x: x["id"])
|
| 112 |
+
|
| 113 |
+
def format_experiment_dropdown_title(experiment: dict) -> str:
|
| 114 |
+
id = str(experiment["id"])
|
| 115 |
+
title = experiment.get("title", "")
|
| 116 |
+
product = experiment.get("product_id", "")
|
| 117 |
+
return f"{id}. {title} ({product})"
|
| 118 |
|
| 119 |
css = """
|
| 120 |
.submit-btn {
|
|
|
|
| 136 |
gr.Markdown("# **Experiments photo moderation**")
|
| 137 |
with gr.Row():
|
| 138 |
with gr.Column():
|
| 139 |
+
gr.Dropdown(
|
| 140 |
+
choices=[(format_experiment_dropdown_title(exp), exp["id"]) for exp in experiments_to_select],
|
| 141 |
+
value=None,
|
| 142 |
+
label="Select Experiment",
|
| 143 |
+
)
|
| 144 |
image_query = gr.Textbox(label="Query Input", placeholder="Enter your query here...")
|
| 145 |
image_upload = gr.Image(type="pil", label="Image")
|
| 146 |
image_submit = gr.Button("Submit", elem_classes="submit-btn")
|
| 147 |
+
model_choice = gr.Radio(
|
| 148 |
+
choices=["Qwen2.5-VL-7B-Instruct", "Qwen2.5-VL-3B-Instruct"],
|
| 149 |
+
label="Select Model",
|
| 150 |
+
value="Qwen2.5-VL-7B-Instruct"
|
| 151 |
)
|
| 152 |
with gr.Accordion("Advanced options", open=False):
|
| 153 |
max_new_tokens = gr.Slider(label="Max new tokens", minimum=1, maximum=MAX_MAX_NEW_TOKENS, step=1, value=DEFAULT_MAX_NEW_TOKENS)
|
|
|
|
| 163 |
|
| 164 |
with gr.Accordion("(Result.md)", open=False):
|
| 165 |
markdown_output = gr.Markdown()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
image_submit.click(
|
| 168 |
fn=process_image,
|
data.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
|
| 3 |
+
def load_jsonl(file_path) -> list[dict]:
|
| 4 |
+
result = []
|
| 5 |
+
with open(file_path, 'r', encoding='utf-8') as file:
|
| 6 |
+
for line in file:
|
| 7 |
+
if not line.strip() or line.startswith('#') or line.startswith('//'):
|
| 8 |
+
continue
|
| 9 |
+
json_line = json.loads(line)
|
| 10 |
+
result.append(json_line)
|
| 11 |
+
return result
|
data_experiments.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Union
|
| 2 |
+
from collections import defaultdict
|
| 3 |
+
|
| 4 |
+
from data import load_jsonl
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
all_experiments = load_jsonl('experiments.jsonl')
|
| 8 |
+
|
| 9 |
+
experiment_ids_by_product_id = defaultdict(list)
|
| 10 |
+
for experiment in all_experiments:
|
| 11 |
+
product_id = experiment.get('product_id')
|
| 12 |
+
if product_id is not None:
|
| 13 |
+
experiment_ids_by_product_id[product_id].append(experiment["id"])
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def get_experiment_by_id(experiment_id: int) -> Union[dict, None]:
|
| 17 |
+
for experiment in all_experiments:
|
| 18 |
+
if experiment['id'] == experiment_id:
|
| 19 |
+
return experiment
|
| 20 |
+
return None
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def filter_experiments(
|
| 24 |
+
experiments: Union[list[dict], None] = None,
|
| 25 |
+
product_id: Union[str, list[str], None] = None,
|
| 26 |
+
experiment_id: Union[int, list[int], None] = None,
|
| 27 |
+
) -> list[dict]:
|
| 28 |
+
filtered_experiments = experiments
|
| 29 |
+
if filtered_experiments is None:
|
| 30 |
+
filtered_experiments = all_experiments
|
| 31 |
+
if product_id is not None:
|
| 32 |
+
if isinstance(product_id, str):
|
| 33 |
+
product_id = {product_id}
|
| 34 |
+
filtered_experiments = [exp for exp in filtered_experiments if exp.get('product_id') in product_id]
|
| 35 |
+
if experiment_id is not None:
|
| 36 |
+
if isinstance(experiment_id, int):
|
| 37 |
+
experiment_id = {experiment_id}
|
| 38 |
+
filtered_experiments = [exp for exp in filtered_experiments if exp['id'] in experiment_id]
|
| 39 |
+
return filtered_experiments
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def get_experiment(
|
| 43 |
+
experiments: Union[list[dict], None] = None,
|
| 44 |
+
product_id: Union[str, list[str], None] = None,
|
| 45 |
+
experiment_id: Union[int, None] = None,
|
| 46 |
+
) -> Union[dict, None]:
|
| 47 |
+
filtered_experiments = filter_experiments(
|
| 48 |
+
experiments=experiments,
|
| 49 |
+
product_id=product_id,
|
| 50 |
+
experiment_id=experiment_id
|
| 51 |
+
)
|
| 52 |
+
if filtered_experiments:
|
| 53 |
+
return filtered_experiments[0]
|
| 54 |
+
else:
|
| 55 |
+
return None
|
data_photos.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Union
|
| 2 |
+
from enum import Enum
|
| 3 |
+
|
| 4 |
+
from data import load_jsonl
|
| 5 |
+
from data_experiments import experiment_ids_by_product_id
|
| 6 |
+
|
| 7 |
+
class PhotoModerationState(Enum):
|
| 8 |
+
INAPPROPRIATE = "inappropriate"
|
| 9 |
+
SAFE = "safe"
|
| 10 |
+
SAFE_FOR_SHARING = "safe_for_sharing"
|
| 11 |
+
UNKNOWN = "unknown"
|
| 12 |
+
|
| 13 |
+
class PhotoApprovalState(Enum):
|
| 14 |
+
APPROVED = "approved"
|
| 15 |
+
FAILED = "failed"
|
| 16 |
+
SUPERSEDED = "superseded"
|
| 17 |
+
UNKNOWN = "unknown"
|
| 18 |
+
|
| 19 |
+
all_photos = load_jsonl('mobile_photo_uploads_2.jsonl')
|
| 20 |
+
|
| 21 |
+
def get_photo_by_id(photo_id: str) -> Union[dict, None]:
|
| 22 |
+
for photo in all_photos:
|
| 23 |
+
if photo['uid'] == photo_id:
|
| 24 |
+
return photo
|
| 25 |
+
return None
|
| 26 |
+
|
| 27 |
+
def get_photo_url(photo: dict) -> str:
|
| 28 |
+
uid = photo['uid']
|
| 29 |
+
url = f'https://res.cloudinary.com/mel-science/image/upload/c_limit,w_1024,h_1024/v1/dotcomprodmobup/{uid}.jpg'
|
| 30 |
+
return url
|
| 31 |
+
|
| 32 |
+
def filter_photos(
|
| 33 |
+
photos: Union[list[dict], None] = None,
|
| 34 |
+
experiment_id: Union[int, list[int], None] = None,
|
| 35 |
+
product_id: Union[str, list[str], None] = None,
|
| 36 |
+
uid: Union[str, set[str], None] = None,
|
| 37 |
+
is_sharing_requested: Union[bool, None] = None,
|
| 38 |
+
moderation_state: Union[set[PhotoModerationState], None] = None,
|
| 39 |
+
approval_state: Union[set[PhotoApprovalState], None] = None,
|
| 40 |
+
) -> list[dict]:
|
| 41 |
+
filtered_photos = photos
|
| 42 |
+
if filtered_photos is None:
|
| 43 |
+
filtered_photos = all_photos
|
| 44 |
+
if experiment_id is not None:
|
| 45 |
+
if isinstance(experiment_id, int):
|
| 46 |
+
experiment_id = {experiment_id}
|
| 47 |
+
filtered_photos = [photo for photo in filtered_photos if int(photo.get('experiment_id')) in experiment_id]
|
| 48 |
+
if product_id is not None:
|
| 49 |
+
if isinstance(product_id, str):
|
| 50 |
+
product_id = {product_id}
|
| 51 |
+
product_experiment_ids = set()
|
| 52 |
+
for id in product_id:
|
| 53 |
+
product_experiment_ids.update(experiment_ids_by_product_id.get(id, []))
|
| 54 |
+
filtered_photos = [photo for photo in filtered_photos if int(photo.get('experiment_id')) in product_experiment_ids]
|
| 55 |
+
if uid is not None:
|
| 56 |
+
if isinstance(uid, str):
|
| 57 |
+
uid = {uid}
|
| 58 |
+
filtered_photos = [photo for photo in filtered_photos if photo.get('uid') in uid]
|
| 59 |
+
if is_sharing_requested is not None:
|
| 60 |
+
filtered_photos = [photo for photo in filtered_photos if photo.get('is_sharing_requested') == str(is_sharing_requested)]
|
| 61 |
+
if moderation_state is not None:
|
| 62 |
+
values = {state.value for state in moderation_state}
|
| 63 |
+
filtered_photos = [photo for photo in filtered_photos if photo.get('moderation_state') in values]
|
| 64 |
+
if approval_state is not None:
|
| 65 |
+
values = {state.value for state in approval_state}
|
| 66 |
+
filtered_photos = [photo for photo in filtered_photos if photo.get('approval_state') in values]
|
| 67 |
+
return filtered_photos
|
| 68 |
+
|
| 69 |
+
def get_photo(
|
| 70 |
+
photos: Union[list[dict], None] = None,
|
| 71 |
+
experiment_id: Union[int, None] = None,
|
| 72 |
+
uid: Union[str, set[str], None] = None,
|
| 73 |
+
is_sharing_requested: Union[bool, None] = None,
|
| 74 |
+
moderation_state: Union[set[PhotoModerationState], None] = None,
|
| 75 |
+
approval_state: Union[set[PhotoApprovalState], None] = None,
|
| 76 |
+
) -> Union[dict, None]:
|
| 77 |
+
filtered_photos = filter_photos(
|
| 78 |
+
photos=photos,
|
| 79 |
+
experiment_id=experiment_id,
|
| 80 |
+
uid=uid,
|
| 81 |
+
is_sharing_requested=is_sharing_requested,
|
| 82 |
+
moderation_state=moderation_state,
|
| 83 |
+
approval_state=approval_state,
|
| 84 |
+
)
|
| 85 |
+
if not filtered_photos:
|
| 86 |
+
return None
|
| 87 |
+
return filtered_photos[0]
|
experiments.jsonl
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
llm_messages_v1.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
|
| 2 |
+
|
| 3 |
+
from data import get_photo_url
|
| 4 |
+
|
| 5 |
+
def format_experiment(experiment: dict) -> str:
|
| 6 |
+
lines = []
|
| 7 |
+
|
| 8 |
+
lines.append(f"Experiment: {experiment['title']}")
|
| 9 |
+
lines.append(f"Description: {experiment['short_description']}")
|
| 10 |
+
|
| 11 |
+
experiment_steps = experiment.get('steps', [])
|
| 12 |
+
if experiment_steps:
|
| 13 |
+
lines.append("Steps:")
|
| 14 |
+
step_index = 1
|
| 15 |
+
for step in experiment_steps:
|
| 16 |
+
step_text = step.get('text', '').strip()
|
| 17 |
+
if step_text:
|
| 18 |
+
lines.append(f" {step_index}. {step_text}")
|
| 19 |
+
step_index += 1
|
| 20 |
+
|
| 21 |
+
experiment_result = experiment.get('expected_result', "").strip()
|
| 22 |
+
if experiment_result:
|
| 23 |
+
lines.append(f"Expected result: {experiment_result}")
|
| 24 |
+
|
| 25 |
+
combined = "\n".join(lines)
|
| 26 |
+
return combined
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def format_system_message(experiment: dict) -> SystemMessage:
|
| 30 |
+
lines = []
|
| 31 |
+
lines.append("You are a photo moderation assistant for science experiments.")
|
| 32 |
+
lines.append("Your task is to determine if the provided photo is a succeful result of the experiment, completed setup or user is on the right way to result. And doesn't contain any inappropriate content. Or not.")
|
| 33 |
+
lines.append("")
|
| 34 |
+
lines.append("Here is the experiment details:")
|
| 35 |
+
experiment_text = format_experiment(experiment)
|
| 36 |
+
lines.append(experiment_text)
|
| 37 |
+
|
| 38 |
+
combined = "\n".join(lines)
|
| 39 |
+
return SystemMessage(content=combined)
|
| 40 |
+
|
| 41 |
+
def format_human_message(experiment: dict, photo: dict) -> HumanMessage:
|
| 42 |
+
lines = []
|
| 43 |
+
lines.append("Here is the photo to check")
|
| 44 |
+
# lines.append("Please analyze the photo and determine if it is a successful result of the experiment, completed setup or user is on the right way to result. And doesn't contain any inappropriate content.")
|
| 45 |
+
lines.append("Result options:")
|
| 46 |
+
lines.append("- `approved`: photo is a successful result of the experiment")
|
| 47 |
+
lines.append("- `partial`: photo is something closed to the experiment, but it is not a final successful result (e.g. not all steps are completed, or parts of result are not visible)")
|
| 48 |
+
# lines.append("- `inappropriate`: photo contains inappropriate content (including faces of children)")
|
| 49 |
+
lines.append("- `failed`: photo is not a successful result of the experiment, but doesn't contain inappropriate content")
|
| 50 |
+
# lines.append("Please analyze the photo and determine if it is a successful result of the experiment.")
|
| 51 |
+
lines.append("Answer in the following format:")
|
| 52 |
+
lines.append("```json")
|
| 53 |
+
lines.append('{"result": "approved" | "partial" | "failed", "reason": "your reason for the decision"}')
|
| 54 |
+
lines.append("```")
|
| 55 |
+
combined = "\n".join(lines)
|
| 56 |
+
photo_url = get_photo_url(photo)
|
| 57 |
+
return HumanMessage(content=[
|
| 58 |
+
{"type": "text", "text": combined},
|
| 59 |
+
{"type": "image_url", "image_url": {"url": photo_url}}
|
| 60 |
+
])
|
| 61 |
+
|
| 62 |
+
def format_ai_message(experiment: dict, photo: dict) -> AIMessage:
|
| 63 |
+
is_approved = photo.get('approval_state', 'unknown') == 'approved'
|
| 64 |
+
result = "approved" if is_approved else "failed"
|
| 65 |
+
reason = photo.get('review_comment', '').strip()
|
| 66 |
+
|
| 67 |
+
lines = []
|
| 68 |
+
lines.append("```json")
|
| 69 |
+
lines.append("{" + f'"result": "{result}", "reason": "{reason}"' + "}")
|
| 70 |
+
lines.append("```")
|
| 71 |
+
combined = "\n".join(lines)
|
| 72 |
+
|
| 73 |
+
return AIMessage(content=[
|
| 74 |
+
{"type": "text", "text": combined},
|
| 75 |
+
])
|
llm_messages_v2.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
|
| 2 |
+
|
| 3 |
+
from data import get_photo_url
|
| 4 |
+
|
| 5 |
+
def format_experiment(experiment: dict) -> str:
|
| 6 |
+
lines = []
|
| 7 |
+
|
| 8 |
+
lines.append(f"Experiment: {experiment['title']}")
|
| 9 |
+
lines.append(f"Description: {experiment['short_description']}")
|
| 10 |
+
|
| 11 |
+
experiment_steps = experiment.get('steps', [])
|
| 12 |
+
if experiment_steps:
|
| 13 |
+
lines.append("Steps:")
|
| 14 |
+
step_index = 1
|
| 15 |
+
for step in experiment_steps:
|
| 16 |
+
step_text = step.get('text', '').strip()
|
| 17 |
+
if step_text:
|
| 18 |
+
lines.append(f" {step_index}. {step_text}")
|
| 19 |
+
step_index += 1
|
| 20 |
+
|
| 21 |
+
experiment_result = experiment.get('expected_result', "").strip()
|
| 22 |
+
if experiment_result:
|
| 23 |
+
lines.append(f"Expected result: {experiment_result}")
|
| 24 |
+
|
| 25 |
+
combined = "\n".join(lines)
|
| 26 |
+
return combined
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def format_system_message(experiment: dict) -> SystemMessage:
|
| 30 |
+
lines = []
|
| 31 |
+
lines.append("You are a photo moderation assistant for science experiments.")
|
| 32 |
+
lines.append("Your task is to determine if the provided photo is a succeful result of the experiment, completed setup or user is on the right way to result. And doesn't contain any inappropriate content. Or not.")
|
| 33 |
+
# lines.append("")
|
| 34 |
+
# lines.append("Here is the experiment details:")
|
| 35 |
+
# experiment_text = format_experiment(experiment)
|
| 36 |
+
# lines.append(experiment_text)
|
| 37 |
+
|
| 38 |
+
combined = "\n".join(lines)
|
| 39 |
+
return SystemMessage(content=combined)
|
| 40 |
+
|
| 41 |
+
def format_human_message(experiment: dict, photo: dict) -> HumanMessage:
|
| 42 |
+
lines = []
|
| 43 |
+
# lines.append("Here is the photo to check")
|
| 44 |
+
# lines.append("Please analyze the photo and determine if it is a successful result of the experiment.")
|
| 45 |
+
lines.append("Answer in the following format:")
|
| 46 |
+
lines.append("```json")
|
| 47 |
+
lines.append('{"result": "approved" | "failed"}')
|
| 48 |
+
lines.append("```")
|
| 49 |
+
combined = "\n".join(lines)
|
| 50 |
+
photo_url = get_photo_url(photo)
|
| 51 |
+
return HumanMessage(content=[
|
| 52 |
+
{"type": "text", "text": combined},
|
| 53 |
+
{"type": "image_url", "image_url": {"url": photo_url}}
|
| 54 |
+
])
|
| 55 |
+
|
| 56 |
+
def format_ai_message(experiment: dict, photo: dict) -> AIMessage:
|
| 57 |
+
is_approved = photo.get('approval_state', 'unknown') == 'approved'
|
| 58 |
+
result = "approved" if is_approved else "failed"
|
| 59 |
+
|
| 60 |
+
lines = []
|
| 61 |
+
lines.append("```json")
|
| 62 |
+
lines.append("{" + f'"result": "{result}"' + "}")
|
| 63 |
+
lines.append("```")
|
| 64 |
+
combined = "\n".join(lines)
|
| 65 |
+
|
| 66 |
+
return AIMessage(content=[
|
| 67 |
+
{"type": "text", "text": combined},
|
| 68 |
+
])
|
llm_messages_v3.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
|
| 2 |
+
|
| 3 |
+
from data import get_photo_url
|
| 4 |
+
|
| 5 |
+
def format_experiment(experiment: dict) -> str:
|
| 6 |
+
lines = []
|
| 7 |
+
|
| 8 |
+
lines.append(f"Experiment: {experiment['title']}")
|
| 9 |
+
lines.append(f"Description: {experiment['short_description']}")
|
| 10 |
+
|
| 11 |
+
experiment_steps = experiment.get('steps', [])
|
| 12 |
+
if experiment_steps:
|
| 13 |
+
lines.append("Steps:")
|
| 14 |
+
step_index = 1
|
| 15 |
+
for step in experiment_steps:
|
| 16 |
+
step_text = step.get('text', '').strip()
|
| 17 |
+
if step_text:
|
| 18 |
+
lines.append(f" {step_index}. {step_text}")
|
| 19 |
+
step_index += 1
|
| 20 |
+
|
| 21 |
+
experiment_result = experiment.get('expected_result', "").strip()
|
| 22 |
+
if experiment_result:
|
| 23 |
+
lines.append(f"Expected result: {experiment_result}")
|
| 24 |
+
|
| 25 |
+
combined = "\n".join(lines)
|
| 26 |
+
return combined
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def format_system_message(experiment: dict) -> SystemMessage:
|
| 30 |
+
lines = []
|
| 31 |
+
lines.append("You are a photo moderation assistant for science experiments.")
|
| 32 |
+
lines.append("Your task is to determine if the provided photo is a succeful result of the experiment, completed setup or user is on the right way to result. And doesn't contain any inappropriate content. Or not.")
|
| 33 |
+
# lines.append("")
|
| 34 |
+
# lines.append("Here is the experiment details:")
|
| 35 |
+
# experiment_text = format_experiment(experiment)
|
| 36 |
+
# lines.append(experiment_text)
|
| 37 |
+
|
| 38 |
+
combined = "\n".join(lines)
|
| 39 |
+
return SystemMessage(content=combined)
|
| 40 |
+
|
| 41 |
+
def format_human_message(experiment: dict, photo: dict) -> HumanMessage:
|
| 42 |
+
lines = []
|
| 43 |
+
|
| 44 |
+
lines.append("Here is the experiment details:")
|
| 45 |
+
experiment_text = format_experiment(experiment)
|
| 46 |
+
lines.append(experiment_text)
|
| 47 |
+
lines.append("")
|
| 48 |
+
|
| 49 |
+
lines.append("Your task is to determine if the provided photo is a succeful result of the experiment, completed setup or user is on the right way to result. And doesn't contain any inappropriate content. Or not.")
|
| 50 |
+
lines.append("Answer in the following format:")
|
| 51 |
+
lines.append("```json")
|
| 52 |
+
lines.append('{"result": "approved" | "failed"}')
|
| 53 |
+
lines.append("```")
|
| 54 |
+
combined = "\n".join(lines)
|
| 55 |
+
photo_url = get_photo_url(photo)
|
| 56 |
+
return HumanMessage(content=[
|
| 57 |
+
{"type": "text", "text": combined},
|
| 58 |
+
{"type": "image_url", "image_url": {"url": photo_url}}
|
| 59 |
+
])
|
| 60 |
+
|
| 61 |
+
def format_ai_message(experiment: dict, photo: dict) -> AIMessage:
|
| 62 |
+
is_approved = photo.get('approval_state', 'unknown') == 'approved'
|
| 63 |
+
result = "approved" if is_approved else "failed"
|
| 64 |
+
|
| 65 |
+
lines = []
|
| 66 |
+
lines.append("```json")
|
| 67 |
+
lines.append("{" + f'"result": "{result}"' + "}")
|
| 68 |
+
lines.append("```")
|
| 69 |
+
combined = "\n".join(lines)
|
| 70 |
+
|
| 71 |
+
return AIMessage(content=[
|
| 72 |
+
{"type": "text", "text": combined},
|
| 73 |
+
])
|