brainsqueeze's picture
Change GET to POST requests to avoid URL character limits
16ab811 verified
raw
history blame
7.14 kB
from typing import List, Dict, Tuple, Union, Optional, Any
import os
import gradio as gr
import requests
import backoff
class OrganizationNotFound(Exception):
"No organization(s) found"
@backoff.on_exception(
backoff.expo,
(requests.exceptions.Timeout, requests.exceptions.ConnectionError),
max_tries=5
)
def _get_json(route: str, **request_kwargs) -> Dict[str, Any] | str:
r = requests.get(
url=f"{os.getenv('LOI_API_URL')}/{route}",
params=request_kwargs,
headers={"x-api-key": os.getenv("LOI_API_KEY")},
timeout=30
)
r.raise_for_status()
return r.json().get("response")
@backoff.on_exception(
backoff.expo,
(requests.exceptions.Timeout, requests.exceptions.ConnectionError),
max_tries=5
)
def _post_json(route: str, *, payload: Dict[str, Any]) -> Dict[str, Any] | str | int:
r = requests.post(
url=f"{os.getenv('LOI_API_URL')}/{route}",
json=payload,
headers={"x-api-key": os.getenv("LOI_API_KEY")},
timeout=30
)
r.raise_for_status()
return r.json().get("response")
def organization_pair_autofill(
recipient_name: str,
recipient_ein: str,
funder_name: str,
funder_ein: str
):
recip_match = _get_json("/organization/search", name=recipient_name, ein=recipient_ein)
if len(recip_match or []) == 0:
# raise OrganizationNotFound()
raise gr.Error("No matching recipient could be found")
gr.Info(f"{recipient_name} found, auto-filling fields...")
funder_match = _get_json("/organization/search", name=funder_name, ein=funder_ein)
if len(funder_match or []) == 0:
# raise OrganizationNotFound()
raise gr.Error("No matching funder could be found")
gr.Info(f"{funder_name} found, auto-filling fields...")
data = _get_json(
"/organization/autofill",
recipient_candid_entity_id=recip_match[0]["candid_entity_id"],
funder_candid_entity_id=funder_match[0]["candid_entity_id"],
)
return (
data.get("recipient_data", {}).get("projects_text"),
data.get("recipient_data", {}).get("capacity_text"),
data.get("recipient_data", {}).get("contact_text"),
data.get("recipient_data", {}).get("data_text"), # accomplishments
data.get("recipient_data", {}).get("mission_statement_text"),
data.get("funder_data", {}).get("mission_statement_text"),
data.get("funding_history_text"),
data.get("recipient_data", {}).get("org_data"),
recip_match[0]["candid_entity_id"],
data.get("funder_data", {}).get("org_data"),
funder_match[0]["candid_entity_id"],
)
def cost_estimator(
recipient_candid_entity_id: Union[int, str],
recipient_data: Dict[str, Any],
funder_data: Dict[str, Any],
program_desc: Optional[str] = None
) -> str:
estimate: str = _post_json(
"budget",
payload={
"recipient_candid_entity_id": recipient_candid_entity_id,
"program_description": program_desc,
"recipient_data": recipient_data,
"funder_data": funder_data,
}
)
return estimate
def identify_vague_statements(text: str) -> Tuple[List[str], List[str], List[str]]:
data = _get_json("/editorialai/vaguestatement", input_section=text)
return (
data.get("vague_statements") or [],
data.get("alternative_texts") or [],
data.get("reasons") or [],
# data.get("alternative_texts") or [],
)
def help_mission_statement(recipient_name: str, recipient_mission_info: str):
return _get_json("/writerhelper/missionstatement", info=recipient_mission_info, org_name=recipient_name)
def draft_letter(
recipient_name: str, funder_name: str, projects: str, amount: str,
recipient_mission_statement: str = "", funder_mission_statement: str = "",
project_name: str = "", project_purpose: str = "",
prior_contact: str = "", connection: str = "",
capacity: str = "", path_to_solution: str = "", recent_accomplishments: str = "",
recipient_history: str = "", mutual_history: str = "",
geo_pop_targets: str = "", project_data_stats: str = "",
desired_objectives: str = "", major_activities: str = "", key_staff: str = "", standout_features: str = "",
success_metric: str = "",
other_funding_sources: str = "",
contact_information: str = ""
):
gr.Info("Writing the letter, please scroll to the top of the page.")
opening: str = _post_json(
"/writer/opening",
payload=dict(
funder_name=funder_name,
recipient_name=recipient_name,
project_name=project_name,
project_purpose=project_purpose,
amount=amount,
prior_contact=prior_contact,
connection=connection
)
)
recipient_description: str = _post_json(
"/writer/org",
payload=dict(
opening=opening,
recipient_mission_statement=recipient_mission_statement,
capacity=capacity,
history=recipient_history,
path=path_to_solution,
accomplishment=recent_accomplishments
)
)
need_statement: str = _post_json(
"/writer/need",
payload=dict(
recipient_desc=recipient_description,
target=geo_pop_targets,
data=project_data_stats,
funder_mission_statement=funder_mission_statement
)
)
project_description: str = _post_json(
"/writer/project",
payload=dict(
need=need_statement,
projects=projects,
desired_objectives=desired_objectives,
major_activities=major_activities,
key_staff=key_staff,
stand_out=standout_features,
success=success_metric
)
)
funding_request: str = _post_json(
"/writer/fund",
payload=dict(
project_desc=project_description,
amount=amount,
funding_history=mutual_history,
other_funding=other_funding_sources
)
)
conclusion: str = _post_json(
"/writer/conclusion",
payload=dict(
funding_request=funding_request,
project_desc=project_description,
follow_up=contact_information
)
)
return (
opening,
recipient_description,
need_statement,
project_description,
funding_request,
conclusion
)
def send_feedback(
context: Dict[str, Any],
letter: Dict[str, Any],
relevance: int,
coherence: int,
fluency: int,
overall_quality: int,
comments: Optional[str] = None,
email: Optional[str] = None
) -> int:
count = _post_json(
"feedback",
payload={
"context": context,
"letter": letter,
"relevance": relevance,
"coherence": coherence,
"fluency": fluency,
"overall_quality": overall_quality,
"comments": comments,
"email": email
}
)
return count