update to include stepwise json creation
Browse files
app.py
CHANGED
|
@@ -10,22 +10,22 @@ os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")
|
|
| 10 |
client = OpenAI()
|
| 11 |
|
| 12 |
# These are the necessary components that make up the Interactions
|
| 13 |
-
class Role(str, Enum):
|
| 14 |
-
PARTNER = 'partner'
|
| 15 |
-
STAFF = 'staff'
|
| 16 |
-
AGRONOMIST = 'agronomist'
|
| 17 |
-
OTHER = 'other'
|
| 18 |
|
| 19 |
-
class Person(BaseModel):
|
| 20 |
-
name: str = Field(..., title="Name", description="Name of this person")
|
| 21 |
-
role: Role = Field(..., title="Role", description="Role of this person")
|
| 22 |
|
| 23 |
-
class Interactions(BaseModel):
|
| 24 |
-
people: List[Person] = Field(..., title="People", description="People involved or mentioned during interaction")
|
| 25 |
-
date: str = Field(..., title="Date of current interaction", description="Date of the interaction")
|
| 26 |
-
nextMeeting: str = Field(..., title="Date of next meeting", description="Proposed date of the next future interaction")
|
| 27 |
-
nextSteps: List[str] = Field(..., title="Next Steps", description="List of individual next steps derived from the interaction")
|
| 28 |
-
summary: str = Field(..., title="Summary", description="Summary of the interaction")
|
| 29 |
|
| 30 |
# These are the components for Farm Activities, Fields, and Plantings
|
| 31 |
class Status(str, Enum):
|
|
@@ -95,6 +95,17 @@ class FarmActivities(BaseModel):
|
|
| 95 |
name: str = Field(..., title="Name", description="The name of the agricultural field.")
|
| 96 |
description: str = Field(..., title="Description", description="The description of the agricultural field.")
|
| 97 |
plantings: List[Planting] = Field(..., title="Plantings", description="All of the plantings which have occurred on this field.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
|
| 99 |
# These are the components for Trials
|
| 100 |
# TBD
|
|
@@ -131,13 +142,84 @@ def generate_json(specification, model_version):
|
|
| 131 |
except Exception as e:
|
| 132 |
return {"error": "Failed to generate valid JSON. " + str(e)}
|
| 133 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
|
| 135 |
-
def process_specifications(data, model_version, json_creation):
|
| 136 |
# This method just drives the process
|
| 137 |
if json_creation == "Single JSON Creation":
|
| 138 |
resulting_schema = generate_json(data, model_version)
|
| 139 |
elif json_creation == "Step-wise JSON Creation":
|
| 140 |
-
|
| 141 |
return resulting_schema
|
| 142 |
|
| 143 |
with gr.Blocks() as demo:
|
|
@@ -147,6 +229,13 @@ with gr.Blocks() as demo:
|
|
| 147 |
|
| 148 |
additional_json_creation_options = gr.Radio(["Parse from one big input text", "Explicit specific pieces"], label="Additional Step-wise JSON Options", visible=False)
|
| 149 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
output_box = gr.Textbox(label="JSON Data Output")
|
| 151 |
|
| 152 |
def update_visibility(radio):
|
|
@@ -155,12 +244,21 @@ with gr.Blocks() as demo:
|
|
| 155 |
return gr.Radio(visible=bool(1))
|
| 156 |
else:
|
| 157 |
return gr.Radio(visible=bool(0))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
|
| 159 |
json_creation_input.change(update_visibility, json_creation_input, additional_json_creation_options)
|
|
|
|
|
|
|
| 160 |
submit_button = gr.Button("Generate JSON")
|
| 161 |
submit_button.click(
|
| 162 |
fn=process_specifications,
|
| 163 |
-
inputs=[data_input, model_version_input, json_creation_input, additional_json_creation_options],
|
| 164 |
outputs=[output_box]
|
| 165 |
)
|
| 166 |
|
|
|
|
| 10 |
client = OpenAI()
|
| 11 |
|
| 12 |
# These are the necessary components that make up the Interactions
|
| 13 |
+
#class Role(str, Enum):
|
| 14 |
+
# PARTNER = 'partner'
|
| 15 |
+
# STAFF = 'staff'
|
| 16 |
+
# AGRONOMIST = 'agronomist'
|
| 17 |
+
# OTHER = 'other'
|
| 18 |
|
| 19 |
+
#class Person(BaseModel):
|
| 20 |
+
# name: str = Field(..., title="Name", description="Name of this person")
|
| 21 |
+
# role: Role = Field(..., title="Role", description="Role of this person")
|
| 22 |
|
| 23 |
+
#class Interactions(BaseModel):
|
| 24 |
+
# people: List[Person] = Field(..., title="People", description="People involved or mentioned during interaction")
|
| 25 |
+
# date: str = Field(..., title="Date of current interaction", description="Date of the interaction")
|
| 26 |
+
# nextMeeting: str = Field(..., title="Date of next meeting", description="Proposed date of the next future interaction")
|
| 27 |
+
# nextSteps: List[str] = Field(..., title="Next Steps", description="List of individual next steps derived from the interaction")
|
| 28 |
+
# summary: str = Field(..., title="Summary", description="Summary of the interaction")
|
| 29 |
|
| 30 |
# These are the components for Farm Activities, Fields, and Plantings
|
| 31 |
class Status(str, Enum):
|
|
|
|
| 95 |
name: str = Field(..., title="Name", description="The name of the agricultural field.")
|
| 96 |
description: str = Field(..., title="Description", description="The description of the agricultural field.")
|
| 97 |
plantings: List[Planting] = Field(..., title="Plantings", description="All of the plantings which have occurred on this field.")
|
| 98 |
+
|
| 99 |
+
# These are extra for the modular approach
|
| 100 |
+
class FarmActivitiesLite(BaseModel):
|
| 101 |
+
name: str = Field(..., title="Name", description="The name of the agricultural field.")
|
| 102 |
+
description: str = Field(..., title="Description", description="The description of the agricultural field.")
|
| 103 |
+
|
| 104 |
+
class PlantingLite(BaseModel):
|
| 105 |
+
name: str = Field(..., title="Name", description="The name of the planting")
|
| 106 |
+
status: Status = Field(..., title="Status", description="The status of the planting. \"active\" is a planting which is currently still in the field. \"archived\" is a planting which is no longer in the field (has been terminated or harvested)")
|
| 107 |
+
crop: List[str] = Field(..., title="Crop", description="A list of the crops in this planting")
|
| 108 |
+
variety: List[str] = Field(..., title="Variety", description="A list of the crop varieties in this planting")
|
| 109 |
|
| 110 |
# These are the components for Trials
|
| 111 |
# TBD
|
|
|
|
| 142 |
except Exception as e:
|
| 143 |
return {"error": "Failed to generate valid JSON. " + str(e)}
|
| 144 |
|
| 145 |
+
# This is for the step-wise JSON creation
|
| 146 |
+
def generate_json_pieces(specification, model_version, additional_json_creation_options, field_data_input, planting_data_input, logs_data_input, soil_data_input, yield_data_input):
|
| 147 |
+
|
| 148 |
+
if additional_json_creation_options == "Explicit specific pieces":
|
| 149 |
+
|
| 150 |
+
try:
|
| 151 |
+
# Call OpenAI API to generate structured output based on prompt
|
| 152 |
+
field_response = client.beta.chat.completions.parse(
|
| 153 |
+
model=model_version, # Use GPT model that supports structured output
|
| 154 |
+
messages=[
|
| 155 |
+
{"role": "system", "content": "Extract the field information."},
|
| 156 |
+
{"role": "user", "content": field_data_input}
|
| 157 |
+
],
|
| 158 |
+
response_format=FarmActivitiesLite,
|
| 159 |
+
)
|
| 160 |
+
|
| 161 |
+
plant_response = client.beta.chat.completions.parse(
|
| 162 |
+
model=model_version, # Use GPT model that supports structured output
|
| 163 |
+
messages=[
|
| 164 |
+
{"role": "system", "content": "Extract the planting information."},
|
| 165 |
+
{"role": "user", "content": planting_data_input}
|
| 166 |
+
],
|
| 167 |
+
response_format=PlantingLite,
|
| 168 |
+
)
|
| 169 |
+
|
| 170 |
+
log_response = client.beta.chat.completions.parse(
|
| 171 |
+
model=model_version, # Use GPT model that supports structured output
|
| 172 |
+
messages=[
|
| 173 |
+
{"role": "system", "content": "Extract the planting information."},
|
| 174 |
+
{"role": "user", "content": logs_data_input}
|
| 175 |
+
],
|
| 176 |
+
response_format=Log,
|
| 177 |
+
)
|
| 178 |
+
|
| 179 |
+
soil_response = client.beta.chat.completions.parse(
|
| 180 |
+
model=model_version, # Use GPT model that supports structured output
|
| 181 |
+
messages=[
|
| 182 |
+
{"role": "system", "content": "Extract the planting information."},
|
| 183 |
+
{"role": "user", "content": soil_data_input}
|
| 184 |
+
],
|
| 185 |
+
response_format=Soil,
|
| 186 |
+
)
|
| 187 |
+
|
| 188 |
+
yield_response = client.beta.chat.completions.parse(
|
| 189 |
+
model=model_version, # Use GPT model that supports structured output
|
| 190 |
+
messages=[
|
| 191 |
+
{"role": "system", "content": "Extract the planting information."},
|
| 192 |
+
{"role": "user", "content": yield_data_input}
|
| 193 |
+
],
|
| 194 |
+
response_format=Yield,
|
| 195 |
+
)
|
| 196 |
+
|
| 197 |
+
combined_json = field_response.choices[0].message.parsed.copy()
|
| 198 |
+
combined_json["plantings"] = plant_response.choices[0].message.parsed
|
| 199 |
+
combined_json["plantings"]["logs"] = log_response.choices[0].message.parsed
|
| 200 |
+
combined_json["plantings"]["soil"] = soil_response.choices[0].message.parsed
|
| 201 |
+
combined_json["plantings"]["yield"] = yield_response.choices[0].message.parsed
|
| 202 |
+
|
| 203 |
+
print(combined_json) # debugging
|
| 204 |
+
|
| 205 |
+
pretty_json = combined_json.json()
|
| 206 |
+
|
| 207 |
+
if 'error' in response:
|
| 208 |
+
raise ValueError(f"API error: {response['error']['message']}")
|
| 209 |
+
|
| 210 |
+
return pretty_json
|
| 211 |
+
|
| 212 |
+
except ValidationError as e:
|
| 213 |
+
return {"error": str(e)}
|
| 214 |
+
except Exception as e:
|
| 215 |
+
return {"error": "Failed to generate valid JSON. " + str(e)}
|
| 216 |
|
| 217 |
+
def process_specifications(data, model_version, json_creation, additional_json_creation_options, field_data_input, planting_data_input, logs_data_input, soil_data_input, yield_data_input):
|
| 218 |
# This method just drives the process
|
| 219 |
if json_creation == "Single JSON Creation":
|
| 220 |
resulting_schema = generate_json(data, model_version)
|
| 221 |
elif json_creation == "Step-wise JSON Creation":
|
| 222 |
+
resulting_schema = generate_json_pieces(data, model_version, additional_json_creation_options, field_data_input, planting_data_input, logs_data_input, soil_data_input, yield_data_input)
|
| 223 |
return resulting_schema
|
| 224 |
|
| 225 |
with gr.Blocks() as demo:
|
|
|
|
| 229 |
|
| 230 |
additional_json_creation_options = gr.Radio(["Parse from one big input text", "Explicit specific pieces"], label="Additional Step-wise JSON Options", visible=False)
|
| 231 |
|
| 232 |
+
# Explicit Specific Pieces
|
| 233 |
+
field_data_input = gr.Textbox(label="Enter your data for field", placeholder="Field Name and Description", visible=False)
|
| 234 |
+
planting_data_input = gr.Textbox(label="Enter your data for plantings", placeholder="Name, Status (active/archived), Crop, Crop variety", visible=False)
|
| 235 |
+
logs_data_input = gr.Textbox(label="Enter your log data", placeholder="Convention, Date, Description", visible=False)
|
| 236 |
+
soil_data_input = gr.Textbox(label="Enter your soil data", placeholder="Description, Structure, Biology", visible=False)
|
| 237 |
+
yield_data_input = gr.Textbox(label="Enter your yield data", placeholder="Quantity, Quality", visible=False)
|
| 238 |
+
|
| 239 |
output_box = gr.Textbox(label="JSON Data Output")
|
| 240 |
|
| 241 |
def update_visibility(radio):
|
|
|
|
| 244 |
return gr.Radio(visible=bool(1))
|
| 245 |
else:
|
| 246 |
return gr.Radio(visible=bool(0))
|
| 247 |
+
|
| 248 |
+
def update_visibility2(radio):
|
| 249 |
+
value = radio
|
| 250 |
+
if value == "Explicit specific pieces":
|
| 251 |
+
return gr.Textbox(visible=bool(1))
|
| 252 |
+
else:
|
| 253 |
+
return gr.Radio(visible=bool(0))
|
| 254 |
|
| 255 |
json_creation_input.change(update_visibility, json_creation_input, additional_json_creation_options)
|
| 256 |
+
additional_json_creation_options.change(update_visibility_option2, additional_json_creation_options, field_data_input, planting_data_input, logs_data_input, soil_data_input, yield_data_input)
|
| 257 |
+
|
| 258 |
submit_button = gr.Button("Generate JSON")
|
| 259 |
submit_button.click(
|
| 260 |
fn=process_specifications,
|
| 261 |
+
inputs=[data_input, model_version_input, json_creation_input, additional_json_creation_options, field_data_input, planting_data_input, logs_data_input, soil_data_input, yield_data_input],
|
| 262 |
outputs=[output_box]
|
| 263 |
)
|
| 264 |
|