Spaces:
Runtime error
Runtime error
iamspruce
commited on
Commit
·
71192d1
1
Parent(s):
f24a55f
updated fastapi
Browse files- .dockerignore +25 -0
- Dockerfile +8 -23
- app/core/app.py +31 -0
- app/core/config.py +9 -0
- app/core/logging.py +8 -0
- app/core/middleware.py +21 -0
- app/core/prompts.py +30 -0
- app/core/security.py +8 -22
- app/data/en/ablist.yml +697 -0
- app/data/en/condescending.yml +50 -0
- app/data/en/gender.yml +1808 -0
- app/data/en/lgbtq.yml +206 -0
- app/data/en/misc.yml +19 -0
- app/data/en/press.yml +20 -0
- app/data/en/race.yml +370 -0
- app/data/en/slogans.yml +9 -0
- app/data/en/suicide.yml +51 -0
- app/main.py +4 -47
- app/models.py +0 -108
- app/prompts.py +0 -121
- app/routers/conciseness.py +0 -42
- app/routers/grammar.py +52 -53
- app/routers/inclusive_language.py +8 -39
- app/routers/paraphrase.py +9 -36
- app/routers/punctuation.py +0 -67
- app/routers/readability.py +24 -46
- app/routers/rewrite.py +18 -0
- app/routers/sentence_correctness.py +0 -62
- app/routers/summarize.py +0 -39
- app/routers/tone.py +8 -53
- app/routers/translate.py +12 -38
- app/routers/vocabulary.py +0 -42
- app/routers/voice.py +8 -69
- app/schemas/base.py +13 -0
- app/services/__init__.py +0 -0
- app/services/base.py +42 -0
- app/services/conciseness_suggestion.py +30 -0
- app/services/gpt4_rewrite.py +44 -0
- app/services/grammar.py +32 -0
- app/services/inclusive_language.py +98 -0
- app/services/paraphrase.py +39 -0
- app/services/tone_classification.py +36 -0
- app/services/translation.py +40 -0
- app/services/vocabulary_enhancement.py +30 -0
- app/services/voice_detection.py +33 -0
- app/test/test_rewrite.py +15 -0
- app/test_main.py +0 -39
- app/utils/shared.py +4 -0
- requirements.txt +1 -1
- run.py +15 -0
.dockerignore
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Python specific files and directories
|
| 2 |
+
*.pyc
|
| 3 |
+
*.pyo
|
| 4 |
+
__pycache__/
|
| 5 |
+
.pytest_cache/
|
| 6 |
+
.mypy_cache/
|
| 7 |
+
.venv/
|
| 8 |
+
venv/
|
| 9 |
+
env/
|
| 10 |
+
|
| 11 |
+
# Editor/IDE specific files
|
| 12 |
+
.vscode/
|
| 13 |
+
.idea/
|
| 14 |
+
*.sublime-project
|
| 15 |
+
*.sublime-workspace
|
| 16 |
+
|
| 17 |
+
# Common build/distribution files
|
| 18 |
+
dist/
|
| 19 |
+
build/
|
| 20 |
+
*.egg-info/
|
| 21 |
+
.DS_Store
|
| 22 |
+
|
| 23 |
+
# Git specific files
|
| 24 |
+
.git/
|
| 25 |
+
.gitignore
|
Dockerfile
CHANGED
|
@@ -1,43 +1,28 @@
|
|
| 1 |
FROM python:3.10-slim
|
| 2 |
|
| 3 |
-
# Set working directory inside the container
|
| 4 |
WORKDIR /app
|
| 5 |
|
| 6 |
# Install system dependencies
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
RUN apt-get update && apt-get install -y git default-jre && rm -rf /var/lib/apt/lists/*
|
| 10 |
|
| 11 |
-
# Install Python dependencies from requirements.txt
|
| 12 |
-
# Ensure requirements.txt is copied before installing to leverage Docker cache
|
| 13 |
COPY requirements.txt .
|
| 14 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 15 |
|
| 16 |
-
|
| 17 |
-
# This is crucial for resolving the "[E050] Can't find model 'en_core_web_sm'" error
|
| 18 |
RUN python -m spacy download en_core_web_sm
|
| 19 |
|
| 20 |
-
|
| 21 |
-
# This directory will also be used by language-tool-python for its main downloads.
|
| 22 |
ENV HF_HOME=/cache
|
| 23 |
RUN mkdir -p /cache && chmod -R 777 /cache
|
| 24 |
|
| 25 |
-
# ... other Dockerfile content ...
|
| 26 |
-
ENV GRAMMAFREE_API_KEY="admin"
|
| 27 |
|
| 28 |
-
# Explicitly create and set permissions for /.cache
|
| 29 |
-
# This is to address PermissionError: [Errno 13] Permission denied: '/.cache'
|
| 30 |
-
# which language-tool-python might be trying to write to.
|
| 31 |
RUN mkdir -p /.cache && chmod -R 777 /.cache
|
| 32 |
|
| 33 |
-
# Set environment variable for language-tool-python download directory
|
| 34 |
-
# This redirects LanguageTool's primary downloads to the shared /cache directory.
|
| 35 |
-
ENV LANGUAGE_TOOL_DOWNLOAD_DIR=/cache
|
| 36 |
|
| 37 |
-
# Copy the entire application code into the container
|
| 38 |
-
# This copies your 'app' directory, including main.py, routers, models, etc.
|
| 39 |
COPY app ./app
|
| 40 |
|
| 41 |
-
#
|
| 42 |
-
|
| 43 |
-
|
|
|
|
|
|
| 1 |
FROM python:3.10-slim
|
| 2 |
|
|
|
|
| 3 |
WORKDIR /app
|
| 4 |
|
| 5 |
# Install system dependencies
|
| 6 |
+
RUN apt-get update && apt-get install -y git && \
|
| 7 |
+
rm -rf /var/lib/apt/lists/*
|
|
|
|
| 8 |
|
|
|
|
|
|
|
| 9 |
COPY requirements.txt .
|
| 10 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 11 |
|
| 12 |
+
|
|
|
|
| 13 |
RUN python -m spacy download en_core_web_sm
|
| 14 |
|
| 15 |
+
|
|
|
|
| 16 |
ENV HF_HOME=/cache
|
| 17 |
RUN mkdir -p /cache && chmod -R 777 /cache
|
| 18 |
|
|
|
|
|
|
|
| 19 |
|
|
|
|
|
|
|
|
|
|
| 20 |
RUN mkdir -p /.cache && chmod -R 777 /.cache
|
| 21 |
|
|
|
|
|
|
|
|
|
|
| 22 |
|
|
|
|
|
|
|
| 23 |
COPY app ./app
|
| 24 |
|
| 25 |
+
# Expose the port your FastAPI application will run on
|
| 26 |
+
EXPOSE 7860
|
| 27 |
+
|
| 28 |
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7860"]
|
app/core/app.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI
|
| 2 |
+
from fastapi.middleware.gzip import GZipMiddleware
|
| 3 |
+
from app.routers import (
|
| 4 |
+
grammar,
|
| 5 |
+
tone,
|
| 6 |
+
voice,
|
| 7 |
+
inclusive_language,
|
| 8 |
+
readability,
|
| 9 |
+
paraphrase,
|
| 10 |
+
translate,
|
| 11 |
+
rewrite,
|
| 12 |
+
)
|
| 13 |
+
|
| 14 |
+
def create_app() -> FastAPI:
|
| 15 |
+
app = FastAPI()
|
| 16 |
+
app.add_middleware(GZipMiddleware, minimum_size=500)
|
| 17 |
+
|
| 18 |
+
app.include_router(grammar.router)
|
| 19 |
+
app.include_router(tone.router)
|
| 20 |
+
app.include_router(voice.router)
|
| 21 |
+
app.include_router(inclusive_language.router)
|
| 22 |
+
app.include_router(readability.router)
|
| 23 |
+
app.include_router(paraphrase.router)
|
| 24 |
+
app.include_router(translate.router)
|
| 25 |
+
app.include_router(rewrite.router)
|
| 26 |
+
|
| 27 |
+
@app.get("/")
|
| 28 |
+
def root():
|
| 29 |
+
return {"message": "Welcome to Grammafree API"}
|
| 30 |
+
|
| 31 |
+
return app
|
app/core/config.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic_settings import BaseSettings
|
| 2 |
+
|
| 3 |
+
class Settings(BaseSettings):
|
| 4 |
+
inclusive_rules_dir: str = "app/data/en"
|
| 5 |
+
openai_model: str = "gpt-4o"
|
| 6 |
+
openai_temperature: float = 0.7
|
| 7 |
+
openai_max_tokens: int = 512
|
| 8 |
+
|
| 9 |
+
settings = Settings()
|
app/core/logging.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# core/logging.py
|
| 2 |
+
import logging
|
| 3 |
+
|
| 4 |
+
def configure_logging():
|
| 5 |
+
logging.basicConfig(
|
| 6 |
+
level=logging.INFO,
|
| 7 |
+
format="%(asctime)s - %(levelname)s - %(message)s"
|
| 8 |
+
)
|
app/core/middleware.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, Request
|
| 2 |
+
from fastapi.responses import JSONResponse
|
| 3 |
+
from slowapi import Limiter
|
| 4 |
+
from slowapi.util import get_remote_address
|
| 5 |
+
from slowapi.errors import RateLimitExceeded
|
| 6 |
+
import logging
|
| 7 |
+
|
| 8 |
+
limiter = Limiter(key_func=get_remote_address)
|
| 9 |
+
|
| 10 |
+
def setup_middlewares(app: FastAPI):
|
| 11 |
+
@app.exception_handler(Exception)
|
| 12 |
+
async def unhandled_exception_handler(request: Request, exc: Exception):
|
| 13 |
+
logging.exception("Unhandled exception")
|
| 14 |
+
return JSONResponse(status_code=500, content={"detail": "Internal server error"})
|
| 15 |
+
|
| 16 |
+
@app.exception_handler(RateLimitExceeded)
|
| 17 |
+
async def rate_limit_exceeded_handler(request: Request, exc: RateLimitExceeded):
|
| 18 |
+
return JSONResponse(status_code=429, content={"detail": "Rate limit exceeded"})
|
| 19 |
+
|
| 20 |
+
limiter.init_app(app)
|
| 21 |
+
app.state.limiter = limiter
|
app/core/prompts.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
def tone_prompt(text: str, tone: str) -> str:
|
| 2 |
+
return f"Change the tone of this sentence to {tone}: {text.strip()}"
|
| 3 |
+
|
| 4 |
+
def summarize_prompt(text: str) -> str:
|
| 5 |
+
return f"Summarize the following text:\n{text.strip()}"
|
| 6 |
+
|
| 7 |
+
def clarity_prompt(text: str) -> str:
|
| 8 |
+
return f"Improve the clarity of the following sentence:\n{text.strip()}"
|
| 9 |
+
|
| 10 |
+
def conciseness_prompt(text: str) -> str:
|
| 11 |
+
return f"Make the following sentence more concise:\n{text.strip()}"
|
| 12 |
+
|
| 13 |
+
def rewrite_prompt(text: str, instruction: str) -> str:
|
| 14 |
+
return f"{instruction.strip()}\n{text.strip()}"
|
| 15 |
+
|
| 16 |
+
def vocabulary_prompt(text: str) -> str:
|
| 17 |
+
return (
|
| 18 |
+
"You are an expert vocabulary enhancer. Rewrite the following text "
|
| 19 |
+
"by replacing common and simple words with more sophisticated, "
|
| 20 |
+
"precise, and contextually appropriate synonyms. Do not change "
|
| 21 |
+
"the original meaning. Maintain the tone.\n" + text.strip()
|
| 22 |
+
)
|
| 23 |
+
|
| 24 |
+
def concise_prompt(text: str) -> str:
|
| 25 |
+
return (
|
| 26 |
+
"You are an expert editor specializing in conciseness. "
|
| 27 |
+
"Rewrite the following text to be more concise and to the point, "
|
| 28 |
+
"removing any verbose phrases, redundant words, or unnecessary clauses. "
|
| 29 |
+
"Maintain the original meaning and professional tone.\n" + text.strip()
|
| 30 |
+
)
|
app/core/security.py
CHANGED
|
@@ -1,25 +1,11 @@
|
|
| 1 |
-
from fastapi import Header, HTTPException
|
| 2 |
import os
|
|
|
|
| 3 |
|
| 4 |
-
|
| 5 |
-
# In a production environment, this should be a more robust and securely managed key.
|
| 6 |
-
# Load API_KEY from an environment variable for security.
|
| 7 |
-
# Fallback to a default for local development if not set, but warn about it.
|
| 8 |
-
API_KEY = os.getenv("GRAMMAFREE_API_KEY", "12345") # Use a strong default for production!
|
| 9 |
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
Args:
|
| 18 |
-
x_api_key (str): The API key expected in the 'X-API-Key' header.
|
| 19 |
-
|
| 20 |
-
Raises:
|
| 21 |
-
HTTPException: If the provided API key does not match the expected API_KEY.
|
| 22 |
-
"""
|
| 23 |
-
if x_api_key != API_KEY:
|
| 24 |
-
# Raise an HTTPException with 401 Unauthorized status if the key is invalid.
|
| 25 |
-
raise HTTPException(status_code=401, detail="Unauthorized")
|
|
|
|
|
|
|
| 1 |
import os
|
| 2 |
+
from fastapi import Header, HTTPException, status, Depends
|
| 3 |
|
| 4 |
+
API_KEY = os.getenv("GRAMMAFREE_API_KEY", "12345")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
+
def verify_api_key(x_api_key: str = Header(...)) -> None:
|
| 7 |
+
if not x_api_key or x_api_key != API_KEY:
|
| 8 |
+
raise HTTPException(
|
| 9 |
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
| 10 |
+
detail="Invalid or missing API key"
|
| 11 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/data/en/ablist.yml
ADDED
|
@@ -0,0 +1,697 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- type: basic
|
| 2 |
+
note: Refer to the person, rather than the disability, first.
|
| 3 |
+
considerate: person with learning disabilities
|
| 4 |
+
inconsiderate: learning disabled
|
| 5 |
+
- type: basic
|
| 6 |
+
note: Refer to the person, rather than the disability, first.
|
| 7 |
+
considerate:
|
| 8 |
+
- turned off
|
| 9 |
+
- has a disability
|
| 10 |
+
- person with a disability
|
| 11 |
+
- people with disabilities
|
| 12 |
+
inconsiderate:
|
| 13 |
+
- disabled
|
| 14 |
+
- invalid
|
| 15 |
+
- type: basic
|
| 16 |
+
source: https://ncdj.org/style-guide/
|
| 17 |
+
note: Assumes/implies that a person with a disability is deficient or inferior to others. When possible, specify the functional ability or its restriction.
|
| 18 |
+
considerate:
|
| 19 |
+
- has a disability
|
| 20 |
+
- person with a disability
|
| 21 |
+
- people with disabilities
|
| 22 |
+
inconsiderate:
|
| 23 |
+
- birth defect
|
| 24 |
+
- type: basic
|
| 25 |
+
source: https://ncdj.org/style-guide/
|
| 26 |
+
note: Assumes that a person with a disability has a reduced quality of life.
|
| 27 |
+
considerate:
|
| 28 |
+
- has a disability
|
| 29 |
+
- person with a disability
|
| 30 |
+
- people with disabilities
|
| 31 |
+
inconsiderate:
|
| 32 |
+
- suffers from disabilities
|
| 33 |
+
- suffering from disabilities
|
| 34 |
+
- suffering from a disability
|
| 35 |
+
- afflicted with disabilities
|
| 36 |
+
- afflicted with a disability
|
| 37 |
+
- type: basic
|
| 38 |
+
source: https://ncdj.org/style-guide/
|
| 39 |
+
note: Refer to the person, rather than the disability, first.
|
| 40 |
+
considerate:
|
| 41 |
+
- people with intellectual disabilities
|
| 42 |
+
inconsiderate:
|
| 43 |
+
- intellectually disabled people
|
| 44 |
+
- type: basic
|
| 45 |
+
source: https://ncdj.org/style-guide/
|
| 46 |
+
note: Assumes that a person with an intellectual disability has a reduced quality of life.
|
| 47 |
+
considerate:
|
| 48 |
+
- person with an intellectual disability
|
| 49 |
+
inconsiderate:
|
| 50 |
+
- intellectually disabled
|
| 51 |
+
- has intellectual issues
|
| 52 |
+
- suffers from intellectual disabilities
|
| 53 |
+
- suffering from intellectual disabilities
|
| 54 |
+
- suffering from an intellectual disability
|
| 55 |
+
- afflicted with intellectual disabilities
|
| 56 |
+
- afflicted with a intellectual disability
|
| 57 |
+
- type: basic
|
| 58 |
+
source: https://ncdj.org/style-guide/
|
| 59 |
+
note: Describe the behavior or illness without derogatory words.
|
| 60 |
+
considerate:
|
| 61 |
+
- rude
|
| 62 |
+
- malicious
|
| 63 |
+
- mean
|
| 64 |
+
- disgusting
|
| 65 |
+
- incredible
|
| 66 |
+
- vile
|
| 67 |
+
- person with symptoms of mental illness
|
| 68 |
+
- person with mental illness
|
| 69 |
+
- person with symptoms of a mental disorder
|
| 70 |
+
- person with a mental disorder
|
| 71 |
+
inconsiderate:
|
| 72 |
+
- batshit
|
| 73 |
+
- psycho
|
| 74 |
+
- crazy
|
| 75 |
+
- delirious
|
| 76 |
+
- insane
|
| 77 |
+
- insanity
|
| 78 |
+
- loony
|
| 79 |
+
- lunacy
|
| 80 |
+
- lunatic
|
| 81 |
+
- mentally ill
|
| 82 |
+
- psychopathology
|
| 83 |
+
- mental defective
|
| 84 |
+
- moron
|
| 85 |
+
- moronic
|
| 86 |
+
- nuts
|
| 87 |
+
- mental case
|
| 88 |
+
- mental
|
| 89 |
+
- type: basic
|
| 90 |
+
note: Describe the behavior or illness without derogatory words.
|
| 91 |
+
considerate:
|
| 92 |
+
- incredibly
|
| 93 |
+
inconsiderate:
|
| 94 |
+
- insanely
|
| 95 |
+
- type: basic
|
| 96 |
+
note: When describing a mathematical or programmatic value, using the word “sane” needlessly invokes the topic of mental health. Consider using a domain-specific or neutral term instead.
|
| 97 |
+
considerate:
|
| 98 |
+
- correct
|
| 99 |
+
- adequate
|
| 100 |
+
- sufficient
|
| 101 |
+
- consistent
|
| 102 |
+
- valid
|
| 103 |
+
- coherent
|
| 104 |
+
- sensible
|
| 105 |
+
- reasonable
|
| 106 |
+
inconsiderate: sane
|
| 107 |
+
- type: basic
|
| 108 |
+
note: When describing a mathematical or programmatic value, using the phrase “sanity check” needlessly invokes the topic of mental health. Consider using simply “check”, or a domain-specific or neutral term, instead.
|
| 109 |
+
considerate:
|
| 110 |
+
- check
|
| 111 |
+
- assertion
|
| 112 |
+
- validation
|
| 113 |
+
- smoke test
|
| 114 |
+
inconsiderate: sanity check
|
| 115 |
+
- type: basic
|
| 116 |
+
source: https://ncdj.org/style-guide/
|
| 117 |
+
note: Only use terms describing mental illness when referring to a professionally diagnosed medical condition.
|
| 118 |
+
considerate:
|
| 119 |
+
- fluctuating
|
| 120 |
+
- person with bipolar disorder
|
| 121 |
+
inconsiderate:
|
| 122 |
+
- bipolar
|
| 123 |
+
- type: basic
|
| 124 |
+
source: https://ncdj.org/style-guide/
|
| 125 |
+
note: Only use terms describing mental illness when referring to a professionally diagnosed medical condition.
|
| 126 |
+
considerate:
|
| 127 |
+
- person with schizophrenia
|
| 128 |
+
inconsiderate:
|
| 129 |
+
- schizophrenic
|
| 130 |
+
- schizo
|
| 131 |
+
- type: basic
|
| 132 |
+
source: https://ncdj.org/style-guide/
|
| 133 |
+
note: Assumes a person with schizophrenia experiences a reduced quality of life.
|
| 134 |
+
considerate:
|
| 135 |
+
- person with schizophrenia
|
| 136 |
+
inconsiderate:
|
| 137 |
+
- suffers from schizophrenia
|
| 138 |
+
- suffering from schizophrenia
|
| 139 |
+
- afflicted with schizophrenia
|
| 140 |
+
- manic
|
| 141 |
+
- type: basic
|
| 142 |
+
source: https://ncdj.org/style-guide/
|
| 143 |
+
considerate: accessible parking
|
| 144 |
+
inconsiderate: handicapped parking
|
| 145 |
+
- type: basic
|
| 146 |
+
source: https://ncdj.org/style-guide/
|
| 147 |
+
note: Refer to the person, rather than the disability, first.
|
| 148 |
+
considerate:
|
| 149 |
+
- person with a handicap
|
| 150 |
+
- accessible
|
| 151 |
+
inconsiderate: handicapped
|
| 152 |
+
- type: basic
|
| 153 |
+
source: https://ncdj.org/style-guide/
|
| 154 |
+
note: Refer to the person, rather than the condition, first.
|
| 155 |
+
considerate: person with an amputation
|
| 156 |
+
inconsiderate: amputee
|
| 157 |
+
- type: basic
|
| 158 |
+
note: Refer to the specific disability.
|
| 159 |
+
considerate: person with a limp
|
| 160 |
+
inconsiderate:
|
| 161 |
+
- cripple
|
| 162 |
+
- crippled
|
| 163 |
+
- gimp
|
| 164 |
+
- type: basic
|
| 165 |
+
considerate: person with Down Syndrome
|
| 166 |
+
inconsiderate: mongoloid
|
| 167 |
+
- type: basic
|
| 168 |
+
note: Refer to the person, rather than the condition, first.
|
| 169 |
+
considerate: individual who has had a stroke
|
| 170 |
+
inconsiderate:
|
| 171 |
+
- stroke victim
|
| 172 |
+
- suffering from a stroke
|
| 173 |
+
- victim of a stroke
|
| 174 |
+
- type: basic
|
| 175 |
+
considerate: person who has multiple sclerosis
|
| 176 |
+
inconsiderate:
|
| 177 |
+
- suffers from multiple sclerosis
|
| 178 |
+
- suffering from multiple sclerosis
|
| 179 |
+
- victim of multiple sclerosis
|
| 180 |
+
- multiple sclerosis victim
|
| 181 |
+
- afflicted with multiple sclerosis
|
| 182 |
+
- type: basic
|
| 183 |
+
source: https://ncdj.org/style-guide
|
| 184 |
+
note: Refer to a person's condition as a state, not as an affliction.
|
| 185 |
+
considerate: person who has muscular dystrophy
|
| 186 |
+
inconsiderate:
|
| 187 |
+
- suffers from muscular dystrophy
|
| 188 |
+
- afflicted with muscular dystrophy
|
| 189 |
+
- suffers from MD
|
| 190 |
+
- afflicted with MD
|
| 191 |
+
- type: basic
|
| 192 |
+
considerate: with family support needs
|
| 193 |
+
inconsiderate: family burden
|
| 194 |
+
- type: basic
|
| 195 |
+
considerate:
|
| 196 |
+
- psychiatric hospital
|
| 197 |
+
- mental health hospital
|
| 198 |
+
inconsiderate:
|
| 199 |
+
- asylum
|
| 200 |
+
- type: basic
|
| 201 |
+
considerate:
|
| 202 |
+
- chaos
|
| 203 |
+
- hectic
|
| 204 |
+
- pandemonium
|
| 205 |
+
inconsiderate:
|
| 206 |
+
- bedlam
|
| 207 |
+
- madhouse
|
| 208 |
+
- loony bin
|
| 209 |
+
- type: basic
|
| 210 |
+
source: https://media.specialolympics.org/soi/files/press-kit/2014_FactSheet_Final.pdf
|
| 211 |
+
considerate:
|
| 212 |
+
- Down Syndrome
|
| 213 |
+
inconsiderate:
|
| 214 |
+
- downs syndrome
|
| 215 |
+
- type: basic
|
| 216 |
+
considerate:
|
| 217 |
+
- silly
|
| 218 |
+
- dullard
|
| 219 |
+
- person with Down Syndrome
|
| 220 |
+
- person with developmental disabilities
|
| 221 |
+
- delay
|
| 222 |
+
- hold back
|
| 223 |
+
inconsiderate:
|
| 224 |
+
- retard
|
| 225 |
+
- retarded
|
| 226 |
+
- short bus
|
| 227 |
+
- type: basic
|
| 228 |
+
considerate:
|
| 229 |
+
- sillies
|
| 230 |
+
- dullards
|
| 231 |
+
- people with developmental disabilities
|
| 232 |
+
- people with Down’s Syndrome
|
| 233 |
+
- delays
|
| 234 |
+
- holds back
|
| 235 |
+
inconsiderate: retards
|
| 236 |
+
- type: basic
|
| 237 |
+
note: Only use terms describing mental illness when referring to a professionally diagnosed medical condition.
|
| 238 |
+
considerate:
|
| 239 |
+
- person with a psychotic condition
|
| 240 |
+
- person with psychosis
|
| 241 |
+
inconsiderate:
|
| 242 |
+
- psychotic
|
| 243 |
+
- suffers from psychosis
|
| 244 |
+
- suffering from psychosis
|
| 245 |
+
- afflicted with psychosis
|
| 246 |
+
- victim of psychosis
|
| 247 |
+
- type: basic
|
| 248 |
+
source: https://ncdj.org/style-guide/
|
| 249 |
+
considerate:
|
| 250 |
+
- boring
|
| 251 |
+
- dull
|
| 252 |
+
inconsiderate: lame
|
| 253 |
+
- type: basic
|
| 254 |
+
considerate:
|
| 255 |
+
- person with AIDS
|
| 256 |
+
inconsiderate:
|
| 257 |
+
- suffering from aids
|
| 258 |
+
- suffer from aids
|
| 259 |
+
- suffers from aids
|
| 260 |
+
- afflicted with aids
|
| 261 |
+
- victim of aids
|
| 262 |
+
- aids victim
|
| 263 |
+
- type: basic
|
| 264 |
+
considerate:
|
| 265 |
+
- uses a wheelchair
|
| 266 |
+
inconsiderate:
|
| 267 |
+
- confined to a wheelchair
|
| 268 |
+
- bound to a wheelchair
|
| 269 |
+
- restricted to a wheelchair
|
| 270 |
+
- wheelchair bound
|
| 271 |
+
- type: basic
|
| 272 |
+
source: https://media.specialolympics.org/soi/files/press-kit/2014_FactSheet_Final.pdf
|
| 273 |
+
note: When possible, use the exact discipline of sport.
|
| 274 |
+
considerate:
|
| 275 |
+
- athletes
|
| 276 |
+
- Special Olympics athletes
|
| 277 |
+
inconsiderate:
|
| 278 |
+
- special olympians
|
| 279 |
+
- special olympic athletes
|
| 280 |
+
- type: basic
|
| 281 |
+
source: https://ncdj.org/style-guide/
|
| 282 |
+
note: Can imply that people with disabilities lack the ability to use their bodies well. Sometimes `typical` can be used.
|
| 283 |
+
considerate:
|
| 284 |
+
- non-disabled
|
| 285 |
+
inconsiderate:
|
| 286 |
+
- ablebodied
|
| 287 |
+
- type: basic
|
| 288 |
+
source: https://ncdj.org/style-guide/
|
| 289 |
+
note: Addiction is a neurobiological disease.
|
| 290 |
+
considerate:
|
| 291 |
+
- person with a drug addiction
|
| 292 |
+
- person recovering from a drug addiction
|
| 293 |
+
inconsiderate:
|
| 294 |
+
- addict
|
| 295 |
+
- junkie
|
| 296 |
+
- type: basic
|
| 297 |
+
source: https://ncdj.org/style-guide/
|
| 298 |
+
note: Addiction is a neurobiological disease.
|
| 299 |
+
considerate:
|
| 300 |
+
- people with a drug addiction
|
| 301 |
+
- people recovering from a drug addiction
|
| 302 |
+
inconsiderate:
|
| 303 |
+
- addicts
|
| 304 |
+
- junkies
|
| 305 |
+
- type: basic
|
| 306 |
+
source: https://ncdj.org/style-guide/
|
| 307 |
+
note: Alcoholism is a neurobiological disease.
|
| 308 |
+
considerate:
|
| 309 |
+
- someone with an alcohol problem
|
| 310 |
+
inconsiderate:
|
| 311 |
+
- alcoholic
|
| 312 |
+
- alcohol abuser
|
| 313 |
+
- type: basic
|
| 314 |
+
source: https://ncdj.org/style-guide/
|
| 315 |
+
considerate:
|
| 316 |
+
- deaf
|
| 317 |
+
inconsiderate:
|
| 318 |
+
- deaf and dumb
|
| 319 |
+
- deafmute
|
| 320 |
+
- type: basic
|
| 321 |
+
source: https://ncdj.org/style-guide/
|
| 322 |
+
considerate:
|
| 323 |
+
- person with dementia
|
| 324 |
+
inconsiderate:
|
| 325 |
+
- demented
|
| 326 |
+
- senile
|
| 327 |
+
- type: basic
|
| 328 |
+
source: https://ncdj.org/style-guide/
|
| 329 |
+
considerate:
|
| 330 |
+
- sad
|
| 331 |
+
- blue
|
| 332 |
+
- bummed out
|
| 333 |
+
- person with seasonal affective disorder
|
| 334 |
+
- person with psychotic depression
|
| 335 |
+
- person with postpartum depression
|
| 336 |
+
inconsiderate:
|
| 337 |
+
- depressed
|
| 338 |
+
- type: basic
|
| 339 |
+
source:
|
| 340 |
+
- https://ncdj.org/style-guide/
|
| 341 |
+
- https://www.lpaonline.org/faq-#Midget
|
| 342 |
+
considerate:
|
| 343 |
+
- person with dwarfism
|
| 344 |
+
- little person
|
| 345 |
+
- little people
|
| 346 |
+
- LP
|
| 347 |
+
- person of short stature
|
| 348 |
+
inconsiderate:
|
| 349 |
+
- vertically challenged
|
| 350 |
+
- midget
|
| 351 |
+
- small person
|
| 352 |
+
- dwarf
|
| 353 |
+
- type: basic
|
| 354 |
+
source: https://ncdj.org/style-guide/
|
| 355 |
+
considerate:
|
| 356 |
+
- person with dyslexia
|
| 357 |
+
inconsiderate:
|
| 358 |
+
- dyslexic
|
| 359 |
+
- type: basic
|
| 360 |
+
source: https://ncdj.org/style-guide/
|
| 361 |
+
considerate:
|
| 362 |
+
- person with epilepsy
|
| 363 |
+
inconsiderate:
|
| 364 |
+
- epileptic
|
| 365 |
+
- type: basic
|
| 366 |
+
source: https://ncdj.org/style-guide/
|
| 367 |
+
note: When possible, ask the person what they prefer.
|
| 368 |
+
considerate:
|
| 369 |
+
- hard of hearing
|
| 370 |
+
- partially deaf
|
| 371 |
+
- partial hearing loss
|
| 372 |
+
- deaf
|
| 373 |
+
inconsiderate:
|
| 374 |
+
- hearing impaired
|
| 375 |
+
- hearing impairment
|
| 376 |
+
- type: basic
|
| 377 |
+
source: https://ncdj.org/style-guide/
|
| 378 |
+
considerate:
|
| 379 |
+
- polio
|
| 380 |
+
- person who had polio
|
| 381 |
+
inconsiderate:
|
| 382 |
+
- infantile paralysis
|
| 383 |
+
- suffers from polio
|
| 384 |
+
- suffering from polio
|
| 385 |
+
- suffering from a polio
|
| 386 |
+
- afflicted with polio
|
| 387 |
+
- afflicted with a polio
|
| 388 |
+
- victim of polio
|
| 389 |
+
- type: basic
|
| 390 |
+
source: https://ncdj.org/style-guide/
|
| 391 |
+
considerate:
|
| 392 |
+
- sustain an injury
|
| 393 |
+
- receive an injury
|
| 394 |
+
inconsiderate:
|
| 395 |
+
- suffer from an injury
|
| 396 |
+
- suffers from an injury
|
| 397 |
+
- suffering from an injury
|
| 398 |
+
- afflicted with an injury
|
| 399 |
+
- victim of an injury
|
| 400 |
+
- type: basic
|
| 401 |
+
source: https://ncdj.org/style-guide/
|
| 402 |
+
considerate:
|
| 403 |
+
- sustain injuries
|
| 404 |
+
- receive injuries
|
| 405 |
+
inconsiderate:
|
| 406 |
+
- suffer from injuries
|
| 407 |
+
- suffers from injuries
|
| 408 |
+
- suffering from injuries
|
| 409 |
+
- afflicted with injuries
|
| 410 |
+
- victim of injuries
|
| 411 |
+
- type: basic
|
| 412 |
+
source: https://ncdj.org/style-guide/
|
| 413 |
+
considerate:
|
| 414 |
+
- person with paraplegia
|
| 415 |
+
inconsiderate:
|
| 416 |
+
- paraplegic
|
| 417 |
+
- type: basic
|
| 418 |
+
source: https://ncdj.org/style-guide/
|
| 419 |
+
considerate:
|
| 420 |
+
- person with quadriplegia
|
| 421 |
+
inconsiderate:
|
| 422 |
+
- quadriplegic
|
| 423 |
+
- type: basic
|
| 424 |
+
source: https://ncdj.org/style-guide/
|
| 425 |
+
considerate:
|
| 426 |
+
- person with cerebral palsy
|
| 427 |
+
- twitch
|
| 428 |
+
- flinch
|
| 429 |
+
- hectic
|
| 430 |
+
inconsiderate:
|
| 431 |
+
- spaz
|
| 432 |
+
- type: basic
|
| 433 |
+
source: https://ncdj.org/style-guide/
|
| 434 |
+
considerate:
|
| 435 |
+
- person with cerebral palsy
|
| 436 |
+
- twitch
|
| 437 |
+
- flinch
|
| 438 |
+
inconsiderate:
|
| 439 |
+
- spastic
|
| 440 |
+
- type: basic
|
| 441 |
+
source: https://ncdj.org/style-guide/
|
| 442 |
+
considerate:
|
| 443 |
+
- stuttering
|
| 444 |
+
- disfluency of speech
|
| 445 |
+
inconsiderate:
|
| 446 |
+
- stammering
|
| 447 |
+
- type: basic
|
| 448 |
+
source: https://ncdj.org/style-guide/
|
| 449 |
+
considerate:
|
| 450 |
+
- person who stutters
|
| 451 |
+
inconsiderate:
|
| 452 |
+
- stutterer
|
| 453 |
+
- type: basic
|
| 454 |
+
source: https://ncdj.org/style-guide/
|
| 455 |
+
considerate:
|
| 456 |
+
- Tourette syndrome
|
| 457 |
+
inconsiderate:
|
| 458 |
+
- tourettes syndrome
|
| 459 |
+
- tourettes disorder
|
| 460 |
+
- type: basic
|
| 461 |
+
source: https://ncdj.org/style-guide/
|
| 462 |
+
considerate:
|
| 463 |
+
- treatment center
|
| 464 |
+
inconsiderate:
|
| 465 |
+
- rehab center
|
| 466 |
+
- detox center
|
| 467 |
+
- type: basic
|
| 468 |
+
source: https://ncdj.org/style-guide/
|
| 469 |
+
considerate:
|
| 470 |
+
- treatment
|
| 471 |
+
inconsiderate:
|
| 472 |
+
- rehab
|
| 473 |
+
- detox
|
| 474 |
+
- type: basic
|
| 475 |
+
source: https://ncdj.org/style-guide/
|
| 476 |
+
note: Only use terms describing mental illness when referring to a professionally diagnosed medical condition.
|
| 477 |
+
considerate:
|
| 478 |
+
- person with a personality disorder
|
| 479 |
+
- person with psychopathic personality
|
| 480 |
+
inconsiderate:
|
| 481 |
+
- sociopath
|
| 482 |
+
- type: basic
|
| 483 |
+
source: https://ncdj.org/style-guide/
|
| 484 |
+
note: Only use terms describing mental illness when referring to a professionally diagnosed medical condition.
|
| 485 |
+
considerate:
|
| 486 |
+
- people with psychopathic personalities
|
| 487 |
+
- people with a personality disorder
|
| 488 |
+
inconsiderate:
|
| 489 |
+
- sociopaths
|
| 490 |
+
- type: basic
|
| 491 |
+
source: https://www.autistichoya.com/p/ableist-words-and-terms-to-avoid.html
|
| 492 |
+
note: Dumb here is used in 2 different contexts , the inability to talk or as a curse word.
|
| 493 |
+
considerate:
|
| 494 |
+
- foolish
|
| 495 |
+
- ludicrous
|
| 496 |
+
- speechless
|
| 497 |
+
- silent
|
| 498 |
+
inconsiderate:
|
| 499 |
+
- dumb
|
| 500 |
+
- type: basic
|
| 501 |
+
source: https://web.archive.org/web/20181025174508/http://www.mmonjejr.com:80/2014/02/deconstructing-stupid.html
|
| 502 |
+
considerate:
|
| 503 |
+
- foolish
|
| 504 |
+
- ludicrous
|
| 505 |
+
- unintelligent
|
| 506 |
+
inconsiderate:
|
| 507 |
+
- simpleton
|
| 508 |
+
- stupid
|
| 509 |
+
- wacko
|
| 510 |
+
- whacko
|
| 511 |
+
- low iq
|
| 512 |
+
- type: basic
|
| 513 |
+
considerate:
|
| 514 |
+
- fit of terror
|
| 515 |
+
- scare
|
| 516 |
+
inconsiderate:
|
| 517 |
+
- panic attack
|
| 518 |
+
- type: basic
|
| 519 |
+
considerate:
|
| 520 |
+
- thin
|
| 521 |
+
- slim
|
| 522 |
+
inconsiderate:
|
| 523 |
+
- anorexic
|
| 524 |
+
- bony
|
| 525 |
+
- type: basic
|
| 526 |
+
source: https://english.stackexchange.com/questions/247550/
|
| 527 |
+
note: Only use terms describing mental illness when referring to a professionally diagnosed medical condition.
|
| 528 |
+
considerate:
|
| 529 |
+
- has an anxiety disorder
|
| 530 |
+
- obsessive
|
| 531 |
+
- pedantic
|
| 532 |
+
- niggly
|
| 533 |
+
- picky
|
| 534 |
+
inconsiderate:
|
| 535 |
+
- neurotic
|
| 536 |
+
- ocd
|
| 537 |
+
- o.c.d
|
| 538 |
+
- o.c.d.
|
| 539 |
+
- type: basic
|
| 540 |
+
considerate:
|
| 541 |
+
- restlessness
|
| 542 |
+
- sleeplessness
|
| 543 |
+
inconsiderate:
|
| 544 |
+
- insomnia
|
| 545 |
+
- type: basic
|
| 546 |
+
considerate:
|
| 547 |
+
- person who has insomnia
|
| 548 |
+
inconsiderate:
|
| 549 |
+
- insomniac
|
| 550 |
+
- type: basic
|
| 551 |
+
considerate:
|
| 552 |
+
- people who have insomnia
|
| 553 |
+
inconsiderate:
|
| 554 |
+
- insomniacs
|
| 555 |
+
- type: basic
|
| 556 |
+
source: https://www.autistichoya.com/p/ableist-words-and-terms-to-avoid.html
|
| 557 |
+
considerate:
|
| 558 |
+
- empty
|
| 559 |
+
- sterile
|
| 560 |
+
- infertile
|
| 561 |
+
inconsiderate:
|
| 562 |
+
- barren
|
| 563 |
+
- type: basic
|
| 564 |
+
source: https://www.autistichoya.com/p/ableist-words-and-terms-to-avoid.html
|
| 565 |
+
considerate:
|
| 566 |
+
- careless
|
| 567 |
+
- heartless
|
| 568 |
+
- indifferent
|
| 569 |
+
- insensitive
|
| 570 |
+
inconsiderate:
|
| 571 |
+
- blind to
|
| 572 |
+
- blind eye to
|
| 573 |
+
- blinded by
|
| 574 |
+
- deaf to
|
| 575 |
+
- deaf ear to
|
| 576 |
+
- deafened by
|
| 577 |
+
- type: basic
|
| 578 |
+
source: https://www.autistichoya.com/p/ableist-words-and-terms-to-avoid.html
|
| 579 |
+
considerate:
|
| 580 |
+
- creep
|
| 581 |
+
- fool
|
| 582 |
+
inconsiderate:
|
| 583 |
+
- cretin
|
| 584 |
+
- type: basic
|
| 585 |
+
source: https://www.autistichoya.com/p/ableist-words-and-terms-to-avoid.html
|
| 586 |
+
considerate:
|
| 587 |
+
- absurd
|
| 588 |
+
- foolish
|
| 589 |
+
inconsiderate:
|
| 590 |
+
- daft
|
| 591 |
+
- type: basic
|
| 592 |
+
source: https://www.autistichoya.com/p/ableist-words-and-terms-to-avoid.html
|
| 593 |
+
considerate:
|
| 594 |
+
- foolish
|
| 595 |
+
- ludicrous
|
| 596 |
+
- silly
|
| 597 |
+
inconsiderate:
|
| 598 |
+
- feebleminded
|
| 599 |
+
- feeble minded
|
| 600 |
+
- idiot
|
| 601 |
+
- imbecile
|
| 602 |
+
- type: basic
|
| 603 |
+
source: https://www.autistichoya.com/p/ableist-words-and-terms-to-avoid.html
|
| 604 |
+
note: Sometimes it's cleft lip or palate, not both. Specify when possible.
|
| 605 |
+
considerate:
|
| 606 |
+
- person with a cleft-lip and palate
|
| 607 |
+
inconsiderate:
|
| 608 |
+
- harelipped
|
| 609 |
+
- cleftlipped
|
| 610 |
+
- type: basic
|
| 611 |
+
source: https://www.autistichoya.com/p/ableist-words-and-terms-to-avoid.html
|
| 612 |
+
considerate:
|
| 613 |
+
- cleft-lip and palate
|
| 614 |
+
inconsiderate:
|
| 615 |
+
- harelip
|
| 616 |
+
- hare lip
|
| 617 |
+
- type: basic
|
| 618 |
+
source: https://www.autistichoya.com/p/ableist-words-and-terms-to-avoid.html
|
| 619 |
+
considerate:
|
| 620 |
+
- fanatic
|
| 621 |
+
- zealot
|
| 622 |
+
- enthusiast
|
| 623 |
+
inconsiderate:
|
| 624 |
+
- maniac
|
| 625 |
+
- type: basic
|
| 626 |
+
considerate:
|
| 627 |
+
- person with prominent teeth
|
| 628 |
+
- prominent teeth
|
| 629 |
+
inconsiderate:
|
| 630 |
+
- bucktoothed
|
| 631 |
+
- buckteeth
|
| 632 |
+
- type: basic
|
| 633 |
+
source:
|
| 634 |
+
- http://cdrnys.org/blog/disability-dialogue/the-disability-dialogue-4-disability-euphemisms-that-need-to-bite-the-dust/
|
| 635 |
+
- https://www.autistichoya.com/p/ableist-words-and-terms-to-avoid.html
|
| 636 |
+
note: Euphemisms for disabilities can be infantilizing.
|
| 637 |
+
considerate:
|
| 638 |
+
- has a disability
|
| 639 |
+
- person with a disability
|
| 640 |
+
- people with disabilities
|
| 641 |
+
inconsiderate:
|
| 642 |
+
- challenged
|
| 643 |
+
- diffability
|
| 644 |
+
- differently abled
|
| 645 |
+
- handicapable
|
| 646 |
+
- special
|
| 647 |
+
- special needs
|
| 648 |
+
- specially abled
|
| 649 |
+
- type: basic
|
| 650 |
+
source: https://www.autistichoya.com/p/ableist-words-and-terms-to-avoid.html
|
| 651 |
+
considerate:
|
| 652 |
+
- disagreeable
|
| 653 |
+
- uneducated
|
| 654 |
+
- ignorant
|
| 655 |
+
- naive
|
| 656 |
+
- inconsiderate
|
| 657 |
+
inconsiderate:
|
| 658 |
+
- fucktard
|
| 659 |
+
- libtard
|
| 660 |
+
- contard
|
| 661 |
+
- type: basic
|
| 662 |
+
considerate:
|
| 663 |
+
- disorganized
|
| 664 |
+
- distracted
|
| 665 |
+
- energetic
|
| 666 |
+
- hyperactive
|
| 667 |
+
- impetuous
|
| 668 |
+
- impulsive
|
| 669 |
+
- inattentive
|
| 670 |
+
- restless
|
| 671 |
+
- unfocused
|
| 672 |
+
inconsiderate:
|
| 673 |
+
# Upper case to only match `ADD`, not `add`.
|
| 674 |
+
- ADD
|
| 675 |
+
- adhd
|
| 676 |
+
- a.d.d.
|
| 677 |
+
- a.d.h.d.
|
| 678 |
+
- type: basic
|
| 679 |
+
note: Dummy can refer to the inability to talk or be used as a derogatory word meaning stupid. In computer programming it is used where a value or behavior is unimportant. There are better alternatives for other use cases also.
|
| 680 |
+
considerate:
|
| 681 |
+
- test double
|
| 682 |
+
- placeholder
|
| 683 |
+
- fake
|
| 684 |
+
- stub
|
| 685 |
+
inconsiderate:
|
| 686 |
+
- dummyvariable
|
| 687 |
+
- dummyvalue
|
| 688 |
+
- dummyobject
|
| 689 |
+
- dummy
|
| 690 |
+
- type: basic
|
| 691 |
+
note: Binge might be insensitive towards folks with eating or drinking disorders
|
| 692 |
+
source: https://github.com/retextjs/retext-equality/issues/110
|
| 693 |
+
considerate:
|
| 694 |
+
- enthusiastic
|
| 695 |
+
- spree
|
| 696 |
+
inconsiderate:
|
| 697 |
+
- binge
|
app/data/en/condescending.yml
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# List of words to avoid, specifically in education writing.
|
| 2 |
+
# From: https://css-tricks.com/words-avoid-educational-writing/
|
| 3 |
+
# The terms `however` and `so` are not included as they’re only an offense if at
|
| 4 |
+
# the start of a sentence according to CSS Tricks.
|
| 5 |
+
# If you want messages for those, use `retext-intensify`.
|
| 6 |
+
- type: basic
|
| 7 |
+
inconsiderate:
|
| 8 |
+
- obvious
|
| 9 |
+
- obviously
|
| 10 |
+
note: Not everything is as obvious as you might think. And if it isn’t obvious to the reader, it can hurt.
|
| 11 |
+
source: https://css-tricks.com/words-avoid-educational-writing/
|
| 12 |
+
- type: basic
|
| 13 |
+
inconsiderate: just
|
| 14 |
+
note: Not everything is as easy as you might think. And if it isn’t easy for the reader, it can hurt.
|
| 15 |
+
source: https://css-tricks.com/words-avoid-educational-writing/
|
| 16 |
+
- type: basic
|
| 17 |
+
inconsiderate: basically
|
| 18 |
+
note: It’s probably not that basic. If you’re going to explain a confusing previous sentence with a clearer next sentence, why not drop the former and only use the latter?
|
| 19 |
+
source: https://css-tricks.com/words-avoid-educational-writing/
|
| 20 |
+
- type: basic
|
| 21 |
+
inconsiderate:
|
| 22 |
+
- simple
|
| 23 |
+
- simply
|
| 24 |
+
note: It’s probably not that simple. Even if it is, you probably don’t need to specifically say it.
|
| 25 |
+
source: https://css-tricks.com/words-avoid-educational-writing/
|
| 26 |
+
- type: basic
|
| 27 |
+
inconsiderate:
|
| 28 |
+
- easy
|
| 29 |
+
- easily
|
| 30 |
+
note: It’s probably not that easy. Even if it is, you probably don’t need to specifically say it.
|
| 31 |
+
source: https://css-tricks.com/words-avoid-educational-writing/
|
| 32 |
+
- type: basic
|
| 33 |
+
inconsiderate: of course
|
| 34 |
+
note: If it’s self-evident then maybe you don’t need to describe it. If it isn’t, don’t say it.
|
| 35 |
+
source: https://css-tricks.com/words-avoid-educational-writing/
|
| 36 |
+
- type: basic
|
| 37 |
+
inconsiderate: clearly
|
| 38 |
+
note: If it’s self-evident then maybe you don’t need to describe it. If it isn’t, don’t say it.
|
| 39 |
+
source: https://css-tricks.com/words-avoid-educational-writing/
|
| 40 |
+
- type: basic
|
| 41 |
+
inconsiderate: everyone knows
|
| 42 |
+
note: If it’s self-evident then maybe you don’t need to describe it. If it isn’t, don’t say it.
|
| 43 |
+
source: https://css-tricks.com/words-avoid-educational-writing/
|
| 44 |
+
- type: basic
|
| 45 |
+
inconsiderate:
|
| 46 |
+
- straight forward
|
| 47 |
+
- straightforward
|
| 48 |
+
- straight forwardly
|
| 49 |
+
- straightforwardly
|
| 50 |
+
note: It’s probably not that straight forward. Even if it is, you probably don’t need to specifically say it.
|
app/data/en/gender.yml
ADDED
|
@@ -0,0 +1,1808 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- type: or
|
| 2 |
+
condition: when referring to a person
|
| 3 |
+
considerate:
|
| 4 |
+
- their
|
| 5 |
+
- theirs
|
| 6 |
+
- them
|
| 7 |
+
inconsiderate:
|
| 8 |
+
her: female
|
| 9 |
+
hers: female
|
| 10 |
+
him: male
|
| 11 |
+
his: male
|
| 12 |
+
- type: or
|
| 13 |
+
apostrophe: true
|
| 14 |
+
considerate:
|
| 15 |
+
- they
|
| 16 |
+
- it
|
| 17 |
+
inconsiderate:
|
| 18 |
+
she: female
|
| 19 |
+
he: male
|
| 20 |
+
she'd: female
|
| 21 |
+
he'd: male
|
| 22 |
+
she'll: female
|
| 23 |
+
he'll: male
|
| 24 |
+
she's: female
|
| 25 |
+
he's: male
|
| 26 |
+
- type: or
|
| 27 |
+
considerate:
|
| 28 |
+
- themselves
|
| 29 |
+
- theirself
|
| 30 |
+
- self
|
| 31 |
+
inconsiderate:
|
| 32 |
+
herself: female
|
| 33 |
+
himself: male
|
| 34 |
+
- type: or
|
| 35 |
+
condition: when referring to a person
|
| 36 |
+
considerate:
|
| 37 |
+
- kid
|
| 38 |
+
- child
|
| 39 |
+
- youth
|
| 40 |
+
inconsiderate:
|
| 41 |
+
girl: female
|
| 42 |
+
boy: male
|
| 43 |
+
- type: or
|
| 44 |
+
considerate:
|
| 45 |
+
- people
|
| 46 |
+
- persons
|
| 47 |
+
- folks
|
| 48 |
+
inconsiderate:
|
| 49 |
+
women: female
|
| 50 |
+
girls: female
|
| 51 |
+
gals: female
|
| 52 |
+
ladies: female
|
| 53 |
+
man: male
|
| 54 |
+
boys: male
|
| 55 |
+
men: male
|
| 56 |
+
guys: male
|
| 57 |
+
dudes: male
|
| 58 |
+
gents: male
|
| 59 |
+
gentlemen: male
|
| 60 |
+
- type: or
|
| 61 |
+
considerate:
|
| 62 |
+
- person
|
| 63 |
+
- friend
|
| 64 |
+
- pal
|
| 65 |
+
- folk
|
| 66 |
+
- individual
|
| 67 |
+
inconsiderate:
|
| 68 |
+
woman: female
|
| 69 |
+
gal: female
|
| 70 |
+
lady: female
|
| 71 |
+
babe: female
|
| 72 |
+
bimbo: female
|
| 73 |
+
chick: female
|
| 74 |
+
guy: male
|
| 75 |
+
lad: male
|
| 76 |
+
fellow: male
|
| 77 |
+
dude: male
|
| 78 |
+
bro: male
|
| 79 |
+
gentleman: male
|
| 80 |
+
- type: or
|
| 81 |
+
considerate:
|
| 82 |
+
- native land
|
| 83 |
+
- homeland
|
| 84 |
+
inconsiderate:
|
| 85 |
+
motherland: female
|
| 86 |
+
fatherland: male
|
| 87 |
+
- type: or
|
| 88 |
+
considerate:
|
| 89 |
+
- native tongue
|
| 90 |
+
- native language
|
| 91 |
+
inconsiderate:
|
| 92 |
+
mother tongue: female
|
| 93 |
+
father tongue: male
|
| 94 |
+
- type: or
|
| 95 |
+
considerate:
|
| 96 |
+
- first-year students
|
| 97 |
+
- freshers
|
| 98 |
+
inconsiderate:
|
| 99 |
+
freshwomen: female
|
| 100 |
+
freshmen: male
|
| 101 |
+
- type: or
|
| 102 |
+
considerate:
|
| 103 |
+
- garbage collector
|
| 104 |
+
- waste collector
|
| 105 |
+
- trash collector
|
| 106 |
+
inconsiderate:
|
| 107 |
+
garbagewoman: female
|
| 108 |
+
garbageman: male
|
| 109 |
+
- type: or
|
| 110 |
+
considerate:
|
| 111 |
+
- garbage collectors
|
| 112 |
+
- waste collectors
|
| 113 |
+
- trash collectors
|
| 114 |
+
inconsiderate:
|
| 115 |
+
garbagewomen: female
|
| 116 |
+
garbagemen: male
|
| 117 |
+
- type: or
|
| 118 |
+
considerate:
|
| 119 |
+
- chair
|
| 120 |
+
- head
|
| 121 |
+
- chairperson
|
| 122 |
+
- coordinator
|
| 123 |
+
- committee head
|
| 124 |
+
- moderator
|
| 125 |
+
- presiding officer
|
| 126 |
+
inconsiderate:
|
| 127 |
+
chairwoman: female
|
| 128 |
+
chairman: male
|
| 129 |
+
- type: or
|
| 130 |
+
considerate:
|
| 131 |
+
- committee member
|
| 132 |
+
inconsiderate:
|
| 133 |
+
committee woman: female
|
| 134 |
+
committee man: male
|
| 135 |
+
- type: or
|
| 136 |
+
considerate:
|
| 137 |
+
- cowhand
|
| 138 |
+
inconsiderate:
|
| 139 |
+
cowgirl: female
|
| 140 |
+
cowboy: male
|
| 141 |
+
- type: or
|
| 142 |
+
considerate:
|
| 143 |
+
- cowhands
|
| 144 |
+
inconsiderate:
|
| 145 |
+
cowgirls: female
|
| 146 |
+
cowboys: male
|
| 147 |
+
- type: or
|
| 148 |
+
considerate:
|
| 149 |
+
- cattle rancher
|
| 150 |
+
inconsiderate:
|
| 151 |
+
cattlewoman: female
|
| 152 |
+
cattleman: male
|
| 153 |
+
- type: or
|
| 154 |
+
considerate:
|
| 155 |
+
- cattle ranchers
|
| 156 |
+
inconsiderate:
|
| 157 |
+
cattlewomen: female
|
| 158 |
+
cattlemen: male
|
| 159 |
+
- type: or
|
| 160 |
+
considerate:
|
| 161 |
+
- chairs
|
| 162 |
+
- chairpersons
|
| 163 |
+
- coordinators
|
| 164 |
+
inconsiderate:
|
| 165 |
+
chairwomen: female
|
| 166 |
+
chairmen: male
|
| 167 |
+
- type: or
|
| 168 |
+
considerate:
|
| 169 |
+
- mail carrier
|
| 170 |
+
- letter carrier
|
| 171 |
+
- postal worker
|
| 172 |
+
inconsiderate:
|
| 173 |
+
postwoman: female
|
| 174 |
+
mailwoman: female
|
| 175 |
+
postman: male
|
| 176 |
+
mailman: male
|
| 177 |
+
- type: or
|
| 178 |
+
considerate:
|
| 179 |
+
- mail carriers
|
| 180 |
+
- letter carriers
|
| 181 |
+
- postal workers
|
| 182 |
+
inconsiderate:
|
| 183 |
+
postwomen: female
|
| 184 |
+
mailwomen: female
|
| 185 |
+
postmen: male
|
| 186 |
+
mailmen: male
|
| 187 |
+
- type: or
|
| 188 |
+
considerate:
|
| 189 |
+
- officer
|
| 190 |
+
- police officer
|
| 191 |
+
inconsiderate:
|
| 192 |
+
policewoman: female
|
| 193 |
+
policeman: male
|
| 194 |
+
chick cop: female
|
| 195 |
+
- type: or
|
| 196 |
+
considerate:
|
| 197 |
+
- officers
|
| 198 |
+
- police officers
|
| 199 |
+
inconsiderate:
|
| 200 |
+
policewomen: female
|
| 201 |
+
policemen: male
|
| 202 |
+
- type: or
|
| 203 |
+
considerate:
|
| 204 |
+
- flight attendant
|
| 205 |
+
inconsiderate:
|
| 206 |
+
stewardess: female
|
| 207 |
+
steward: male
|
| 208 |
+
- type: or
|
| 209 |
+
considerate:
|
| 210 |
+
- flight attendants
|
| 211 |
+
inconsiderate:
|
| 212 |
+
stewardesses: female
|
| 213 |
+
stewards: male
|
| 214 |
+
- type: or
|
| 215 |
+
considerate:
|
| 216 |
+
- member of congress
|
| 217 |
+
- congress person
|
| 218 |
+
- legislator
|
| 219 |
+
- representative
|
| 220 |
+
inconsiderate:
|
| 221 |
+
congresswoman: female
|
| 222 |
+
congressman: male
|
| 223 |
+
- type: or
|
| 224 |
+
considerate:
|
| 225 |
+
- members of congress
|
| 226 |
+
- congress persons
|
| 227 |
+
- legislators
|
| 228 |
+
- representatives
|
| 229 |
+
inconsiderate:
|
| 230 |
+
congresswomen: female
|
| 231 |
+
congressmen: male
|
| 232 |
+
- type: or
|
| 233 |
+
considerate:
|
| 234 |
+
- fire fighter
|
| 235 |
+
- fire officer
|
| 236 |
+
inconsiderate:
|
| 237 |
+
firewoman: female
|
| 238 |
+
fireman: male
|
| 239 |
+
- type: or
|
| 240 |
+
considerate:
|
| 241 |
+
- fire fighters
|
| 242 |
+
inconsiderate:
|
| 243 |
+
firewomen: female
|
| 244 |
+
firemen: male
|
| 245 |
+
- type: or
|
| 246 |
+
considerate:
|
| 247 |
+
- fisher
|
| 248 |
+
- crew member
|
| 249 |
+
- fisherfolk
|
| 250 |
+
- angler
|
| 251 |
+
inconsiderate:
|
| 252 |
+
fisherwoman: female
|
| 253 |
+
fisherman: male
|
| 254 |
+
- type: or
|
| 255 |
+
considerate:
|
| 256 |
+
- fishers
|
| 257 |
+
inconsiderate:
|
| 258 |
+
fisherwomen: female
|
| 259 |
+
fishermen: male
|
| 260 |
+
- type: or
|
| 261 |
+
considerate:
|
| 262 |
+
- kinship
|
| 263 |
+
- community
|
| 264 |
+
inconsiderate:
|
| 265 |
+
sisterhood: female
|
| 266 |
+
brotherhood: male
|
| 267 |
+
- type: or
|
| 268 |
+
considerate:
|
| 269 |
+
- common person
|
| 270 |
+
- average person
|
| 271 |
+
inconsiderate:
|
| 272 |
+
common girl: female
|
| 273 |
+
common man: male
|
| 274 |
+
- type: or
|
| 275 |
+
considerate:
|
| 276 |
+
- business executive
|
| 277 |
+
- entrepreneur
|
| 278 |
+
- business person
|
| 279 |
+
- professional
|
| 280 |
+
inconsiderate:
|
| 281 |
+
businesswoman: female
|
| 282 |
+
salarywoman: female
|
| 283 |
+
businessman: male
|
| 284 |
+
salaryman: male
|
| 285 |
+
- type: or
|
| 286 |
+
considerate:
|
| 287 |
+
- business executives
|
| 288 |
+
- entrepreneurs
|
| 289 |
+
inconsiderate:
|
| 290 |
+
businesswomen: female
|
| 291 |
+
salarywomen: female
|
| 292 |
+
career girl: female
|
| 293 |
+
career woman: female
|
| 294 |
+
businessmen: male
|
| 295 |
+
salarymen: male
|
| 296 |
+
- type: or
|
| 297 |
+
considerate:
|
| 298 |
+
- cleaner
|
| 299 |
+
inconsiderate:
|
| 300 |
+
cleaning lady: female
|
| 301 |
+
cleaning girl: female
|
| 302 |
+
cleaning woman: female
|
| 303 |
+
janitress: female
|
| 304 |
+
cleaning man: male
|
| 305 |
+
cleaning boy: male
|
| 306 |
+
janitor: male
|
| 307 |
+
- type: or
|
| 308 |
+
considerate:
|
| 309 |
+
- cleaners
|
| 310 |
+
- housekeeping
|
| 311 |
+
inconsiderate:
|
| 312 |
+
cleaning ladies: female
|
| 313 |
+
cleaning girls: female
|
| 314 |
+
janitresses: female
|
| 315 |
+
cleaning men: male
|
| 316 |
+
janitors: male
|
| 317 |
+
- type: or
|
| 318 |
+
considerate:
|
| 319 |
+
- courier
|
| 320 |
+
- messenger
|
| 321 |
+
inconsiderate:
|
| 322 |
+
delivery girl: female
|
| 323 |
+
delivery boy: male
|
| 324 |
+
- type: or
|
| 325 |
+
considerate:
|
| 326 |
+
- supervisor
|
| 327 |
+
- shift boss
|
| 328 |
+
inconsiderate:
|
| 329 |
+
forewoman: female
|
| 330 |
+
foreman: male
|
| 331 |
+
- type: or
|
| 332 |
+
considerate:
|
| 333 |
+
- lead
|
| 334 |
+
- front
|
| 335 |
+
- figurehead
|
| 336 |
+
inconsiderate:
|
| 337 |
+
'frontwoman, front woman': female
|
| 338 |
+
'frontman, front man': male
|
| 339 |
+
- type: or
|
| 340 |
+
considerate:
|
| 341 |
+
- figureheads
|
| 342 |
+
inconsiderate:
|
| 343 |
+
'front women, frontwomen': female
|
| 344 |
+
'front men, frontmen': male
|
| 345 |
+
- type: or
|
| 346 |
+
considerate:
|
| 347 |
+
- supervisors
|
| 348 |
+
- shift bosses
|
| 349 |
+
inconsiderate:
|
| 350 |
+
forewomen: female
|
| 351 |
+
foremen: male
|
| 352 |
+
- type: or
|
| 353 |
+
considerate:
|
| 354 |
+
- insurance agent
|
| 355 |
+
inconsiderate:
|
| 356 |
+
insurance woman: female
|
| 357 |
+
insurance man: male
|
| 358 |
+
- type: or
|
| 359 |
+
considerate:
|
| 360 |
+
- insurance agents
|
| 361 |
+
inconsiderate:
|
| 362 |
+
insurance women: female
|
| 363 |
+
insurance men: male
|
| 364 |
+
- type: or
|
| 365 |
+
considerate:
|
| 366 |
+
- proprietor
|
| 367 |
+
- building manager
|
| 368 |
+
inconsiderate:
|
| 369 |
+
landlady: female
|
| 370 |
+
landlord: male
|
| 371 |
+
- type: or
|
| 372 |
+
considerate:
|
| 373 |
+
- proprietors
|
| 374 |
+
- building managers
|
| 375 |
+
inconsiderate:
|
| 376 |
+
landladies: female
|
| 377 |
+
landlords: male
|
| 378 |
+
- type: or
|
| 379 |
+
considerate:
|
| 380 |
+
- graduate
|
| 381 |
+
inconsiderate:
|
| 382 |
+
alumna: female
|
| 383 |
+
alumnus: male
|
| 384 |
+
- type: or
|
| 385 |
+
considerate:
|
| 386 |
+
- graduates
|
| 387 |
+
inconsiderate:
|
| 388 |
+
alumnae: female
|
| 389 |
+
alumni: male
|
| 390 |
+
- type: or
|
| 391 |
+
considerate:
|
| 392 |
+
- anchor
|
| 393 |
+
- journalist
|
| 394 |
+
inconsiderate:
|
| 395 |
+
newswoman: female
|
| 396 |
+
newspaperwoman: female
|
| 397 |
+
anchorwoman: female
|
| 398 |
+
newsman: male
|
| 399 |
+
newspaperman: male
|
| 400 |
+
anchorman: male
|
| 401 |
+
- type: or
|
| 402 |
+
considerate:
|
| 403 |
+
- anchors
|
| 404 |
+
- journalists
|
| 405 |
+
inconsiderate:
|
| 406 |
+
newswomen: female
|
| 407 |
+
newspaperwomen: female
|
| 408 |
+
anchorwomen: female
|
| 409 |
+
newsmen: male
|
| 410 |
+
newspapermen: male
|
| 411 |
+
anchormen: male
|
| 412 |
+
- type: or
|
| 413 |
+
considerate:
|
| 414 |
+
- repairer
|
| 415 |
+
- technician
|
| 416 |
+
inconsiderate:
|
| 417 |
+
repairwoman: female
|
| 418 |
+
repairman: male
|
| 419 |
+
- type: or
|
| 420 |
+
considerate:
|
| 421 |
+
- technicians
|
| 422 |
+
inconsiderate:
|
| 423 |
+
repairwomen: female
|
| 424 |
+
repairmen: male
|
| 425 |
+
- type: or
|
| 426 |
+
considerate:
|
| 427 |
+
- salesperson
|
| 428 |
+
- sales clerk
|
| 429 |
+
- sales rep
|
| 430 |
+
- sales agent
|
| 431 |
+
- sales attendant
|
| 432 |
+
- seller
|
| 433 |
+
- shop assistant
|
| 434 |
+
inconsiderate:
|
| 435 |
+
saleswoman: female
|
| 436 |
+
sales woman: female
|
| 437 |
+
saleslady: female
|
| 438 |
+
salesman: male
|
| 439 |
+
sales man: male
|
| 440 |
+
- type: or
|
| 441 |
+
considerate:
|
| 442 |
+
- sales clerks
|
| 443 |
+
- sales reps
|
| 444 |
+
- sales agents
|
| 445 |
+
- sellers
|
| 446 |
+
inconsiderate:
|
| 447 |
+
saleswomen: female
|
| 448 |
+
sales women: female
|
| 449 |
+
salesladies: female
|
| 450 |
+
salesmen: male
|
| 451 |
+
sales men: male
|
| 452 |
+
- type: or
|
| 453 |
+
considerate:
|
| 454 |
+
- soldier
|
| 455 |
+
- service representative
|
| 456 |
+
inconsiderate:
|
| 457 |
+
servicewoman: female
|
| 458 |
+
serviceman: male
|
| 459 |
+
- type: or
|
| 460 |
+
considerate:
|
| 461 |
+
- soldiers
|
| 462 |
+
- service representatives
|
| 463 |
+
inconsiderate:
|
| 464 |
+
servicewomen: female
|
| 465 |
+
servicemen: male
|
| 466 |
+
- type: or
|
| 467 |
+
considerate:
|
| 468 |
+
- server
|
| 469 |
+
inconsiderate:
|
| 470 |
+
waitress: female
|
| 471 |
+
waiter: male
|
| 472 |
+
- type: or
|
| 473 |
+
considerate:
|
| 474 |
+
- servers
|
| 475 |
+
inconsiderate:
|
| 476 |
+
waitresses: female
|
| 477 |
+
waiters: male
|
| 478 |
+
- type: or
|
| 479 |
+
considerate:
|
| 480 |
+
- worker
|
| 481 |
+
- wage earner
|
| 482 |
+
- taxpayer
|
| 483 |
+
inconsiderate:
|
| 484 |
+
workwoman: female
|
| 485 |
+
working woman: female
|
| 486 |
+
workman: male
|
| 487 |
+
working man: male
|
| 488 |
+
- type: or
|
| 489 |
+
considerate:
|
| 490 |
+
- workers
|
| 491 |
+
inconsiderate:
|
| 492 |
+
workwomen: female
|
| 493 |
+
workmen: male
|
| 494 |
+
- type: or
|
| 495 |
+
considerate:
|
| 496 |
+
- performer
|
| 497 |
+
- star
|
| 498 |
+
- artist
|
| 499 |
+
- entertainer
|
| 500 |
+
inconsiderate:
|
| 501 |
+
actress: female
|
| 502 |
+
actor: male
|
| 503 |
+
- type: or
|
| 504 |
+
considerate:
|
| 505 |
+
- performers
|
| 506 |
+
- stars
|
| 507 |
+
- artists
|
| 508 |
+
- entertainers
|
| 509 |
+
inconsiderate:
|
| 510 |
+
actresses: female
|
| 511 |
+
actors: male
|
| 512 |
+
- type: or
|
| 513 |
+
considerate:
|
| 514 |
+
- pilot
|
| 515 |
+
- aviator
|
| 516 |
+
- airstaff
|
| 517 |
+
inconsiderate:
|
| 518 |
+
aircrewwoman: female
|
| 519 |
+
aircrew woman: female
|
| 520 |
+
aircrewman: male
|
| 521 |
+
airman: male
|
| 522 |
+
- type: or
|
| 523 |
+
considerate:
|
| 524 |
+
- pilots
|
| 525 |
+
- aviators
|
| 526 |
+
- airstaff
|
| 527 |
+
inconsiderate:
|
| 528 |
+
aircrewwomen: female
|
| 529 |
+
aircrew women: female
|
| 530 |
+
aircrewmen: male
|
| 531 |
+
airmen: male
|
| 532 |
+
- type: or
|
| 533 |
+
considerate:
|
| 534 |
+
- cabinet member
|
| 535 |
+
inconsiderate:
|
| 536 |
+
alderwoman: female
|
| 537 |
+
alderman: male
|
| 538 |
+
- type: or
|
| 539 |
+
considerate:
|
| 540 |
+
- cabinet
|
| 541 |
+
- cabinet members
|
| 542 |
+
- alderperson
|
| 543 |
+
inconsiderate:
|
| 544 |
+
alderwomen: female
|
| 545 |
+
aldermen: male
|
| 546 |
+
- type: or
|
| 547 |
+
considerate:
|
| 548 |
+
- assembly person
|
| 549 |
+
- assembly worker
|
| 550 |
+
inconsiderate:
|
| 551 |
+
assemblywoman: female
|
| 552 |
+
assemblyman: male
|
| 553 |
+
- type: or
|
| 554 |
+
considerate:
|
| 555 |
+
- relative
|
| 556 |
+
inconsiderate:
|
| 557 |
+
kinswoman: female
|
| 558 |
+
aunt: female
|
| 559 |
+
kinsman: male
|
| 560 |
+
uncle: male
|
| 561 |
+
- type: or
|
| 562 |
+
considerate:
|
| 563 |
+
- relatives
|
| 564 |
+
inconsiderate:
|
| 565 |
+
kinswomen: female
|
| 566 |
+
aunts: female
|
| 567 |
+
kinsmen: male
|
| 568 |
+
uncles: male
|
| 569 |
+
- type: or
|
| 570 |
+
considerate:
|
| 571 |
+
- boogeymonster
|
| 572 |
+
inconsiderate:
|
| 573 |
+
boogeywoman: female
|
| 574 |
+
boogeyman: male
|
| 575 |
+
- type: or
|
| 576 |
+
considerate:
|
| 577 |
+
- boogeymonster
|
| 578 |
+
inconsiderate:
|
| 579 |
+
boogiewoman: female
|
| 580 |
+
boogieman: male
|
| 581 |
+
- type: or
|
| 582 |
+
considerate:
|
| 583 |
+
- bogeymonster
|
| 584 |
+
inconsiderate:
|
| 585 |
+
bogeywoman: female
|
| 586 |
+
bogeyman: male
|
| 587 |
+
- type: or
|
| 588 |
+
considerate:
|
| 589 |
+
- bogeymonster
|
| 590 |
+
inconsiderate:
|
| 591 |
+
bogiewoman: female
|
| 592 |
+
bogieman: male
|
| 593 |
+
- type: or
|
| 594 |
+
considerate:
|
| 595 |
+
- boogeymonsters
|
| 596 |
+
inconsiderate:
|
| 597 |
+
boogiewomen: female
|
| 598 |
+
boogiemen: male
|
| 599 |
+
- type: or
|
| 600 |
+
considerate:
|
| 601 |
+
- bogeymonsters
|
| 602 |
+
inconsiderate:
|
| 603 |
+
bogiewomen: female
|
| 604 |
+
bogiemen: male
|
| 605 |
+
- type: or
|
| 606 |
+
considerate:
|
| 607 |
+
- bonder
|
| 608 |
+
inconsiderate:
|
| 609 |
+
bondswoman: female
|
| 610 |
+
bondsman: male
|
| 611 |
+
- type: or
|
| 612 |
+
considerate:
|
| 613 |
+
- bonders
|
| 614 |
+
inconsiderate:
|
| 615 |
+
bondswomen: female
|
| 616 |
+
bondsmen: male
|
| 617 |
+
- type: or
|
| 618 |
+
source: https://www.bustle.com/articles/108321-6-reasons-to-refer-to-your-significant-other-as-your-partner
|
| 619 |
+
considerate:
|
| 620 |
+
- partner
|
| 621 |
+
- significant other
|
| 622 |
+
- spouse
|
| 623 |
+
inconsiderate:
|
| 624 |
+
wife: female
|
| 625 |
+
husband: male
|
| 626 |
+
- type: or
|
| 627 |
+
source: https://www.bustle.com/articles/108321-6-reasons-to-refer-to-your-significant-other-as-your-partner
|
| 628 |
+
considerate:
|
| 629 |
+
- partners
|
| 630 |
+
- significant others
|
| 631 |
+
- spouses
|
| 632 |
+
inconsiderate:
|
| 633 |
+
wives: female
|
| 634 |
+
husbands: male
|
| 635 |
+
- type: or
|
| 636 |
+
source: https://www.bustle.com/articles/108321-6-reasons-to-refer-to-your-significant-other-as-your-partner
|
| 637 |
+
considerate:
|
| 638 |
+
- partner
|
| 639 |
+
- friend
|
| 640 |
+
- significant other
|
| 641 |
+
inconsiderate:
|
| 642 |
+
girlfriend: female
|
| 643 |
+
boyfriend: male
|
| 644 |
+
- type: or
|
| 645 |
+
source: https://www.bustle.com/articles/108321-6-reasons-to-refer-to-your-significant-other-as-your-partner
|
| 646 |
+
considerate:
|
| 647 |
+
- partners
|
| 648 |
+
- friends
|
| 649 |
+
- significant others
|
| 650 |
+
inconsiderate:
|
| 651 |
+
girlfriends: female
|
| 652 |
+
boyfriends: male
|
| 653 |
+
- type: or
|
| 654 |
+
considerate:
|
| 655 |
+
- childhood
|
| 656 |
+
inconsiderate:
|
| 657 |
+
girlhood: female
|
| 658 |
+
boyhood: male
|
| 659 |
+
- type: or
|
| 660 |
+
considerate:
|
| 661 |
+
- childish
|
| 662 |
+
inconsiderate:
|
| 663 |
+
girly: female
|
| 664 |
+
girlish: female
|
| 665 |
+
boyish: male
|
| 666 |
+
- type: or
|
| 667 |
+
considerate:
|
| 668 |
+
- journeyperson
|
| 669 |
+
inconsiderate:
|
| 670 |
+
journeywoman: female
|
| 671 |
+
journeyman: male
|
| 672 |
+
- type: or
|
| 673 |
+
considerate:
|
| 674 |
+
- journeypersons
|
| 675 |
+
inconsiderate:
|
| 676 |
+
journeywomen: female
|
| 677 |
+
journeymen: male
|
| 678 |
+
- type: or
|
| 679 |
+
considerate:
|
| 680 |
+
- godparent
|
| 681 |
+
- elder
|
| 682 |
+
- patron
|
| 683 |
+
inconsiderate:
|
| 684 |
+
godmother: female
|
| 685 |
+
patroness: female
|
| 686 |
+
godfather: male
|
| 687 |
+
- type: or
|
| 688 |
+
considerate:
|
| 689 |
+
- grandchild
|
| 690 |
+
inconsiderate:
|
| 691 |
+
granddaughter: female
|
| 692 |
+
grandson: male
|
| 693 |
+
- type: or
|
| 694 |
+
considerate:
|
| 695 |
+
- grandchildren
|
| 696 |
+
inconsiderate:
|
| 697 |
+
granddaughters: female
|
| 698 |
+
grandsons: male
|
| 699 |
+
- type: or
|
| 700 |
+
considerate:
|
| 701 |
+
- ancestor
|
| 702 |
+
inconsiderate:
|
| 703 |
+
foremother: female
|
| 704 |
+
forefather: male
|
| 705 |
+
- type: or
|
| 706 |
+
considerate:
|
| 707 |
+
- ancestors
|
| 708 |
+
inconsiderate:
|
| 709 |
+
foremothers: female
|
| 710 |
+
forefathers: male
|
| 711 |
+
- type: or
|
| 712 |
+
considerate:
|
| 713 |
+
- grandparent
|
| 714 |
+
- ancestor
|
| 715 |
+
inconsiderate:
|
| 716 |
+
granny: female
|
| 717 |
+
grandma: female
|
| 718 |
+
grandmother: female
|
| 719 |
+
grandpappy: male
|
| 720 |
+
granddaddy: male
|
| 721 |
+
gramps: male
|
| 722 |
+
grandpa: male
|
| 723 |
+
grandfather: male
|
| 724 |
+
- type: or
|
| 725 |
+
considerate:
|
| 726 |
+
- grandparents
|
| 727 |
+
- ancestors
|
| 728 |
+
inconsiderate:
|
| 729 |
+
grandmothers: female
|
| 730 |
+
grandfathers: male
|
| 731 |
+
- type: or
|
| 732 |
+
considerate:
|
| 733 |
+
- spouse
|
| 734 |
+
- newlywed
|
| 735 |
+
inconsiderate:
|
| 736 |
+
bride: female
|
| 737 |
+
groom: male
|
| 738 |
+
- type: or
|
| 739 |
+
considerate:
|
| 740 |
+
- sibling
|
| 741 |
+
inconsiderate:
|
| 742 |
+
sister: female
|
| 743 |
+
brother: male
|
| 744 |
+
- type: or
|
| 745 |
+
considerate:
|
| 746 |
+
- siblings
|
| 747 |
+
inconsiderate:
|
| 748 |
+
sisters: female
|
| 749 |
+
brothers: male
|
| 750 |
+
- type: or
|
| 751 |
+
considerate:
|
| 752 |
+
- camera operator
|
| 753 |
+
- camera person
|
| 754 |
+
inconsiderate:
|
| 755 |
+
camerawoman: female
|
| 756 |
+
cameraman: male
|
| 757 |
+
- type: or
|
| 758 |
+
considerate:
|
| 759 |
+
- camera operators
|
| 760 |
+
inconsiderate:
|
| 761 |
+
camerawomen: female
|
| 762 |
+
cameramen: male
|
| 763 |
+
- type: or
|
| 764 |
+
considerate:
|
| 765 |
+
- troglodyte
|
| 766 |
+
- hominidae
|
| 767 |
+
inconsiderate:
|
| 768 |
+
cavewoman: female
|
| 769 |
+
caveman: male
|
| 770 |
+
- type: or
|
| 771 |
+
considerate:
|
| 772 |
+
- troglodytae
|
| 773 |
+
- troglodyti
|
| 774 |
+
- troglodytes
|
| 775 |
+
- hominids
|
| 776 |
+
inconsiderate:
|
| 777 |
+
cavewomen: female
|
| 778 |
+
cavemen: male
|
| 779 |
+
- type: or
|
| 780 |
+
considerate:
|
| 781 |
+
- clergyperson
|
| 782 |
+
- clergy
|
| 783 |
+
- cleric
|
| 784 |
+
inconsiderate:
|
| 785 |
+
clergywoman: female
|
| 786 |
+
clergyman: male
|
| 787 |
+
- type: or
|
| 788 |
+
considerate:
|
| 789 |
+
- clergies
|
| 790 |
+
- clerics
|
| 791 |
+
inconsiderate:
|
| 792 |
+
clergywomen: female
|
| 793 |
+
clergymen: male
|
| 794 |
+
- type: or
|
| 795 |
+
considerate:
|
| 796 |
+
- council member
|
| 797 |
+
inconsiderate:
|
| 798 |
+
councilwoman: female
|
| 799 |
+
councilman: male
|
| 800 |
+
- type: or
|
| 801 |
+
considerate:
|
| 802 |
+
- council members
|
| 803 |
+
inconsiderate:
|
| 804 |
+
councilwomen: female
|
| 805 |
+
councilmen: male
|
| 806 |
+
- type: or
|
| 807 |
+
considerate:
|
| 808 |
+
- country person
|
| 809 |
+
inconsiderate:
|
| 810 |
+
countrywoman: female
|
| 811 |
+
countryman: male
|
| 812 |
+
- type: or
|
| 813 |
+
considerate:
|
| 814 |
+
- country folk
|
| 815 |
+
inconsiderate:
|
| 816 |
+
countrywomen: female
|
| 817 |
+
countrymen: male
|
| 818 |
+
- type: or
|
| 819 |
+
considerate:
|
| 820 |
+
- artisan
|
| 821 |
+
- craftsperson
|
| 822 |
+
- skilled worker
|
| 823 |
+
inconsiderate:
|
| 824 |
+
handywoman: female
|
| 825 |
+
craftswoman: female
|
| 826 |
+
handyman: male
|
| 827 |
+
craftsman: male
|
| 828 |
+
- type: or
|
| 829 |
+
considerate:
|
| 830 |
+
- presenter
|
| 831 |
+
- entertainer
|
| 832 |
+
- emcee
|
| 833 |
+
inconsiderate:
|
| 834 |
+
hostess: female
|
| 835 |
+
host: male
|
| 836 |
+
- type: or
|
| 837 |
+
considerate:
|
| 838 |
+
- presenters
|
| 839 |
+
- entertainers
|
| 840 |
+
- emcees
|
| 841 |
+
inconsiderate:
|
| 842 |
+
hostesses: female
|
| 843 |
+
hosts: male
|
| 844 |
+
- type: or
|
| 845 |
+
considerate:
|
| 846 |
+
- artisans
|
| 847 |
+
- craftspersons
|
| 848 |
+
- skilled workers
|
| 849 |
+
inconsiderate:
|
| 850 |
+
handywomen: female
|
| 851 |
+
craftswomen: female
|
| 852 |
+
handymen: male
|
| 853 |
+
craftsmen: male
|
| 854 |
+
- type: or
|
| 855 |
+
considerate:
|
| 856 |
+
- guillotine
|
| 857 |
+
inconsiderate:
|
| 858 |
+
hangwoman: female
|
| 859 |
+
hangman: male
|
| 860 |
+
- type: or
|
| 861 |
+
considerate:
|
| 862 |
+
- guillotines
|
| 863 |
+
inconsiderate:
|
| 864 |
+
hangwomen: female
|
| 865 |
+
hangmen: male
|
| 866 |
+
- type: or
|
| 867 |
+
considerate:
|
| 868 |
+
- sidekick
|
| 869 |
+
inconsiderate:
|
| 870 |
+
henchwoman: female
|
| 871 |
+
henchman: male
|
| 872 |
+
- type: or
|
| 873 |
+
considerate:
|
| 874 |
+
- sidekicks
|
| 875 |
+
inconsiderate:
|
| 876 |
+
henchwomen: female
|
| 877 |
+
henchmen: male
|
| 878 |
+
- type: or
|
| 879 |
+
considerate:
|
| 880 |
+
- role-model
|
| 881 |
+
- mentor
|
| 882 |
+
inconsiderate:
|
| 883 |
+
heroine: female
|
| 884 |
+
hero: male
|
| 885 |
+
- type: or
|
| 886 |
+
considerate:
|
| 887 |
+
- role-models
|
| 888 |
+
- mentor
|
| 889 |
+
inconsiderate:
|
| 890 |
+
heroines: female
|
| 891 |
+
heroes: male
|
| 892 |
+
- type: or
|
| 893 |
+
considerate:
|
| 894 |
+
- parental
|
| 895 |
+
- warm
|
| 896 |
+
- intimate
|
| 897 |
+
inconsiderate:
|
| 898 |
+
maternal: female
|
| 899 |
+
paternal: male
|
| 900 |
+
fraternal: male
|
| 901 |
+
- type: or
|
| 902 |
+
considerate:
|
| 903 |
+
- parental
|
| 904 |
+
inconsiderate:
|
| 905 |
+
maternity: female
|
| 906 |
+
paternity: male
|
| 907 |
+
- type: or
|
| 908 |
+
considerate:
|
| 909 |
+
- parents
|
| 910 |
+
inconsiderate:
|
| 911 |
+
mamas: female
|
| 912 |
+
mothers: female
|
| 913 |
+
moms: female
|
| 914 |
+
mums: female
|
| 915 |
+
mommas: female
|
| 916 |
+
mommies: female
|
| 917 |
+
papas: male
|
| 918 |
+
fathers: male
|
| 919 |
+
dads: male
|
| 920 |
+
daddies: male
|
| 921 |
+
- type: or
|
| 922 |
+
considerate:
|
| 923 |
+
- parent
|
| 924 |
+
inconsiderate:
|
| 925 |
+
mama: female
|
| 926 |
+
mother: female
|
| 927 |
+
mom: female
|
| 928 |
+
mum: female
|
| 929 |
+
momma: female
|
| 930 |
+
mommy: female
|
| 931 |
+
papa: male
|
| 932 |
+
father: male
|
| 933 |
+
dad: male
|
| 934 |
+
pop: male
|
| 935 |
+
daddy: male
|
| 936 |
+
- type: or
|
| 937 |
+
considerate:
|
| 938 |
+
- child
|
| 939 |
+
inconsiderate:
|
| 940 |
+
daughter: female
|
| 941 |
+
son: male
|
| 942 |
+
- type: or
|
| 943 |
+
considerate:
|
| 944 |
+
- children
|
| 945 |
+
inconsiderate:
|
| 946 |
+
daughters: female
|
| 947 |
+
sons: male
|
| 948 |
+
- type: or
|
| 949 |
+
considerate:
|
| 950 |
+
- concierge
|
| 951 |
+
inconsiderate:
|
| 952 |
+
doorwoman: female
|
| 953 |
+
doorman: male
|
| 954 |
+
- type: or
|
| 955 |
+
considerate:
|
| 956 |
+
- concierges
|
| 957 |
+
inconsiderate:
|
| 958 |
+
doorwomen: female
|
| 959 |
+
doormen: male
|
| 960 |
+
- type: or
|
| 961 |
+
considerate:
|
| 962 |
+
- humanly
|
| 963 |
+
- mature
|
| 964 |
+
inconsiderate:
|
| 965 |
+
feminin: female
|
| 966 |
+
dudely: male
|
| 967 |
+
manly: male
|
| 968 |
+
- type: or
|
| 969 |
+
considerate:
|
| 970 |
+
- humans
|
| 971 |
+
inconsiderate:
|
| 972 |
+
females: female
|
| 973 |
+
males: male
|
| 974 |
+
- type: or
|
| 975 |
+
considerate:
|
| 976 |
+
- ruler
|
| 977 |
+
inconsiderate:
|
| 978 |
+
empress: female
|
| 979 |
+
queen: female
|
| 980 |
+
emperor: male
|
| 981 |
+
king: male
|
| 982 |
+
- type: or
|
| 983 |
+
considerate:
|
| 984 |
+
- rulers
|
| 985 |
+
inconsiderate:
|
| 986 |
+
empresses: female
|
| 987 |
+
queens: female
|
| 988 |
+
emperors: male
|
| 989 |
+
kings: male
|
| 990 |
+
- type: or
|
| 991 |
+
considerate:
|
| 992 |
+
- jumbo
|
| 993 |
+
- gigantic
|
| 994 |
+
inconsiderate:
|
| 995 |
+
queensize: female
|
| 996 |
+
kingsize: male
|
| 997 |
+
- type: or
|
| 998 |
+
considerate:
|
| 999 |
+
- power behind the throne
|
| 1000 |
+
inconsiderate:
|
| 1001 |
+
queenmaker: female
|
| 1002 |
+
kingmaker: male
|
| 1003 |
+
- type: or
|
| 1004 |
+
considerate:
|
| 1005 |
+
- civilian
|
| 1006 |
+
inconsiderate:
|
| 1007 |
+
laywoman: female
|
| 1008 |
+
layman: male
|
| 1009 |
+
- type: or
|
| 1010 |
+
considerate:
|
| 1011 |
+
- civilians
|
| 1012 |
+
inconsiderate:
|
| 1013 |
+
laywomen: female
|
| 1014 |
+
laymen: male
|
| 1015 |
+
- type: or
|
| 1016 |
+
considerate:
|
| 1017 |
+
- official
|
| 1018 |
+
- owner
|
| 1019 |
+
- expert
|
| 1020 |
+
- superior
|
| 1021 |
+
- chief
|
| 1022 |
+
- ruler
|
| 1023 |
+
inconsiderate:
|
| 1024 |
+
dame: female
|
| 1025 |
+
lord: male
|
| 1026 |
+
- type: or
|
| 1027 |
+
considerate:
|
| 1028 |
+
- officials
|
| 1029 |
+
- chiefs
|
| 1030 |
+
- rulers
|
| 1031 |
+
inconsiderate:
|
| 1032 |
+
dames: female
|
| 1033 |
+
lords: male
|
| 1034 |
+
- type: or
|
| 1035 |
+
considerate:
|
| 1036 |
+
- adulthood
|
| 1037 |
+
- personhood
|
| 1038 |
+
- maturity
|
| 1039 |
+
inconsiderate:
|
| 1040 |
+
womanhood: female
|
| 1041 |
+
masculinity: male
|
| 1042 |
+
manhood: male
|
| 1043 |
+
- type: or
|
| 1044 |
+
considerate:
|
| 1045 |
+
- humanity
|
| 1046 |
+
inconsiderate:
|
| 1047 |
+
femininity: female
|
| 1048 |
+
manliness: male
|
| 1049 |
+
- type: or
|
| 1050 |
+
considerate:
|
| 1051 |
+
- shooter
|
| 1052 |
+
inconsiderate:
|
| 1053 |
+
markswoman: female
|
| 1054 |
+
marksman: male
|
| 1055 |
+
- type: or
|
| 1056 |
+
considerate:
|
| 1057 |
+
- shooters
|
| 1058 |
+
inconsiderate:
|
| 1059 |
+
markswomen: female
|
| 1060 |
+
marksmen: male
|
| 1061 |
+
- type: or
|
| 1062 |
+
considerate:
|
| 1063 |
+
- intermediary
|
| 1064 |
+
- go-between
|
| 1065 |
+
inconsiderate:
|
| 1066 |
+
middlewoman: female
|
| 1067 |
+
middleman: male
|
| 1068 |
+
- type: or
|
| 1069 |
+
considerate:
|
| 1070 |
+
- intermediaries
|
| 1071 |
+
- go-betweens
|
| 1072 |
+
inconsiderate:
|
| 1073 |
+
middlewomen: female
|
| 1074 |
+
middlemen: male
|
| 1075 |
+
- type: or
|
| 1076 |
+
considerate:
|
| 1077 |
+
- milk person
|
| 1078 |
+
inconsiderate:
|
| 1079 |
+
milkwoman: female
|
| 1080 |
+
milkman: male
|
| 1081 |
+
- type: or
|
| 1082 |
+
considerate:
|
| 1083 |
+
- milk people
|
| 1084 |
+
inconsiderate:
|
| 1085 |
+
milkwomen: female
|
| 1086 |
+
milkmen: male
|
| 1087 |
+
- type: or
|
| 1088 |
+
considerate:
|
| 1089 |
+
- nibling
|
| 1090 |
+
- sibling’s child
|
| 1091 |
+
inconsiderate:
|
| 1092 |
+
niece: female
|
| 1093 |
+
nephew: male
|
| 1094 |
+
- type: or
|
| 1095 |
+
considerate:
|
| 1096 |
+
- niblings
|
| 1097 |
+
- sibling’s children
|
| 1098 |
+
inconsiderate:
|
| 1099 |
+
nieces: female
|
| 1100 |
+
nephews: male
|
| 1101 |
+
- type: or
|
| 1102 |
+
considerate:
|
| 1103 |
+
- noble
|
| 1104 |
+
inconsiderate:
|
| 1105 |
+
noblewoman: female
|
| 1106 |
+
nobleman: male
|
| 1107 |
+
- type: or
|
| 1108 |
+
considerate:
|
| 1109 |
+
- nobles
|
| 1110 |
+
inconsiderate:
|
| 1111 |
+
noblewomen: female
|
| 1112 |
+
noblemen: male
|
| 1113 |
+
- type: or
|
| 1114 |
+
considerate:
|
| 1115 |
+
- notary
|
| 1116 |
+
- consumer advocate
|
| 1117 |
+
- trouble shooter
|
| 1118 |
+
- omsbudperson
|
| 1119 |
+
- mediator
|
| 1120 |
+
inconsiderate:
|
| 1121 |
+
ombudswoman: female
|
| 1122 |
+
ombudsman: male
|
| 1123 |
+
- type: or
|
| 1124 |
+
considerate:
|
| 1125 |
+
- notaries
|
| 1126 |
+
- omsbudpersons
|
| 1127 |
+
- omsbudpeople
|
| 1128 |
+
- mediators
|
| 1129 |
+
inconsiderate:
|
| 1130 |
+
ombudswomen: female
|
| 1131 |
+
ombudsmen: male
|
| 1132 |
+
- type: or
|
| 1133 |
+
considerate:
|
| 1134 |
+
- heir
|
| 1135 |
+
inconsiderate:
|
| 1136 |
+
princess: female
|
| 1137 |
+
prince: male
|
| 1138 |
+
- type: or
|
| 1139 |
+
considerate:
|
| 1140 |
+
- heirs
|
| 1141 |
+
inconsiderate:
|
| 1142 |
+
princesses: female
|
| 1143 |
+
princes: male
|
| 1144 |
+
- type: or
|
| 1145 |
+
considerate:
|
| 1146 |
+
- fairy
|
| 1147 |
+
inconsiderate:
|
| 1148 |
+
sandwoman: female
|
| 1149 |
+
sandman: male
|
| 1150 |
+
- type: or
|
| 1151 |
+
considerate:
|
| 1152 |
+
- fairies
|
| 1153 |
+
inconsiderate:
|
| 1154 |
+
sandwomen: female
|
| 1155 |
+
sandmen: male
|
| 1156 |
+
- type: or
|
| 1157 |
+
considerate:
|
| 1158 |
+
- promoter
|
| 1159 |
+
inconsiderate:
|
| 1160 |
+
showwoman: female
|
| 1161 |
+
showman: male
|
| 1162 |
+
- type: or
|
| 1163 |
+
considerate:
|
| 1164 |
+
- promoters
|
| 1165 |
+
inconsiderate:
|
| 1166 |
+
showwomen: female
|
| 1167 |
+
show women: female
|
| 1168 |
+
showmen: male
|
| 1169 |
+
- type: or
|
| 1170 |
+
considerate:
|
| 1171 |
+
- astronaut
|
| 1172 |
+
inconsiderate:
|
| 1173 |
+
spacewoman: female
|
| 1174 |
+
spaceman: male
|
| 1175 |
+
- type: or
|
| 1176 |
+
considerate:
|
| 1177 |
+
- astronauts
|
| 1178 |
+
inconsiderate:
|
| 1179 |
+
spacewomen: female
|
| 1180 |
+
spacemen: male
|
| 1181 |
+
- type: or
|
| 1182 |
+
considerate:
|
| 1183 |
+
- speaker
|
| 1184 |
+
- spokesperson
|
| 1185 |
+
- representative
|
| 1186 |
+
inconsiderate:
|
| 1187 |
+
spokeswoman: female
|
| 1188 |
+
spokesman: male
|
| 1189 |
+
- type: or
|
| 1190 |
+
considerate:
|
| 1191 |
+
- speakers
|
| 1192 |
+
- spokespersons
|
| 1193 |
+
inconsiderate:
|
| 1194 |
+
spokeswomen: female
|
| 1195 |
+
spokesmen: male
|
| 1196 |
+
- type: or
|
| 1197 |
+
considerate:
|
| 1198 |
+
- athlete
|
| 1199 |
+
- sports person
|
| 1200 |
+
inconsiderate:
|
| 1201 |
+
sportswoman: female
|
| 1202 |
+
sportsman: male
|
| 1203 |
+
- type: or
|
| 1204 |
+
considerate:
|
| 1205 |
+
- athletes
|
| 1206 |
+
- sports persons
|
| 1207 |
+
inconsiderate:
|
| 1208 |
+
sportswomen: female
|
| 1209 |
+
sportsmen: male
|
| 1210 |
+
- type: or
|
| 1211 |
+
considerate:
|
| 1212 |
+
- senator
|
| 1213 |
+
inconsiderate:
|
| 1214 |
+
stateswoman: female
|
| 1215 |
+
statesman: male
|
| 1216 |
+
- type: or
|
| 1217 |
+
considerate:
|
| 1218 |
+
- step-sibling
|
| 1219 |
+
inconsiderate:
|
| 1220 |
+
stepsister: female
|
| 1221 |
+
stepbrother: male
|
| 1222 |
+
- type: or
|
| 1223 |
+
considerate:
|
| 1224 |
+
- step-siblings
|
| 1225 |
+
inconsiderate:
|
| 1226 |
+
stepsisters: female
|
| 1227 |
+
stepbrothers: male
|
| 1228 |
+
- type: or
|
| 1229 |
+
considerate:
|
| 1230 |
+
- step-parent
|
| 1231 |
+
inconsiderate:
|
| 1232 |
+
stepmom: female
|
| 1233 |
+
stepmother: female
|
| 1234 |
+
stepdad: male
|
| 1235 |
+
stepfather: male
|
| 1236 |
+
- type: or
|
| 1237 |
+
considerate:
|
| 1238 |
+
- step-parents
|
| 1239 |
+
inconsiderate:
|
| 1240 |
+
stepmothers: female
|
| 1241 |
+
stepfathers: male
|
| 1242 |
+
- type: or
|
| 1243 |
+
considerate:
|
| 1244 |
+
- titan
|
| 1245 |
+
inconsiderate:
|
| 1246 |
+
superwoman: female
|
| 1247 |
+
superman: male
|
| 1248 |
+
- type: or
|
| 1249 |
+
considerate:
|
| 1250 |
+
- titans
|
| 1251 |
+
inconsiderate:
|
| 1252 |
+
superwomen: female
|
| 1253 |
+
supermen: male
|
| 1254 |
+
- type: or
|
| 1255 |
+
considerate:
|
| 1256 |
+
- inhumane
|
| 1257 |
+
inconsiderate:
|
| 1258 |
+
unwomanly: female
|
| 1259 |
+
unwomenly: female
|
| 1260 |
+
unmanly: male
|
| 1261 |
+
unmenly: male
|
| 1262 |
+
- type: or
|
| 1263 |
+
considerate:
|
| 1264 |
+
- watcher
|
| 1265 |
+
inconsiderate:
|
| 1266 |
+
watchwoman: female
|
| 1267 |
+
watchman: male
|
| 1268 |
+
- type: or
|
| 1269 |
+
considerate:
|
| 1270 |
+
- watchers
|
| 1271 |
+
inconsiderate:
|
| 1272 |
+
watchwomen: female
|
| 1273 |
+
watchmen: male
|
| 1274 |
+
- type: or
|
| 1275 |
+
considerate:
|
| 1276 |
+
- weather forecaster
|
| 1277 |
+
- meteorologist
|
| 1278 |
+
inconsiderate:
|
| 1279 |
+
weatherwoman: female
|
| 1280 |
+
weatherman: male
|
| 1281 |
+
- type: or
|
| 1282 |
+
considerate:
|
| 1283 |
+
- weather forecasters
|
| 1284 |
+
- meteorologists
|
| 1285 |
+
inconsiderate:
|
| 1286 |
+
weatherwomen: female
|
| 1287 |
+
weathermen: male
|
| 1288 |
+
- type: or
|
| 1289 |
+
considerate:
|
| 1290 |
+
- bereaved
|
| 1291 |
+
inconsiderate:
|
| 1292 |
+
widow: female
|
| 1293 |
+
widows: female
|
| 1294 |
+
widower: male
|
| 1295 |
+
widowers: male
|
| 1296 |
+
- type: or
|
| 1297 |
+
considerate:
|
| 1298 |
+
- own person
|
| 1299 |
+
inconsiderate:
|
| 1300 |
+
own woman: female
|
| 1301 |
+
own man: male
|
| 1302 |
+
- type: basic
|
| 1303 |
+
considerate:
|
| 1304 |
+
- french
|
| 1305 |
+
- the french
|
| 1306 |
+
inconsiderate:
|
| 1307 |
+
frenchmen: male
|
| 1308 |
+
- type: basic
|
| 1309 |
+
considerate:
|
| 1310 |
+
- courteous
|
| 1311 |
+
- cultured
|
| 1312 |
+
inconsiderate:
|
| 1313 |
+
ladylike: female
|
| 1314 |
+
- type: basic
|
| 1315 |
+
considerate:
|
| 1316 |
+
- resolutely
|
| 1317 |
+
- bravely
|
| 1318 |
+
inconsiderate:
|
| 1319 |
+
like a man: male
|
| 1320 |
+
- type: basic
|
| 1321 |
+
considerate:
|
| 1322 |
+
- birth name
|
| 1323 |
+
inconsiderate:
|
| 1324 |
+
maiden name: female
|
| 1325 |
+
- type: basic
|
| 1326 |
+
considerate:
|
| 1327 |
+
- first voyage
|
| 1328 |
+
inconsiderate:
|
| 1329 |
+
maiden voyage: female
|
| 1330 |
+
- type: basic
|
| 1331 |
+
considerate:
|
| 1332 |
+
- first flight
|
| 1333 |
+
inconsiderate:
|
| 1334 |
+
maiden flight: female
|
| 1335 |
+
- type: basic
|
| 1336 |
+
considerate:
|
| 1337 |
+
- strong enough
|
| 1338 |
+
inconsiderate:
|
| 1339 |
+
man enough: male
|
| 1340 |
+
- type: basic
|
| 1341 |
+
considerate:
|
| 1342 |
+
- upstaging
|
| 1343 |
+
- competitiveness
|
| 1344 |
+
inconsiderate:
|
| 1345 |
+
oneupmanship: male
|
| 1346 |
+
- type: basic
|
| 1347 |
+
considerate:
|
| 1348 |
+
- ms.
|
| 1349 |
+
inconsiderate:
|
| 1350 |
+
miss.: female
|
| 1351 |
+
mrs.: female
|
| 1352 |
+
- type: basic
|
| 1353 |
+
considerate:
|
| 1354 |
+
- manufactured
|
| 1355 |
+
- artificial
|
| 1356 |
+
- synthetic
|
| 1357 |
+
- machine-made
|
| 1358 |
+
- constructed
|
| 1359 |
+
inconsiderate:
|
| 1360 |
+
manmade: male
|
| 1361 |
+
- type: basic
|
| 1362 |
+
considerate:
|
| 1363 |
+
- dynamo
|
| 1364 |
+
inconsiderate:
|
| 1365 |
+
man of action: male
|
| 1366 |
+
- type: basic
|
| 1367 |
+
considerate:
|
| 1368 |
+
- scholar
|
| 1369 |
+
- writer
|
| 1370 |
+
- literary figure
|
| 1371 |
+
inconsiderate:
|
| 1372 |
+
man of letters: male
|
| 1373 |
+
- type: basic
|
| 1374 |
+
considerate:
|
| 1375 |
+
- sophisticate
|
| 1376 |
+
inconsiderate:
|
| 1377 |
+
man of the world: male
|
| 1378 |
+
- type: basic
|
| 1379 |
+
considerate:
|
| 1380 |
+
- camaraderie
|
| 1381 |
+
- community
|
| 1382 |
+
- organization
|
| 1383 |
+
inconsiderate:
|
| 1384 |
+
fellowship: male
|
| 1385 |
+
- type: basic
|
| 1386 |
+
considerate:
|
| 1387 |
+
- first-year student
|
| 1388 |
+
- fresher
|
| 1389 |
+
inconsiderate:
|
| 1390 |
+
freshman: male
|
| 1391 |
+
freshwoman: male
|
| 1392 |
+
- type: basic
|
| 1393 |
+
considerate:
|
| 1394 |
+
- quality construction
|
| 1395 |
+
- expertise
|
| 1396 |
+
inconsiderate:
|
| 1397 |
+
workmanship: male
|
| 1398 |
+
- type: basic
|
| 1399 |
+
considerate:
|
| 1400 |
+
- homemaker
|
| 1401 |
+
- homeworker
|
| 1402 |
+
inconsiderate:
|
| 1403 |
+
housewife: female
|
| 1404 |
+
- type: basic
|
| 1405 |
+
considerate:
|
| 1406 |
+
- homemakers
|
| 1407 |
+
- homeworkers
|
| 1408 |
+
inconsiderate:
|
| 1409 |
+
housewives: female
|
| 1410 |
+
- type: basic
|
| 1411 |
+
considerate:
|
| 1412 |
+
- loving
|
| 1413 |
+
- warm
|
| 1414 |
+
- nurturing
|
| 1415 |
+
inconsiderate:
|
| 1416 |
+
motherly: female
|
| 1417 |
+
- type: basic
|
| 1418 |
+
considerate:
|
| 1419 |
+
- human resources
|
| 1420 |
+
- workforce
|
| 1421 |
+
- personnel
|
| 1422 |
+
- staff
|
| 1423 |
+
- labor
|
| 1424 |
+
- personnel
|
| 1425 |
+
- labor force
|
| 1426 |
+
- staffing
|
| 1427 |
+
- combat personnel
|
| 1428 |
+
inconsiderate:
|
| 1429 |
+
manpower: male
|
| 1430 |
+
- type: basic
|
| 1431 |
+
considerate:
|
| 1432 |
+
- emcee
|
| 1433 |
+
- moderator
|
| 1434 |
+
- convenor
|
| 1435 |
+
inconsiderate:
|
| 1436 |
+
master of ceremonies: male
|
| 1437 |
+
- type: basic
|
| 1438 |
+
considerate:
|
| 1439 |
+
- skilled
|
| 1440 |
+
- authoritative
|
| 1441 |
+
- commanding
|
| 1442 |
+
inconsiderate:
|
| 1443 |
+
masterful: male
|
| 1444 |
+
- type: basic
|
| 1445 |
+
considerate:
|
| 1446 |
+
- genius
|
| 1447 |
+
- creator
|
| 1448 |
+
- instigator
|
| 1449 |
+
- oversee
|
| 1450 |
+
- launch
|
| 1451 |
+
- originate
|
| 1452 |
+
inconsiderate:
|
| 1453 |
+
mastermind: male
|
| 1454 |
+
- type: basic
|
| 1455 |
+
considerate:
|
| 1456 |
+
- work of genius
|
| 1457 |
+
- chef d’oeuvre
|
| 1458 |
+
inconsiderate:
|
| 1459 |
+
masterpiece: male
|
| 1460 |
+
- type: basic
|
| 1461 |
+
considerate:
|
| 1462 |
+
- vision
|
| 1463 |
+
- comprehensive plan
|
| 1464 |
+
inconsiderate:
|
| 1465 |
+
masterplan: male
|
| 1466 |
+
- type: basic
|
| 1467 |
+
considerate:
|
| 1468 |
+
- trump card
|
| 1469 |
+
- stroke of genius
|
| 1470 |
+
inconsiderate:
|
| 1471 |
+
masterstroke: male
|
| 1472 |
+
- type: basic
|
| 1473 |
+
considerate:
|
| 1474 |
+
- fanatic
|
| 1475 |
+
- zealot
|
| 1476 |
+
- enthusiast
|
| 1477 |
+
inconsiderate:
|
| 1478 |
+
madman: male
|
| 1479 |
+
mad man: male
|
| 1480 |
+
- type: basic
|
| 1481 |
+
considerate:
|
| 1482 |
+
- fanatics
|
| 1483 |
+
- zealots
|
| 1484 |
+
- enthusiasts
|
| 1485 |
+
inconsiderate:
|
| 1486 |
+
madmen: male
|
| 1487 |
+
mad men: male
|
| 1488 |
+
- type: basic
|
| 1489 |
+
considerate:
|
| 1490 |
+
- humankind
|
| 1491 |
+
inconsiderate:
|
| 1492 |
+
mankind: male
|
| 1493 |
+
- type: basic
|
| 1494 |
+
considerate:
|
| 1495 |
+
- staff hour
|
| 1496 |
+
- hour of work
|
| 1497 |
+
inconsiderate:
|
| 1498 |
+
manhour: male
|
| 1499 |
+
man hour: male
|
| 1500 |
+
- type: basic
|
| 1501 |
+
considerate:
|
| 1502 |
+
- staff hours
|
| 1503 |
+
- hours of work
|
| 1504 |
+
- hours of labor
|
| 1505 |
+
- hours
|
| 1506 |
+
inconsiderate:
|
| 1507 |
+
manhours: male
|
| 1508 |
+
man hours: male
|
| 1509 |
+
- type: basic
|
| 1510 |
+
note: Using gender neutral language means users will help to break up gender stereotypes.
|
| 1511 |
+
considerate:
|
| 1512 |
+
- staffed
|
| 1513 |
+
- crewed
|
| 1514 |
+
- piloted
|
| 1515 |
+
inconsiderate:
|
| 1516 |
+
- manned
|
| 1517 |
+
- type: basic
|
| 1518 |
+
note: Using gender neutral language means users will help to break up gender stereotypes.
|
| 1519 |
+
considerate:
|
| 1520 |
+
- robotic
|
| 1521 |
+
- automated
|
| 1522 |
+
inconsiderate:
|
| 1523 |
+
- unmanned
|
| 1524 |
+
- type: basic
|
| 1525 |
+
considerate:
|
| 1526 |
+
- whining
|
| 1527 |
+
- complaining
|
| 1528 |
+
- crying
|
| 1529 |
+
inconsiderate:
|
| 1530 |
+
- bitching
|
| 1531 |
+
- moaning
|
| 1532 |
+
- type: basic
|
| 1533 |
+
considerate:
|
| 1534 |
+
- whine
|
| 1535 |
+
- complain
|
| 1536 |
+
- cry
|
| 1537 |
+
inconsiderate:
|
| 1538 |
+
- bitch
|
| 1539 |
+
- moan
|
| 1540 |
+
- type: basic
|
| 1541 |
+
considerate:
|
| 1542 |
+
- tank top
|
| 1543 |
+
- sleeveless undershirt
|
| 1544 |
+
inconsiderate:
|
| 1545 |
+
- wife beater
|
| 1546 |
+
- wifebeater
|
| 1547 |
+
- type: basic
|
| 1548 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1549 |
+
considerate:
|
| 1550 |
+
- ancient civilization
|
| 1551 |
+
- ancient people
|
| 1552 |
+
inconsiderate: ancient man
|
| 1553 |
+
- type: basic
|
| 1554 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1555 |
+
considerate:
|
| 1556 |
+
- author
|
| 1557 |
+
- writer
|
| 1558 |
+
inconsiderate: authoress
|
| 1559 |
+
- type: basic
|
| 1560 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1561 |
+
considerate:
|
| 1562 |
+
- average consumer
|
| 1563 |
+
- average household
|
| 1564 |
+
- average homemaker
|
| 1565 |
+
inconsiderate: average housewife
|
| 1566 |
+
- type: basic
|
| 1567 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1568 |
+
considerate: average person
|
| 1569 |
+
inconsiderate: average man
|
| 1570 |
+
- type: basic
|
| 1571 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1572 |
+
considerate:
|
| 1573 |
+
- average wage earner
|
| 1574 |
+
- average taxpayer
|
| 1575 |
+
inconsiderate: average working man
|
| 1576 |
+
- type: basic
|
| 1577 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1578 |
+
considerate: aviator
|
| 1579 |
+
inconsiderate: aviatrix
|
| 1580 |
+
- type: basic
|
| 1581 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1582 |
+
considerate: the human family
|
| 1583 |
+
inconsiderate: brotherhood of man
|
| 1584 |
+
- type: basic
|
| 1585 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1586 |
+
considerate: model
|
| 1587 |
+
inconsiderate: calendar girl
|
| 1588 |
+
- type: basic
|
| 1589 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1590 |
+
considerate:
|
| 1591 |
+
- escort
|
| 1592 |
+
- prostitute
|
| 1593 |
+
- sex worker
|
| 1594 |
+
inconsiderate: call girl
|
| 1595 |
+
- type: basic
|
| 1596 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1597 |
+
considerate:
|
| 1598 |
+
- cleric
|
| 1599 |
+
- practicing Christian
|
| 1600 |
+
- pillar of the Church
|
| 1601 |
+
inconsiderate: churchman
|
| 1602 |
+
- type: basic
|
| 1603 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1604 |
+
considerate:
|
| 1605 |
+
- english coordinator
|
| 1606 |
+
- senior teacher of english
|
| 1607 |
+
inconsiderate: english master
|
| 1608 |
+
- type: basic
|
| 1609 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1610 |
+
considerate: the english
|
| 1611 |
+
inconsiderate: englishmen
|
| 1612 |
+
- type: basic
|
| 1613 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1614 |
+
considerate: executor
|
| 1615 |
+
inconsiderate: executrix
|
| 1616 |
+
- type: basic
|
| 1617 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1618 |
+
considerate: founder of
|
| 1619 |
+
inconsiderate: father of *
|
| 1620 |
+
- type: basic
|
| 1621 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1622 |
+
considerate:
|
| 1623 |
+
- the founders
|
| 1624 |
+
- founding leaders
|
| 1625 |
+
- forebears
|
| 1626 |
+
inconsiderate: founding father
|
| 1627 |
+
- type: basic
|
| 1628 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1629 |
+
considerate:
|
| 1630 |
+
- house worker
|
| 1631 |
+
- domestic help
|
| 1632 |
+
inconsiderate: housemaid
|
| 1633 |
+
- type: basic
|
| 1634 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1635 |
+
considerate:
|
| 1636 |
+
- industrial civilization
|
| 1637 |
+
- industrial people
|
| 1638 |
+
inconsiderate: industrial man
|
| 1639 |
+
- type: basic
|
| 1640 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1641 |
+
considerate: doctor
|
| 1642 |
+
inconsiderate: lady doctor
|
| 1643 |
+
- type: basic
|
| 1644 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1645 |
+
considerate: lead
|
| 1646 |
+
inconsiderate: leading lady
|
| 1647 |
+
- type: basic
|
| 1648 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1649 |
+
considerate: virgin
|
| 1650 |
+
inconsiderate: maiden
|
| 1651 |
+
- type: basic
|
| 1652 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1653 |
+
considerate: first race
|
| 1654 |
+
inconsiderate: maiden race
|
| 1655 |
+
- type: basic
|
| 1656 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1657 |
+
considerate: first speech
|
| 1658 |
+
inconsiderate: maiden speech
|
| 1659 |
+
- type: basic
|
| 1660 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1661 |
+
considerate: staff a desk
|
| 1662 |
+
inconsiderate: man a desk
|
| 1663 |
+
- type: basic
|
| 1664 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1665 |
+
considerate:
|
| 1666 |
+
- ordinary citizen
|
| 1667 |
+
- typical person
|
| 1668 |
+
- average person
|
| 1669 |
+
inconsiderate: man in the street
|
| 1670 |
+
- type: basic
|
| 1671 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1672 |
+
considerate:
|
| 1673 |
+
- farmer
|
| 1674 |
+
- rural worker
|
| 1675 |
+
- grazier
|
| 1676 |
+
- landowner
|
| 1677 |
+
- rural community
|
| 1678 |
+
- country people
|
| 1679 |
+
- country folk
|
| 1680 |
+
inconsiderate: man of the land
|
| 1681 |
+
- type: basic
|
| 1682 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1683 |
+
considerate: a faithful dog
|
| 1684 |
+
inconsiderate: mans best friend
|
| 1685 |
+
- type: basic
|
| 1686 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1687 |
+
considerate: staff the booth
|
| 1688 |
+
inconsiderate: man the booth
|
| 1689 |
+
- type: basic
|
| 1690 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1691 |
+
considerate: answer the phones
|
| 1692 |
+
inconsiderate: man the phones
|
| 1693 |
+
- type: basic
|
| 1694 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1695 |
+
considerate:
|
| 1696 |
+
- a demanding task
|
| 1697 |
+
- a big job
|
| 1698 |
+
inconsiderate:
|
| 1699 |
+
- mansized task
|
| 1700 |
+
- man sized task
|
| 1701 |
+
- type: basic
|
| 1702 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1703 |
+
considerate:
|
| 1704 |
+
- pass key
|
| 1705 |
+
- original
|
| 1706 |
+
inconsiderate:
|
| 1707 |
+
- master key
|
| 1708 |
+
- master copy
|
| 1709 |
+
- type: basic
|
| 1710 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1711 |
+
considerate:
|
| 1712 |
+
- grand scheme
|
| 1713 |
+
- guiding principles
|
| 1714 |
+
inconsiderate: master plan
|
| 1715 |
+
- type: basic
|
| 1716 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1717 |
+
considerate: become skilled
|
| 1718 |
+
inconsiderate: master the art
|
| 1719 |
+
- type: basic
|
| 1720 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1721 |
+
considerate: scientists
|
| 1722 |
+
inconsiderate: men of science
|
| 1723 |
+
- type: basic
|
| 1724 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1725 |
+
considerate: birthing nurse
|
| 1726 |
+
inconsiderate: midwife
|
| 1727 |
+
- type: basic
|
| 1728 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1729 |
+
considerate:
|
| 1730 |
+
- modern civilization
|
| 1731 |
+
- modern people
|
| 1732 |
+
inconsiderate: modern man
|
| 1733 |
+
- type: basic
|
| 1734 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1735 |
+
considerate:
|
| 1736 |
+
- unoccupied territory
|
| 1737 |
+
- wasteland
|
| 1738 |
+
- deathtrap
|
| 1739 |
+
inconsiderate: no mans land
|
| 1740 |
+
- type: basic
|
| 1741 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1742 |
+
considerate: administrative staff
|
| 1743 |
+
inconsiderate: office girls
|
| 1744 |
+
- type: basic
|
| 1745 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1746 |
+
considerate: poet
|
| 1747 |
+
inconsiderate: poetess
|
| 1748 |
+
- type: basic
|
| 1749 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1750 |
+
considerate: railway worker
|
| 1751 |
+
inconsiderate: railwayman
|
| 1752 |
+
- type: basic
|
| 1753 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1754 |
+
considerate:
|
| 1755 |
+
- fair
|
| 1756 |
+
- sporting
|
| 1757 |
+
inconsiderate: sportsmanlike
|
| 1758 |
+
- type: basic
|
| 1759 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1760 |
+
considerate:
|
| 1761 |
+
- fairness
|
| 1762 |
+
- good humor
|
| 1763 |
+
- sense of fair play
|
| 1764 |
+
inconsiderate: sportsmanship
|
| 1765 |
+
- type: basic
|
| 1766 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1767 |
+
considerate: diplomatic
|
| 1768 |
+
inconsiderate:
|
| 1769 |
+
- statesmanlike
|
| 1770 |
+
- statesman like
|
| 1771 |
+
- type: basic
|
| 1772 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1773 |
+
considerate:
|
| 1774 |
+
- cattle worker
|
| 1775 |
+
- farmhand
|
| 1776 |
+
- drover
|
| 1777 |
+
inconsiderate: stockman
|
| 1778 |
+
- type: basic
|
| 1779 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1780 |
+
considerate: service entrance
|
| 1781 |
+
inconsiderate: tradesmans entrance
|
| 1782 |
+
- type: basic
|
| 1783 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1784 |
+
considerate:
|
| 1785 |
+
- tax commissioner
|
| 1786 |
+
- tax office
|
| 1787 |
+
- tax collector
|
| 1788 |
+
inconsiderate: tax man
|
| 1789 |
+
- type: basic
|
| 1790 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1791 |
+
considerate: usher
|
| 1792 |
+
inconsiderate: usherette
|
| 1793 |
+
- type: basic
|
| 1794 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1795 |
+
considerate: lawyer
|
| 1796 |
+
inconsiderate: woman lawyer
|
| 1797 |
+
- type: basic
|
| 1798 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1799 |
+
considerate: painter
|
| 1800 |
+
inconsiderate: woman painter
|
| 1801 |
+
- type: basic
|
| 1802 |
+
source: https://radyananda.wordpress.com/2009/06/06/nonsexist-alternative-language-handbook-for-conscious-writers/
|
| 1803 |
+
considerate:
|
| 1804 |
+
- wage or salary earning woman
|
| 1805 |
+
- two-income family
|
| 1806 |
+
inconsiderate:
|
| 1807 |
+
- working mother
|
| 1808 |
+
- working wife
|
app/data/en/lgbtq.yml
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- type: basic
|
| 2 |
+
source: https://www.glaad.org/reference/offensive
|
| 3 |
+
note: This term has a clinical history and is used to imply LGBTQ+ people are diseased or psychologically/emotionally disordered
|
| 4 |
+
considerate:
|
| 5 |
+
- gay
|
| 6 |
+
- gay man
|
| 7 |
+
- lesbian
|
| 8 |
+
- gay person/people
|
| 9 |
+
inconsiderate:
|
| 10 |
+
- homosexual
|
| 11 |
+
- type: basic
|
| 12 |
+
source: https://www.glaad.org/reference/offensive
|
| 13 |
+
note: Avoid labeling something as LGBTQ+ unless you would call the same thing “straight”
|
| 14 |
+
considerate:
|
| 15 |
+
- relationship
|
| 16 |
+
inconsiderate:
|
| 17 |
+
- homosexual relations
|
| 18 |
+
- homosexual relationship
|
| 19 |
+
- type: basic
|
| 20 |
+
source: https://www.glaad.org/reference/offensive
|
| 21 |
+
note: Avoid labeling something as LGBTQ+ unless you would call the same thing “straight”
|
| 22 |
+
considerate:
|
| 23 |
+
- couple
|
| 24 |
+
inconsiderate:
|
| 25 |
+
- homosexual couple
|
| 26 |
+
- type: basic
|
| 27 |
+
source: https://www.glaad.org/reference/offensive
|
| 28 |
+
note: Implies that being LGBTQ+ is a choice
|
| 29 |
+
considerate:
|
| 30 |
+
- sexual orientation
|
| 31 |
+
- orientation
|
| 32 |
+
inconsiderate:
|
| 33 |
+
- sexual preference
|
| 34 |
+
- type: basic
|
| 35 |
+
source: https://www.glaad.org/reference/offensive
|
| 36 |
+
note: Implies that being LGBTQ+ is a choice
|
| 37 |
+
considerate:
|
| 38 |
+
- gay lives
|
| 39 |
+
- gay/lesbian lives
|
| 40 |
+
inconsiderate:
|
| 41 |
+
- gay lifestyle
|
| 42 |
+
- homosexual lifestyle
|
| 43 |
+
- type: basic
|
| 44 |
+
source: https://www.glaad.org/reference/offensive
|
| 45 |
+
note: Used by anti-LGBTQ+ extremists to create a climate of fear around LGBTQ+ issues
|
| 46 |
+
considerate:
|
| 47 |
+
- gay issues
|
| 48 |
+
inconsiderate:
|
| 49 |
+
- gay agenda
|
| 50 |
+
- homosexual agenda
|
| 51 |
+
- type: basic
|
| 52 |
+
source: https://www.glaad.org/reference/style
|
| 53 |
+
note: LGBTQ+ rights are human rights
|
| 54 |
+
considerate:
|
| 55 |
+
- equal rights
|
| 56 |
+
- civil rights for gay people
|
| 57 |
+
inconsiderate:
|
| 58 |
+
- special rights
|
| 59 |
+
- gay rights
|
| 60 |
+
- type: basic
|
| 61 |
+
source: https://www.glaad.org/reference/offensive
|
| 62 |
+
note: Derogatory terms for LGBTQ+ people are offensive
|
| 63 |
+
considerate:
|
| 64 |
+
- gay
|
| 65 |
+
inconsiderate:
|
| 66 |
+
- fag
|
| 67 |
+
- faggot
|
| 68 |
+
- dyke
|
| 69 |
+
- homo
|
| 70 |
+
- sodomite
|
| 71 |
+
- type: basic
|
| 72 |
+
source: https://www.glaad.org/reference/style
|
| 73 |
+
note: Avoid using slang shorthand
|
| 74 |
+
considerate:
|
| 75 |
+
- bisexual
|
| 76 |
+
inconsiderate:
|
| 77 |
+
- bi
|
| 78 |
+
- type: basic
|
| 79 |
+
source: https://www.glaad.org/reference/style
|
| 80 |
+
note: Homosexual has a clinical history and is used to imply LGBTQ+ people are diseased or psychologically/emotionally disordered
|
| 81 |
+
considerate:
|
| 82 |
+
- gay marriage
|
| 83 |
+
- same-sex marriage
|
| 84 |
+
inconsiderate:
|
| 85 |
+
- homosexual marriage
|
| 86 |
+
- type: basic
|
| 87 |
+
source: https://www.glaad.org/reference/style
|
| 88 |
+
note: Derogatory terms for LGBTQ+ people are offensive
|
| 89 |
+
considerate:
|
| 90 |
+
- transgender
|
| 91 |
+
inconsiderate:
|
| 92 |
+
- tranny
|
| 93 |
+
- type: basic
|
| 94 |
+
source: https://www.glaad.org/reference/transgender
|
| 95 |
+
note: Avoid using outdated / offensive terms
|
| 96 |
+
considerate:
|
| 97 |
+
- cross-dresser
|
| 98 |
+
inconsiderate:
|
| 99 |
+
- transvestite
|
| 100 |
+
- type: basic
|
| 101 |
+
source: https://www.glaad.org/reference/transgender
|
| 102 |
+
note: Avoid overemphasizing surgery when discussing transgender people or the process of transition - it’s not a necessary component
|
| 103 |
+
considerate:
|
| 104 |
+
- transition
|
| 105 |
+
- gender confirmation surgery
|
| 106 |
+
inconsiderate:
|
| 107 |
+
- sexchange
|
| 108 |
+
- sex change
|
| 109 |
+
- type: basic
|
| 110 |
+
source: https://www.glaad.org/reference/transgender
|
| 111 |
+
note: Shift focus away from the assigned sex and towards the identified gender
|
| 112 |
+
considerate:
|
| 113 |
+
- sex reassignment surgery
|
| 114 |
+
- gender confirmation surgery
|
| 115 |
+
inconsiderate:
|
| 116 |
+
- sex change operation
|
| 117 |
+
- type: basic
|
| 118 |
+
source: https://www.glaad.org/reference/transgender
|
| 119 |
+
note: Transgender should be used as an adjective, not as a noun
|
| 120 |
+
considerate:
|
| 121 |
+
- transgender people
|
| 122 |
+
inconsiderate:
|
| 123 |
+
- transgenders
|
| 124 |
+
- type: basic
|
| 125 |
+
source: https://www.glaad.org/reference/transgender
|
| 126 |
+
note: Transgender is already an adjective
|
| 127 |
+
considerate:
|
| 128 |
+
- transgender
|
| 129 |
+
inconsiderate:
|
| 130 |
+
- transgendered
|
| 131 |
+
- type: basic
|
| 132 |
+
source: https://www.glaad.org/reference/transgender
|
| 133 |
+
note: This is a term used by anti-transgender activists to dehumanize transgender people and reduce who they are to a condition
|
| 134 |
+
considerate:
|
| 135 |
+
- being transgender
|
| 136 |
+
- the movement for transgender equality
|
| 137 |
+
inconsiderate:
|
| 138 |
+
- transgenderism
|
| 139 |
+
- type: basic
|
| 140 |
+
note: Assigned birth gender is complicated; gender identity is more than what your parents decided you were at birth
|
| 141 |
+
considerate:
|
| 142 |
+
- assigned male at birth
|
| 143 |
+
- designated male at birth
|
| 144 |
+
inconsiderate:
|
| 145 |
+
- biologically male
|
| 146 |
+
- born a man
|
| 147 |
+
- genetically male
|
| 148 |
+
- type: basic
|
| 149 |
+
note: Assigned birth gender is complicated; gender identity is more than what your parents decided you were at birth
|
| 150 |
+
considerate:
|
| 151 |
+
- assigned female at birth
|
| 152 |
+
- designated female at birth
|
| 153 |
+
inconsiderate:
|
| 154 |
+
- biologically female
|
| 155 |
+
- born a woman
|
| 156 |
+
- genetically female
|
| 157 |
+
- type: basic
|
| 158 |
+
source: https://www.glaad.org/reference/transgender
|
| 159 |
+
note: A term created and used by far-right extremists to oppose nondiscrimination laws that protect transgender people
|
| 160 |
+
considerate:
|
| 161 |
+
- non-discrimination law
|
| 162 |
+
- non-discrimination ordinance
|
| 163 |
+
inconsiderate:
|
| 164 |
+
- bathroom bill
|
| 165 |
+
- type: basic
|
| 166 |
+
source: http://www.isna.org/node/979
|
| 167 |
+
note: These terms are stigmatizing to patients and their families because intersex status is more complicated than the mere presence or absence of certain gonadal tissues
|
| 168 |
+
considerate:
|
| 169 |
+
- intersex
|
| 170 |
+
inconsiderate:
|
| 171 |
+
- hermaphroditic
|
| 172 |
+
- pseudohermaphroditic
|
| 173 |
+
- pseudo hermaphroditic
|
| 174 |
+
- type: basic
|
| 175 |
+
source: http://www.isna.org/node/979
|
| 176 |
+
note: These terms are stigmatizing to patients and their families because intersex status is more complicated than the mere presence or absence of certain gonadal tissues
|
| 177 |
+
considerate:
|
| 178 |
+
- person who is intersex
|
| 179 |
+
- person
|
| 180 |
+
- intersex person
|
| 181 |
+
inconsiderate:
|
| 182 |
+
- hermaphrodite
|
| 183 |
+
- pseudohermaphrodite
|
| 184 |
+
- pseudo hermaphrodite
|
| 185 |
+
- type: basic
|
| 186 |
+
source: https://www.reddit.com/r/asktransgender/comments/23wbq1/is_the_term_shemale_seen_as_offensive/
|
| 187 |
+
note: This word dehumanizes transgender people
|
| 188 |
+
considerate:
|
| 189 |
+
- transgender person
|
| 190 |
+
- person
|
| 191 |
+
inconsiderate:
|
| 192 |
+
- shemale
|
| 193 |
+
- she male
|
| 194 |
+
- heshe
|
| 195 |
+
- shehe
|
| 196 |
+
- type: basic
|
| 197 |
+
source: https://www.selfdefined.app/definitions/pronouns/
|
| 198 |
+
note: Preferred pronoun sounds like it is optional to use someone's correct pronoun
|
| 199 |
+
considerate:
|
| 200 |
+
- pronoun
|
| 201 |
+
- pronouns
|
| 202 |
+
inconsiderate:
|
| 203 |
+
- preferred pronoun
|
| 204 |
+
- preferred pronouns
|
| 205 |
+
- gender pronoun
|
| 206 |
+
- gender pronouns
|
app/data/en/misc.yml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- type: basic
|
| 2 |
+
note: Avoid using terms that implies colonialism/genocide against Indigenous peoples
|
| 3 |
+
considerate:
|
| 4 |
+
- keep an eye on things
|
| 5 |
+
- keep shop
|
| 6 |
+
- provide coverage
|
| 7 |
+
- cover things
|
| 8 |
+
- take charge
|
| 9 |
+
inconsiderate:
|
| 10 |
+
- man the fort
|
| 11 |
+
- type: basic
|
| 12 |
+
note: Avoid using terms that relate to gun violence.
|
| 13 |
+
considerate:
|
| 14 |
+
- go for it
|
| 15 |
+
- take a chance
|
| 16 |
+
- make a move
|
| 17 |
+
- take action
|
| 18 |
+
inconsiderate:
|
| 19 |
+
- pull the trigger
|
app/data/en/press.yml
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- type: basic
|
| 2 |
+
source: https://www.usnews.com/news/newsgram/articles/2013/04/04/the-associated-press-revises-islamist-another-politically-charged-term
|
| 3 |
+
considerate:
|
| 4 |
+
- muslim
|
| 5 |
+
- person of Islamic faith
|
| 6 |
+
- fanatic
|
| 7 |
+
- zealot
|
| 8 |
+
- follower of islam
|
| 9 |
+
- follower of the islamic faith
|
| 10 |
+
inconsiderate:
|
| 11 |
+
- islamist
|
| 12 |
+
- type: basic
|
| 13 |
+
source: https://www.usnews.com/news/newsgram/articles/2013/04/04/the-associated-press-revises-islamist-another-politically-charged-term
|
| 14 |
+
considerate:
|
| 15 |
+
- muslims
|
| 16 |
+
- people of Islamic faith
|
| 17 |
+
- fanatics
|
| 18 |
+
- zealots
|
| 19 |
+
inconsiderate:
|
| 20 |
+
- islamists
|
app/data/en/race.yml
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- type: basic
|
| 2 |
+
note: Avoid using the term `master`; these suggestions are for the computer term, but there are better alternatives for other cases too
|
| 3 |
+
considerate:
|
| 4 |
+
- primary
|
| 5 |
+
- lead
|
| 6 |
+
- hub
|
| 7 |
+
- reference
|
| 8 |
+
inconsiderate:
|
| 9 |
+
- master
|
| 10 |
+
- type: basic
|
| 11 |
+
note: Avoid using the term `master`; these suggestions are for the computer term, but there are better alternatives for other cases too
|
| 12 |
+
considerate:
|
| 13 |
+
- primaries
|
| 14 |
+
- hubs
|
| 15 |
+
- references
|
| 16 |
+
inconsiderate:
|
| 17 |
+
- masters
|
| 18 |
+
- type: basic
|
| 19 |
+
note: Avoid using the term `slave`; these suggestions are for the computer term, but there are better alternatives for other cases too
|
| 20 |
+
considerate:
|
| 21 |
+
- secondary
|
| 22 |
+
- worker
|
| 23 |
+
- replica
|
| 24 |
+
- node
|
| 25 |
+
inconsiderate:
|
| 26 |
+
- slave
|
| 27 |
+
- type: basic
|
| 28 |
+
note: Avoid using the term `slave`; these suggestions are for the computer term, but there are better alternatives for other cases too
|
| 29 |
+
considerate:
|
| 30 |
+
- secondaries
|
| 31 |
+
- workers
|
| 32 |
+
- replicas
|
| 33 |
+
- nodes
|
| 34 |
+
inconsiderate:
|
| 35 |
+
- slaves
|
| 36 |
+
- type: basic
|
| 37 |
+
considerate:
|
| 38 |
+
- unethical hacker
|
| 39 |
+
- malicious actor
|
| 40 |
+
inconsiderate:
|
| 41 |
+
- blackhat
|
| 42 |
+
- type: basic
|
| 43 |
+
considerate:
|
| 44 |
+
- ethical hacker
|
| 45 |
+
- security researcher
|
| 46 |
+
inconsiderate:
|
| 47 |
+
- whitehat
|
| 48 |
+
- type: basic
|
| 49 |
+
considerate:
|
| 50 |
+
- Inuit
|
| 51 |
+
inconsiderate:
|
| 52 |
+
- eskimo
|
| 53 |
+
- type: basic
|
| 54 |
+
considerate:
|
| 55 |
+
- Inuits
|
| 56 |
+
inconsiderate:
|
| 57 |
+
- eskimos
|
| 58 |
+
- type: basic
|
| 59 |
+
considerate:
|
| 60 |
+
- Asian person
|
| 61 |
+
inconsiderate:
|
| 62 |
+
- oriental
|
| 63 |
+
- type: basic
|
| 64 |
+
considerate:
|
| 65 |
+
- Asian people
|
| 66 |
+
inconsiderate:
|
| 67 |
+
- orientals
|
| 68 |
+
- type: basic
|
| 69 |
+
considerate:
|
| 70 |
+
- person of color
|
| 71 |
+
- people of color
|
| 72 |
+
inconsiderate:
|
| 73 |
+
- nonwhite
|
| 74 |
+
- non white
|
| 75 |
+
- type: basic
|
| 76 |
+
considerate:
|
| 77 |
+
- projects
|
| 78 |
+
- urban
|
| 79 |
+
inconsiderate:
|
| 80 |
+
- ghetto
|
| 81 |
+
- type: basic
|
| 82 |
+
considerate:
|
| 83 |
+
- Native American
|
| 84 |
+
inconsiderate:
|
| 85 |
+
- red indian
|
| 86 |
+
- pocahontas
|
| 87 |
+
- redskin
|
| 88 |
+
- type: basic
|
| 89 |
+
considerate:
|
| 90 |
+
- Native American People
|
| 91 |
+
inconsiderate:
|
| 92 |
+
- red indians
|
| 93 |
+
- redskins
|
| 94 |
+
- type: basic
|
| 95 |
+
inconsiderate:
|
| 96 |
+
- animal spirit
|
| 97 |
+
- dream catcher
|
| 98 |
+
- spirit animal
|
| 99 |
+
- totem
|
| 100 |
+
note: Avoid using terms that oversimplify the complex and varied beliefs of indigenous religions.
|
| 101 |
+
source:
|
| 102 |
+
- https://www.worldreligionnews.com/opinion/spirit-animal-not-joke-oppression
|
| 103 |
+
- https://www.spiralnature.com/spirituality/spirit-animal-cultural-appropriation
|
| 104 |
+
considerate:
|
| 105 |
+
- favorite
|
| 106 |
+
- inspiration
|
| 107 |
+
- personal interest
|
| 108 |
+
- personality type
|
| 109 |
+
- type: basic
|
| 110 |
+
inconsiderate:
|
| 111 |
+
- long time no hear
|
| 112 |
+
- long time no see
|
| 113 |
+
note: Avoid using phrases that implicitly mock people with limited knowledge of the English language.
|
| 114 |
+
source: https://www.npr.org/sections/codeswitch/2014/03/09/288300303/who-first-said-long-time-no-see-and-in-which-language
|
| 115 |
+
considerate:
|
| 116 |
+
- I haven’t seen you in a long time
|
| 117 |
+
- it’s been a long time
|
| 118 |
+
- type: basic
|
| 119 |
+
inconsiderate:
|
| 120 |
+
- Indian country
|
| 121 |
+
note: Avoid using phrases referring to the genocidal United States “Indian Removal” laws.
|
| 122 |
+
source:
|
| 123 |
+
- https://newsmaven.io/indiancountrytoday/archive/off-the-reservation-a-teachable-moment-nW1d7U0JRkOszhtg8N1V1A/
|
| 124 |
+
considerate:
|
| 125 |
+
- enemy territory
|
| 126 |
+
- type: basic
|
| 127 |
+
inconsiderate:
|
| 128 |
+
- jump the reservation
|
| 129 |
+
- off reserve
|
| 130 |
+
- off the reservation
|
| 131 |
+
note: Avoid using phrases referring to the genocidal United States “Indian Removal” laws.
|
| 132 |
+
source:
|
| 133 |
+
- http://blog.nativepartnership.org/off-the-reservation/
|
| 134 |
+
- https://www.wsj.com/articles/off-the-reservation-is-a-phrase-with-a-dark-past-1462552837
|
| 135 |
+
- https://www.npr.org/sections/codeswitch/2014/06/29/326690947/should-saying-someone-is-off-the-reservation-be-off-limits
|
| 136 |
+
- https://nowtoronto.com/news/native-references-and-terms-that-are-offensive-to-indigenous-people/
|
| 137 |
+
considerate:
|
| 138 |
+
- disobey
|
| 139 |
+
- endure
|
| 140 |
+
- object to
|
| 141 |
+
- oppose
|
| 142 |
+
- resist
|
| 143 |
+
- type: basic
|
| 144 |
+
inconsiderate:
|
| 145 |
+
- circle the wagons
|
| 146 |
+
- on the warpath
|
| 147 |
+
note: Avoid using phrases referring to colonial stereotypes regarding Native Americans.
|
| 148 |
+
source:
|
| 149 |
+
- https://idioms.thefreedictionary.com/circle+the+wagons
|
| 150 |
+
- https://idioms.thefreedictionary.com/go+on+the+warpath
|
| 151 |
+
considerate:
|
| 152 |
+
- defend
|
| 153 |
+
- type: basic
|
| 154 |
+
inconsiderate:
|
| 155 |
+
- too many chiefs
|
| 156 |
+
note: Avoid using phrases referring to colonial stereotypes regarding Native Americans.
|
| 157 |
+
source:
|
| 158 |
+
- https://idioms.thefreedictionary.com/too+many+chiefs+and+not+enough+Indians
|
| 159 |
+
considerate:
|
| 160 |
+
- too many chefs in the kitchen
|
| 161 |
+
- too many cooks spoil the broth
|
| 162 |
+
- type: basic
|
| 163 |
+
inconsiderate:
|
| 164 |
+
- natives are restless
|
| 165 |
+
- natives are becoming restless
|
| 166 |
+
- natives are getting restless
|
| 167 |
+
- natives are growing restless
|
| 168 |
+
note: Avoid using phrases referring to colonial stereotypes regarding indigenous peoples.
|
| 169 |
+
source:
|
| 170 |
+
- https://tvtropes.org/pmwiki/pmwiki.php/Main/TheNativesAreRestless
|
| 171 |
+
considerate:
|
| 172 |
+
- dissatisfied
|
| 173 |
+
- frustrated
|
| 174 |
+
- type: basic
|
| 175 |
+
inconsiderate:
|
| 176 |
+
- pow wow
|
| 177 |
+
- powwow
|
| 178 |
+
note: Avoid casually using this term, which refers to traditional indigenous celebration ceremonies that were banned by genocidal laws in the United States and Canada — Native people died fighting for this right.
|
| 179 |
+
source:
|
| 180 |
+
- https://twitter.com/chadloder/status/1203507070772793345
|
| 181 |
+
- http://nativeappropriations.com/2012/09/paul-frank-offends-every-native-person-on-the-planet-with-fashion-night-out-dream-catchin-pow-wow.html
|
| 182 |
+
- https://www.britannica.com/topic/powwow
|
| 183 |
+
- https://nowtoronto.com/news/native-references-and-terms-that-are-offensive-to-indigenous-people/
|
| 184 |
+
considerate:
|
| 185 |
+
- conference
|
| 186 |
+
- gathering
|
| 187 |
+
- meeting
|
| 188 |
+
- type: basic
|
| 189 |
+
note: Avoid using phrases referring to colonial stereotypes regarding Native Americans.
|
| 190 |
+
considerate:
|
| 191 |
+
- go back on one’s offer
|
| 192 |
+
inconsiderate:
|
| 193 |
+
- indian give
|
| 194 |
+
- indian giver
|
| 195 |
+
- type: basic
|
| 196 |
+
considerate:
|
| 197 |
+
- Filipinos
|
| 198 |
+
- Filipino people
|
| 199 |
+
inconsiderate:
|
| 200 |
+
- pinoys
|
| 201 |
+
- pinays
|
| 202 |
+
- type: basic
|
| 203 |
+
considerate:
|
| 204 |
+
- Arabs
|
| 205 |
+
- Middle Eastern People
|
| 206 |
+
inconsiderate:
|
| 207 |
+
- towel heads
|
| 208 |
+
- type: basic
|
| 209 |
+
note: Whenever possible, try to be gender inclusive.
|
| 210 |
+
considerate:
|
| 211 |
+
- Latinx
|
| 212 |
+
inconsiderate:
|
| 213 |
+
- latino
|
| 214 |
+
- latina
|
| 215 |
+
- type: basic
|
| 216 |
+
considerate:
|
| 217 |
+
- Japanese person
|
| 218 |
+
- Japanese people
|
| 219 |
+
inconsiderate:
|
| 220 |
+
- japs
|
| 221 |
+
- type: basic
|
| 222 |
+
considerate:
|
| 223 |
+
- Jewish person
|
| 224 |
+
inconsiderate:
|
| 225 |
+
- shlomo
|
| 226 |
+
- shyster
|
| 227 |
+
- hymie
|
| 228 |
+
- type: basic
|
| 229 |
+
considerate:
|
| 230 |
+
- a person who is not Jewish
|
| 231 |
+
- not Jewish
|
| 232 |
+
inconsiderate:
|
| 233 |
+
- goyim
|
| 234 |
+
- goyum
|
| 235 |
+
- goy
|
| 236 |
+
- type: basic
|
| 237 |
+
considerate:
|
| 238 |
+
- a Black person
|
| 239 |
+
inconsiderate:
|
| 240 |
+
- spade
|
| 241 |
+
- type: basic
|
| 242 |
+
source: en.wikipedia.org/wiki/Romani_people#cite_ref-80
|
| 243 |
+
note: Gypsy is insensitive, use Roma or Romani. They’re not Egyptian as the name suggests.
|
| 244 |
+
considerate:
|
| 245 |
+
- Nomad
|
| 246 |
+
- Traveler
|
| 247 |
+
- Roma
|
| 248 |
+
- Romani
|
| 249 |
+
inconsiderate:
|
| 250 |
+
- gyppo
|
| 251 |
+
- gypsy
|
| 252 |
+
- Gipsy
|
| 253 |
+
- gyp
|
| 254 |
+
- type: basic
|
| 255 |
+
note: Replace racially-charged language with more accurate and inclusive words
|
| 256 |
+
considerate:
|
| 257 |
+
- blocklist
|
| 258 |
+
- wronglist
|
| 259 |
+
- banlist
|
| 260 |
+
- deny list
|
| 261 |
+
inconsiderate:
|
| 262 |
+
- blacklist
|
| 263 |
+
- black list
|
| 264 |
+
- type: basic
|
| 265 |
+
note: Replace racially-charged language with more accurate and inclusive words
|
| 266 |
+
considerate:
|
| 267 |
+
- blocklisted
|
| 268 |
+
- wronglisted
|
| 269 |
+
- banlisted
|
| 270 |
+
- deny-listed
|
| 271 |
+
inconsiderate:
|
| 272 |
+
- blacklisted
|
| 273 |
+
- type: basic
|
| 274 |
+
note: Replace racially-charged language with more accurate and inclusive words
|
| 275 |
+
considerate:
|
| 276 |
+
- blocklisting
|
| 277 |
+
- wronglisting
|
| 278 |
+
- banlisting
|
| 279 |
+
- deny-listing
|
| 280 |
+
inconsiderate:
|
| 281 |
+
- blacklisting
|
| 282 |
+
- type: basic
|
| 283 |
+
note: Replace racially-charged language with more accurate and inclusive words
|
| 284 |
+
considerate:
|
| 285 |
+
- passlist
|
| 286 |
+
- alrightlist
|
| 287 |
+
- safelist
|
| 288 |
+
- allow list
|
| 289 |
+
inconsiderate:
|
| 290 |
+
- whitelist
|
| 291 |
+
- white list
|
| 292 |
+
- type: basic
|
| 293 |
+
note: Replace racially-charged language with more accurate and inclusive words
|
| 294 |
+
considerate:
|
| 295 |
+
- passlisted
|
| 296 |
+
- alrightlisted
|
| 297 |
+
- safelisted
|
| 298 |
+
- allow-listed
|
| 299 |
+
inconsiderate:
|
| 300 |
+
- whitelisted
|
| 301 |
+
- type: basic
|
| 302 |
+
note: Replace racially-charged language with more accurate and inclusive words
|
| 303 |
+
considerate:
|
| 304 |
+
- passlisting
|
| 305 |
+
- alrightlisting
|
| 306 |
+
- safelisting
|
| 307 |
+
- allow-listing
|
| 308 |
+
inconsiderate:
|
| 309 |
+
- whitelisting
|
| 310 |
+
- type: basic
|
| 311 |
+
note: Avoid using terms that imply a group has not changed over time and that they are inferior
|
| 312 |
+
considerate:
|
| 313 |
+
- simple
|
| 314 |
+
- indigenous
|
| 315 |
+
- hunter-gatherer
|
| 316 |
+
inconsiderate:
|
| 317 |
+
- primitive
|
| 318 |
+
- savage
|
| 319 |
+
- stone age
|
| 320 |
+
- type: basic
|
| 321 |
+
note: Avoid using terms that make some groups sound inferior
|
| 322 |
+
considerate:
|
| 323 |
+
- society
|
| 324 |
+
- community
|
| 325 |
+
inconsiderate:
|
| 326 |
+
- tribe
|
| 327 |
+
- type: basic
|
| 328 |
+
note: Avoid using terms that make some groups sound inferior. Replace “sophisticated” with a neutral term such as “complex”
|
| 329 |
+
considerate:
|
| 330 |
+
- complex culture
|
| 331 |
+
inconsiderate:
|
| 332 |
+
- sophisticated culture
|
| 333 |
+
- type: basic
|
| 334 |
+
note: Avoid using terms that make some groups sound inferior. Replace “sophisticated” with a neutral term such as “complex”
|
| 335 |
+
considerate:
|
| 336 |
+
- complex technology
|
| 337 |
+
inconsiderate:
|
| 338 |
+
- sophisticated technology
|
| 339 |
+
- type: basic
|
| 340 |
+
note: Avoid using `bugreport`, as the word `bugre` is a slur in Brazilian Portuguese
|
| 341 |
+
considerate:
|
| 342 |
+
- bug report
|
| 343 |
+
- snapshot
|
| 344 |
+
inconsiderate:
|
| 345 |
+
- bugreport
|
| 346 |
+
- type: basic
|
| 347 |
+
source: https://en.wikipedia.org/wiki/Grandfather_clause#Origin
|
| 348 |
+
note: Avoid using phrases referring to racist United States “Jim Crow” laws.
|
| 349 |
+
considerate:
|
| 350 |
+
- legacy policy
|
| 351 |
+
- legacy clause
|
| 352 |
+
- deprecation policy
|
| 353 |
+
inconsiderate:
|
| 354 |
+
- grandfather clause
|
| 355 |
+
- grandfather policy
|
| 356 |
+
- type: basic
|
| 357 |
+
source: https://en.wikipedia.org/wiki/Grandfather_clause#Origin
|
| 358 |
+
note: Avoid using phrases referring to racist United States “Jim Crow” laws.
|
| 359 |
+
considerate:
|
| 360 |
+
- deprecate
|
| 361 |
+
inconsiderate:
|
| 362 |
+
- grandfathering
|
| 363 |
+
- type: basic
|
| 364 |
+
source: https://en.wikipedia.org/wiki/Grandfather_clause#Origin
|
| 365 |
+
note: Avoid using phrases referring to racist United States “Jim Crow” laws.
|
| 366 |
+
considerate:
|
| 367 |
+
- deprecated
|
| 368 |
+
- legacy
|
| 369 |
+
inconsiderate:
|
| 370 |
+
- grandfathered
|
app/data/en/slogans.yml
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- type: basic
|
| 2 |
+
considerate:
|
| 3 |
+
- improve
|
| 4 |
+
inconsiderate:
|
| 5 |
+
- make * great again
|
| 6 |
+
- make * * great again
|
| 7 |
+
- make * * * great again
|
| 8 |
+
- make * * * * great again
|
| 9 |
+
- make * * * * * great again
|
app/data/en/suicide.yml
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- type: basic
|
| 2 |
+
source: https://www.afsp.org/news-events/for-the-media/reporting-on-suicide, https://www.speakingofsuicide.com/2013/04/13/language/
|
| 3 |
+
considerate:
|
| 4 |
+
- died by suicide
|
| 5 |
+
inconsiderate:
|
| 6 |
+
- committed suicide
|
| 7 |
+
- completed suicide
|
| 8 |
+
- type: basic
|
| 9 |
+
source: https://www.afsp.org/news-events/for-the-media/reporting-on-suicide, https://www.speakingofsuicide.com/2013/04/13/language/
|
| 10 |
+
note: Committing suicide is not successful/unsuccessful, that sends the wrong message
|
| 11 |
+
considerate:
|
| 12 |
+
- die by suicide
|
| 13 |
+
inconsiderate:
|
| 14 |
+
- commit suicide
|
| 15 |
+
- complete suicide
|
| 16 |
+
- successful suicide
|
| 17 |
+
- type: basic
|
| 18 |
+
source: https://www.afsp.org/news-events/for-the-media/reporting-on-suicide
|
| 19 |
+
note: Using sensational words can cause copycat suicides or contagion
|
| 20 |
+
considerate:
|
| 21 |
+
- rise in suicides
|
| 22 |
+
inconsiderate:
|
| 23 |
+
- suicide epidemic
|
| 24 |
+
- epidemic of suicides
|
| 25 |
+
- suicide pact
|
| 26 |
+
- type: basic
|
| 27 |
+
source: https://www.speakingofsuicide.com/2013/04/13/language, https://www.afsp.org/news-events/for-the-media/reporting-on-suicide
|
| 28 |
+
note: Attempted suicide should not be depicted as a failure
|
| 29 |
+
considerate:
|
| 30 |
+
- suicide attempt
|
| 31 |
+
- attempted suicide
|
| 32 |
+
inconsiderate:
|
| 33 |
+
- failed suicide
|
| 34 |
+
- failed attempt
|
| 35 |
+
- suicide failure
|
| 36 |
+
- type: basic
|
| 37 |
+
source: https://www.afsp.org/news-events/for-the-media/reporting-on-suicide
|
| 38 |
+
considerate:
|
| 39 |
+
- a note from the deceased
|
| 40 |
+
inconsiderate:
|
| 41 |
+
- suicide note
|
| 42 |
+
- type: basic
|
| 43 |
+
note: When describing the behavior of computer software, using the word “hanged” needlessly invokes the topic of death by self-harm or lynching. Consider using the word “froze” or the phrase “stopped responding to events” or “became unresponsive” instead.
|
| 44 |
+
considerate:
|
| 45 |
+
- the app froze
|
| 46 |
+
- the app stopped responding
|
| 47 |
+
- the app stopped responding to events
|
| 48 |
+
- the app became unresponsive
|
| 49 |
+
inconsiderate:
|
| 50 |
+
- hang
|
| 51 |
+
- hanged
|
app/main.py
CHANGED
|
@@ -1,48 +1,5 @@
|
|
| 1 |
-
from
|
| 2 |
-
|
| 3 |
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
logger = logging.getLogger(__name__)
|
| 7 |
-
|
| 8 |
-
# Import all individual routers for different functionalities
|
| 9 |
-
from app.routers import (
|
| 10 |
-
grammar,
|
| 11 |
-
punctuation,
|
| 12 |
-
sentence_correctness,
|
| 13 |
-
tone,
|
| 14 |
-
voice,
|
| 15 |
-
inclusive_language,
|
| 16 |
-
vocabulary,
|
| 17 |
-
conciseness,
|
| 18 |
-
readability,
|
| 19 |
-
paraphrase,
|
| 20 |
-
translate,
|
| 21 |
-
summarize
|
| 22 |
-
)
|
| 23 |
-
|
| 24 |
-
# Initialize the FastAPI application
|
| 25 |
-
app = FastAPI()
|
| 26 |
-
|
| 27 |
-
@app.get("/")
|
| 28 |
-
def root():
|
| 29 |
-
"""
|
| 30 |
-
Root endpoint for the API.
|
| 31 |
-
Returns a welcome message.
|
| 32 |
-
"""
|
| 33 |
-
logger.info("Root endpoint accessed.")
|
| 34 |
-
return {"message": "Welcome to Grammafree API"}
|
| 35 |
-
|
| 36 |
-
# Include all the individual routers for modular API structure.
|
| 37 |
-
app.include_router(grammar.router) # Grammar correction and diffs
|
| 38 |
-
app.include_router(punctuation.router) # Punctuation fixes
|
| 39 |
-
app.include_router(sentence_correctness.router) # Sentence correctness feedback
|
| 40 |
-
app.include_router(tone.router) # Tone detection and suggestions
|
| 41 |
-
app.include_router(voice.router) # Active/Passive voice detection
|
| 42 |
-
app.include_router(inclusive_language.router) # Inclusive language rewriting
|
| 43 |
-
app.include_router(vocabulary.router) # Vocabulary enhancement
|
| 44 |
-
app.include_router(conciseness.router) # Conciseness suggestions
|
| 45 |
-
app.include_router(readability.router) # Readability scores
|
| 46 |
-
app.include_router(paraphrase.router) # Existing paraphrasing functionality
|
| 47 |
-
app.include_router(translate.router) # Existing translation functionality
|
| 48 |
-
app.include_router(summarize.router) # Existing summarization functionality
|
|
|
|
| 1 |
+
from app.core.app import create_app
|
| 2 |
+
from app.core.logging import configure_logging
|
| 3 |
|
| 4 |
+
configure_logging()
|
| 5 |
+
app = create_app()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/models.py
DELETED
|
@@ -1,108 +0,0 @@
|
|
| 1 |
-
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, pipeline
|
| 2 |
-
import torch
|
| 3 |
-
|
| 4 |
-
# Set the device for model inference (CPU is used by default)
|
| 5 |
-
# You can change to "cuda" if a compatible GPU is available for faster processing.
|
| 6 |
-
device = torch.device("cpu")
|
| 7 |
-
|
| 8 |
-
# --- Grammar model ---
|
| 9 |
-
# Changed to deepashri/t5-small-grammar-correction, a publicly available model
|
| 10 |
-
# for grammatical error correction. This model is fine-tuned from T5-small.
|
| 11 |
-
grammar_tokenizer = AutoTokenizer.from_pretrained("AventIQ-AI/t5-small-grammar-correction")
|
| 12 |
-
grammar_model = AutoModelForSeq2SeqLM.from_pretrained("AventIQ-AI/t5-small-grammar-correction").to(device)
|
| 13 |
-
|
| 14 |
-
# --- FLAN-T5 for all prompts ---
|
| 15 |
-
# Uses google/flan-t5-small for various text generation tasks based on prompts,
|
| 16 |
-
# such as paraphrasing, summarizing, and generating tone suggestions.
|
| 17 |
-
flan_tokenizer = AutoTokenizer.from_pretrained("google/flan-t5-small")
|
| 18 |
-
flan_model = AutoModelForSeq2SeqLM.from_pretrained("google/flan-t5-small").to(device)
|
| 19 |
-
|
| 20 |
-
# --- Translation model ---
|
| 21 |
-
# Uses Helsinki-NLP/opus-mt-en-ROMANCE for English to Romance language translation.
|
| 22 |
-
trans_tokenizer = AutoTokenizer.from_pretrained("Helsinki-NLP/opus-mt-en-ROMANCE")
|
| 23 |
-
trans_model = AutoModelForSeq2SeqLM.from_pretrained("Helsinki-NLP/opus-mt-en-ROMANCE").to(device)
|
| 24 |
-
|
| 25 |
-
# --- Tone classification model ---
|
| 26 |
-
# Uses j-hartmann/emotion-english-distilroberta-base for detecting emotions/tones
|
| 27 |
-
# within text. This provides a more nuanced analysis than simple positive/negative.
|
| 28 |
-
# 'top_k=1' ensures that only the most confident label is returned.
|
| 29 |
-
tone_classifier = pipeline("sentiment-analysis", model="j-hartmann/emotion-english-distilroberta-base", top_k=1)
|
| 30 |
-
|
| 31 |
-
def run_grammar_correction(text: str) -> str:
|
| 32 |
-
"""
|
| 33 |
-
Corrects the grammar of the input text using the pre-trained T5 grammar model.
|
| 34 |
-
|
| 35 |
-
Args:
|
| 36 |
-
text (str): The input text to be grammatically corrected.
|
| 37 |
-
|
| 38 |
-
Returns:
|
| 39 |
-
str: The corrected text.
|
| 40 |
-
"""
|
| 41 |
-
# Prepare the input for the grammar model by prefixing with "grammar: " as per
|
| 42 |
-
# the 'deepashri/t5-small-grammar-correction' model's expected input format.
|
| 43 |
-
# Some grammar correction models expect a specific prefix like "grammar: " or "fix: ".
|
| 44 |
-
inputs = grammar_tokenizer(f"grammar: {text}", return_tensors="pt").to(device)
|
| 45 |
-
# Generate the corrected output
|
| 46 |
-
outputs = grammar_model.generate(**inputs)
|
| 47 |
-
# Decode the generated tokens back into a readable string, skipping special tokens
|
| 48 |
-
return grammar_tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 49 |
-
|
| 50 |
-
def run_flan_prompt(prompt: str) -> str:
|
| 51 |
-
"""
|
| 52 |
-
Runs a given prompt through the FLAN-T5 model to generate a response.
|
| 53 |
-
Includes advanced generation parameters for better output quality.
|
| 54 |
-
|
| 55 |
-
Args:
|
| 56 |
-
prompt (str): The prompt string to be processed by FLAN-T5.
|
| 57 |
-
|
| 58 |
-
Returns:
|
| 59 |
-
str: The generated text response from FLAN-T5.
|
| 60 |
-
"""
|
| 61 |
-
# Prepare the input for the FLAN-T5 model
|
| 62 |
-
inputs = flan_tokenizer(prompt, return_tensors="pt").to(device)
|
| 63 |
-
|
| 64 |
-
# Generate the output with improved parameters:
|
| 65 |
-
outputs = flan_model.generate(
|
| 66 |
-
**inputs,
|
| 67 |
-
max_new_tokens=100,
|
| 68 |
-
num_beams=5,
|
| 69 |
-
do_sample=True,
|
| 70 |
-
top_k=50,
|
| 71 |
-
top_p=0.95,
|
| 72 |
-
temperature=0.7
|
| 73 |
-
)
|
| 74 |
-
# Decode the generated tokens back into a readable string
|
| 75 |
-
return flan_tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 76 |
-
|
| 77 |
-
def run_translation(text: str, target_lang: str) -> str:
|
| 78 |
-
"""
|
| 79 |
-
Translates the input text to the target language using the Helsinki-NLP translation model.
|
| 80 |
-
|
| 81 |
-
Args:
|
| 82 |
-
text (str): The input text to be translated.
|
| 83 |
-
target_lang (str): The target language code (e.g., "fr" for French, "es" for Spanish).
|
| 84 |
-
|
| 85 |
-
Returns:
|
| 86 |
-
str: The translated text.
|
| 87 |
-
"""
|
| 88 |
-
# Prepare the input for the translation model by specifying the target language
|
| 89 |
-
inputs = trans_tokenizer(f">>{target_lang}<< {text}", return_tensors="pt").to(device)
|
| 90 |
-
# Generate the translated output
|
| 91 |
-
outputs = trans_model.generate(**inputs)
|
| 92 |
-
# Decode the generated tokens back into a readable string
|
| 93 |
-
return trans_tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 94 |
-
|
| 95 |
-
def classify_tone(text: str) -> str:
|
| 96 |
-
"""
|
| 97 |
-
Classifies the emotional tone of the input text using the pre-trained emotion classifier.
|
| 98 |
-
|
| 99 |
-
Args:
|
| 100 |
-
text (str): The input text for tone classification.
|
| 101 |
-
|
| 102 |
-
Returns:
|
| 103 |
-
str: The detected emotional label (e.g., 'neutral', 'joy', 'sadness', 'anger', 'fear', 'disgust', 'surprise').
|
| 104 |
-
"""
|
| 105 |
-
# The tone_classifier returns a list of dictionaries, where each dictionary
|
| 106 |
-
# contains 'label' and 'score'. We extract the 'label' from the first (and only) result.
|
| 107 |
-
result = tone_classifier(text)[0][0]
|
| 108 |
-
return result['label']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/prompts.py
DELETED
|
@@ -1,121 +0,0 @@
|
|
| 1 |
-
def tone_prompt(text: str, tone: str) -> str:
|
| 2 |
-
"""
|
| 3 |
-
Generates a prompt to rewrite text in a specified tone.
|
| 4 |
-
|
| 5 |
-
Args:
|
| 6 |
-
text (str): The original text.
|
| 7 |
-
tone (str): The desired tone (e.g., "formal", "informal", "confident").
|
| 8 |
-
|
| 9 |
-
Returns:
|
| 10 |
-
str: The generated prompt.
|
| 11 |
-
"""
|
| 12 |
-
return f"Rewrite the following text in a {tone} tone: {text}"
|
| 13 |
-
|
| 14 |
-
def clarity_prompt(text: str) -> str:
|
| 15 |
-
"""
|
| 16 |
-
Generates a prompt to make text clearer.
|
| 17 |
-
|
| 18 |
-
Args:
|
| 19 |
-
text (str): The original text.
|
| 20 |
-
|
| 21 |
-
Returns:
|
| 22 |
-
str: The generated prompt.
|
| 23 |
-
"""
|
| 24 |
-
return f"Make this clearer: {text}"
|
| 25 |
-
|
| 26 |
-
def fluency_prompt(text: str) -> str:
|
| 27 |
-
"""
|
| 28 |
-
Generates a prompt to improve the fluency of a sentence.
|
| 29 |
-
|
| 30 |
-
Args:
|
| 31 |
-
text (str): The original sentence.
|
| 32 |
-
|
| 33 |
-
Returns:
|
| 34 |
-
str: The generated prompt.
|
| 35 |
-
"""
|
| 36 |
-
return f"Improve the fluency of this sentence: {text}"
|
| 37 |
-
|
| 38 |
-
def paraphrase_prompt(text: str) -> str:
|
| 39 |
-
"""
|
| 40 |
-
Generates a prompt to paraphrase text.
|
| 41 |
-
|
| 42 |
-
Args:
|
| 43 |
-
text (str): The original text.
|
| 44 |
-
|
| 45 |
-
Returns:
|
| 46 |
-
str: The generated prompt.
|
| 47 |
-
"""
|
| 48 |
-
return f"Paraphrase: {text}"
|
| 49 |
-
|
| 50 |
-
def summarize_prompt(text: str) -> str:
|
| 51 |
-
"""
|
| 52 |
-
Generates a prompt to summarize text.
|
| 53 |
-
|
| 54 |
-
Args:
|
| 55 |
-
text (str): The original text.
|
| 56 |
-
|
| 57 |
-
Returns:
|
| 58 |
-
str: The generated prompt.
|
| 59 |
-
"""
|
| 60 |
-
return f"Summarize: {text}"
|
| 61 |
-
|
| 62 |
-
def pronoun_friendly_prompt(text: str) -> str:
|
| 63 |
-
"""
|
| 64 |
-
Generates a prompt to rewrite text using inclusive, respectful language,
|
| 65 |
-
avoiding gender-specific pronouns.
|
| 66 |
-
|
| 67 |
-
Args:
|
| 68 |
-
text (str): The original text.
|
| 69 |
-
|
| 70 |
-
Returns:
|
| 71 |
-
str: The generated prompt.
|
| 72 |
-
"""
|
| 73 |
-
return f"Rewrite the following text using inclusive, respectful language avoiding gender-specific pronouns: {text}"
|
| 74 |
-
|
| 75 |
-
def active_voice_prompt(text: str) -> str:
|
| 76 |
-
"""
|
| 77 |
-
Generates a prompt to detect passive/active voice and suggest an active voice version if passive.
|
| 78 |
-
|
| 79 |
-
Args:
|
| 80 |
-
text (str): The original text.
|
| 81 |
-
|
| 82 |
-
Returns:
|
| 83 |
-
str: The generated prompt.
|
| 84 |
-
"""
|
| 85 |
-
return f"Detect if this is passive or active voice. If passive, suggest an active voice version: {text}"
|
| 86 |
-
|
| 87 |
-
def tone_analysis_prompt(text: str) -> str:
|
| 88 |
-
"""
|
| 89 |
-
Generates a prompt to analyze the tone of text and suggest improvements.
|
| 90 |
-
|
| 91 |
-
Args:
|
| 92 |
-
text (str): The original text.
|
| 93 |
-
|
| 94 |
-
Returns:
|
| 95 |
-
str: The generated prompt.
|
| 96 |
-
"""
|
| 97 |
-
return f"Analyze the tone of the following text and suggest improvements if needed: {text}"
|
| 98 |
-
|
| 99 |
-
def vocabulary_prompt(text: str) -> str:
|
| 100 |
-
"""
|
| 101 |
-
Generates a prompt to suggest vocabulary improvements for the given text.
|
| 102 |
-
|
| 103 |
-
Args:
|
| 104 |
-
text (str): The original text.
|
| 105 |
-
|
| 106 |
-
Returns:
|
| 107 |
-
str: The generated prompt.
|
| 108 |
-
"""
|
| 109 |
-
return f"For the following text, identify any weak or overused words and suggest stronger, more precise synonyms or alternative phrasing. Provide suggestions as a list of 'original word/phrase -> suggested word/phrase': {text}"
|
| 110 |
-
|
| 111 |
-
def conciseness_prompt(text: str) -> str:
|
| 112 |
-
"""
|
| 113 |
-
Generates a prompt to make the given text more concise.
|
| 114 |
-
|
| 115 |
-
Args:
|
| 116 |
-
text (str): The original text.
|
| 117 |
-
|
| 118 |
-
Returns:
|
| 119 |
-
str: The generated prompt.
|
| 120 |
-
"""
|
| 121 |
-
return f"Rewrite the following text to be more concise, removing any unnecessary words or phrases while retaining the original meaning: {text}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/routers/conciseness.py
DELETED
|
@@ -1,42 +0,0 @@
|
|
| 1 |
-
from fastapi import APIRouter, Depends, HTTPException, status # Import HTTPException and status
|
| 2 |
-
from pydantic import BaseModel
|
| 3 |
-
from app import models, prompts
|
| 4 |
-
from app.core.security import verify_api_key
|
| 5 |
-
import logging # Import logging
|
| 6 |
-
|
| 7 |
-
logger = logging.getLogger(__name__)
|
| 8 |
-
|
| 9 |
-
router = APIRouter()
|
| 10 |
-
|
| 11 |
-
class ConcisenessInput(BaseModel):
|
| 12 |
-
"""
|
| 13 |
-
Pydantic BaseModel for validating the input request body for the /conciseness_check endpoint.
|
| 14 |
-
It expects a single field: 'text' (string).
|
| 15 |
-
"""
|
| 16 |
-
text: str
|
| 17 |
-
|
| 18 |
-
@router.post("/conciseness_check", dependencies=[Depends(verify_api_key)])
|
| 19 |
-
def conciseness_check(payload: ConcisenessInput):
|
| 20 |
-
"""
|
| 21 |
-
Provides suggestions for making text more concise.
|
| 22 |
-
|
| 23 |
-
Args:
|
| 24 |
-
payload (ConcisenessInput): The request body containing the text to be analyzed.
|
| 25 |
-
|
| 26 |
-
Returns:
|
| 27 |
-
dict: A dictionary containing the concise version of the text.
|
| 28 |
-
"""
|
| 29 |
-
text = payload.text
|
| 30 |
-
|
| 31 |
-
try:
|
| 32 |
-
concise_text = models.run_flan_prompt(prompts.conciseness_prompt(text))
|
| 33 |
-
|
| 34 |
-
return {
|
| 35 |
-
"concise_version": concise_text
|
| 36 |
-
}
|
| 37 |
-
except Exception as e:
|
| 38 |
-
logger.error(f"Error in conciseness_check: {e}", exc_info=True)
|
| 39 |
-
raise HTTPException(
|
| 40 |
-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 41 |
-
detail=f"An error occurred during conciseness checking: {e}"
|
| 42 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/routers/grammar.py
CHANGED
|
@@ -1,61 +1,60 @@
|
|
| 1 |
-
from fastapi import APIRouter, Depends, HTTPException, status
|
| 2 |
-
from
|
| 3 |
-
from app import
|
| 4 |
from app.core.security import verify_api_key
|
| 5 |
import difflib
|
| 6 |
-
import logging
|
| 7 |
|
|
|
|
|
|
|
| 8 |
logger = logging.getLogger(__name__)
|
| 9 |
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
dict: A dictionary containing the corrected text and a list of changes.
|
| 29 |
-
"""
|
| 30 |
-
original_text = payload.text
|
| 31 |
-
|
| 32 |
-
try:
|
| 33 |
-
corrected_text = models.run_grammar_correction(original_text)
|
| 34 |
-
|
| 35 |
-
grammar_changes = []
|
| 36 |
-
s = difflib.SequenceMatcher(None, original_text.split(), corrected_text.split())
|
| 37 |
-
|
| 38 |
-
for opcode, i1, i2, j1, j2 in s.get_opcodes():
|
| 39 |
-
if opcode == 'replace':
|
| 40 |
-
original_part = ' '.join(original_text.split()[i1:i2])
|
| 41 |
-
corrected_part = ' '.join(corrected_text.split()[j1:j2])
|
| 42 |
-
grammar_changes.append(f"'{original_part}' \u2192 '{corrected_part}'")
|
| 43 |
-
elif opcode == 'delete':
|
| 44 |
-
deleted_part = ' '.join(original_text.split()[i1:i2])
|
| 45 |
-
grammar_changes.append(f"'{deleted_part}' removed")
|
| 46 |
-
elif opcode == 'insert':
|
| 47 |
-
inserted_part = ' '.join(corrected_text.split()[j1:j2])
|
| 48 |
-
grammar_changes.append(f"'{inserted_part}' added")
|
| 49 |
-
|
| 50 |
-
return {
|
| 51 |
-
"grammar": {
|
| 52 |
-
"corrected": corrected_text,
|
| 53 |
-
"changes": grammar_changes
|
| 54 |
-
}
|
| 55 |
}
|
| 56 |
-
|
| 57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
raise HTTPException(
|
| 59 |
-
status_code=status.
|
| 60 |
-
detail=
|
| 61 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter, Depends, HTTPException, status
|
| 2 |
+
from app.schemas.base import TextOnlyRequest
|
| 3 |
+
from app.services.grammar import GrammarCorrector
|
| 4 |
from app.core.security import verify_api_key
|
| 5 |
import difflib
|
| 6 |
+
import logging
|
| 7 |
|
| 8 |
+
router = APIRouter(prefix="/grammar", tags=["Grammar"])
|
| 9 |
+
corrector = GrammarCorrector()
|
| 10 |
logger = logging.getLogger(__name__)
|
| 11 |
|
| 12 |
+
def get_diff_issues(original: str, corrected: str):
|
| 13 |
+
matcher = difflib.SequenceMatcher(None, original, corrected)
|
| 14 |
+
issues = []
|
| 15 |
+
|
| 16 |
+
for tag, i1, i2, j1, j2 in matcher.get_opcodes():
|
| 17 |
+
if tag == 'equal':
|
| 18 |
+
continue
|
| 19 |
+
|
| 20 |
+
issue = {
|
| 21 |
+
"offset": i1,
|
| 22 |
+
"length": i2 - i1,
|
| 23 |
+
"original": original[i1:i2],
|
| 24 |
+
"suggestion": corrected[j1:j2],
|
| 25 |
+
"context_before": original[max(0, i1 - 15):i1],
|
| 26 |
+
"context_after": original[i2:i2 + 15],
|
| 27 |
+
"message": "Grammar correction",
|
| 28 |
+
"line": original[:i1].count("\n") + 1,
|
| 29 |
+
"column": i1 - original[:i1].rfind("\n") if "\n" in original[:i1] else i1 + 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
}
|
| 31 |
+
issues.append(issue)
|
| 32 |
+
|
| 33 |
+
return issues
|
| 34 |
+
|
| 35 |
+
@router.post("/", dependencies=[Depends(verify_api_key)])
|
| 36 |
+
def correct_grammar(payload: TextOnlyRequest):
|
| 37 |
+
text = payload.text.strip()
|
| 38 |
+
|
| 39 |
+
if not text:
|
| 40 |
raise HTTPException(
|
| 41 |
+
status_code=status.HTTP_400_BAD_REQUEST,
|
| 42 |
+
detail="Input text cannot be empty."
|
| 43 |
)
|
| 44 |
+
|
| 45 |
+
corrected = corrector.correct(text)
|
| 46 |
+
|
| 47 |
+
if corrected.startswith("Input text is empty."):
|
| 48 |
+
raise HTTPException(status_code=400, detail="Input text cannot be empty.")
|
| 49 |
+
elif corrected.startswith("An error occurred during grammar correction."):
|
| 50 |
+
raise HTTPException(status_code=500, detail=corrected)
|
| 51 |
+
|
| 52 |
+
issues = get_diff_issues(text, corrected)
|
| 53 |
+
|
| 54 |
+
return {
|
| 55 |
+
"grammar": {
|
| 56 |
+
"original_text": text,
|
| 57 |
+
"corrected_text_suggestion": corrected,
|
| 58 |
+
"issues": issues
|
| 59 |
+
}
|
| 60 |
+
}
|
app/routers/inclusive_language.py
CHANGED
|
@@ -1,42 +1,11 @@
|
|
| 1 |
-
from fastapi import APIRouter, Depends
|
| 2 |
-
from
|
| 3 |
-
from app import
|
| 4 |
from app.core.security import verify_api_key
|
| 5 |
-
import logging # Import logging
|
| 6 |
|
| 7 |
-
|
|
|
|
| 8 |
|
| 9 |
-
router =
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
"""
|
| 13 |
-
Pydantic BaseModel for validating the input request body for the /inclusive_language endpoint.
|
| 14 |
-
It expects a single field: 'text' (string).
|
| 15 |
-
"""
|
| 16 |
-
text: str
|
| 17 |
-
|
| 18 |
-
@router.post("/inclusive_language", dependencies=[Depends(verify_api_key)])
|
| 19 |
-
def inclusive_language_check(payload: InclusiveLanguageInput):
|
| 20 |
-
"""
|
| 21 |
-
Provides suggestions for rewriting text using inclusive language.
|
| 22 |
-
|
| 23 |
-
Args:
|
| 24 |
-
payload (InclusiveLanguageInput): The request body containing the text to be analyzed.
|
| 25 |
-
|
| 26 |
-
Returns:
|
| 27 |
-
dict: A dictionary containing the rewritten text with inclusive language.
|
| 28 |
-
"""
|
| 29 |
-
text = payload.text
|
| 30 |
-
|
| 31 |
-
try:
|
| 32 |
-
inclusive_text = models.run_flan_prompt(prompts.pronoun_friendly_prompt(text))
|
| 33 |
-
|
| 34 |
-
return {
|
| 35 |
-
"inclusive_pronouns": inclusive_text
|
| 36 |
-
}
|
| 37 |
-
except Exception as e:
|
| 38 |
-
logger.error(f"Error in inclusive_language_check: {e}", exc_info=True)
|
| 39 |
-
raise HTTPException(
|
| 40 |
-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 41 |
-
detail=f"An error occurred during inclusive language check: {e}"
|
| 42 |
-
)
|
|
|
|
| 1 |
+
from fastapi import APIRouter, Depends
|
| 2 |
+
from app.schemas.base import TextOnlyRequest
|
| 3 |
+
from app.services.inclusive_language import InclusiveLanguageChecker
|
| 4 |
from app.core.security import verify_api_key
|
|
|
|
| 5 |
|
| 6 |
+
router = APIRouter(prefix="/inclusive-language", tags=["Inclusive Language"])
|
| 7 |
+
checker = InclusiveLanguageChecker()
|
| 8 |
|
| 9 |
+
@router.post("/", dependencies=[Depends(verify_api_key)])
|
| 10 |
+
def check_inclusive_language(payload: TextOnlyRequest):
|
| 11 |
+
return {"suggestions": checker.check(payload.text)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/routers/paraphrase.py
CHANGED
|
@@ -1,39 +1,12 @@
|
|
| 1 |
-
from fastapi import APIRouter, Depends
|
| 2 |
-
from
|
| 3 |
-
from app import
|
| 4 |
from app.core.security import verify_api_key
|
| 5 |
-
import logging # Import logging
|
| 6 |
|
| 7 |
-
|
|
|
|
| 8 |
|
| 9 |
-
router =
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
""
|
| 13 |
-
Pydantic BaseModel for validating the input request body for the /paraphrase endpoint.
|
| 14 |
-
It expects a single field: 'text' (string).
|
| 15 |
-
"""
|
| 16 |
-
text: str
|
| 17 |
-
|
| 18 |
-
@router.post("/paraphrase", dependencies=[Depends(verify_api_key)])
|
| 19 |
-
def paraphrase(payload: ParaphraseInput): # Renamed input to payload for consistency
|
| 20 |
-
"""
|
| 21 |
-
Paraphrases the provided text.
|
| 22 |
-
|
| 23 |
-
Args:
|
| 24 |
-
payload (ParaphraseInput): The request body containing the text to be paraphrased.
|
| 25 |
-
|
| 26 |
-
Returns:
|
| 27 |
-
dict: A dictionary containing the paraphrased text.
|
| 28 |
-
"""
|
| 29 |
-
text = payload.text
|
| 30 |
-
|
| 31 |
-
try:
|
| 32 |
-
paraphrased_text = models.run_flan_prompt(prompts.paraphrase_prompt(text))
|
| 33 |
-
return {"result": paraphrased_text}
|
| 34 |
-
except Exception as e:
|
| 35 |
-
logger.error(f"Error in paraphrase: {e}", exc_info=True)
|
| 36 |
-
raise HTTPException(
|
| 37 |
-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 38 |
-
detail=f"An error occurred during paraphrasing: {e}"
|
| 39 |
-
)
|
|
|
|
| 1 |
+
from fastapi import APIRouter, Depends
|
| 2 |
+
from app.schemas.base import TextOnlyRequest
|
| 3 |
+
from app.services.paraphrase import Paraphraser
|
| 4 |
from app.core.security import verify_api_key
|
|
|
|
| 5 |
|
| 6 |
+
router = APIRouter(prefix="/paraphrase", tags=["Paraphrase"])
|
| 7 |
+
paraphraser = Paraphraser()
|
| 8 |
|
| 9 |
+
@router.post("/", dependencies=[Depends(verify_api_key)])
|
| 10 |
+
def paraphrase_text(payload: TextOnlyRequest):
|
| 11 |
+
result = paraphraser.paraphrase(payload.text)
|
| 12 |
+
return {"result": result}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/routers/punctuation.py
DELETED
|
@@ -1,67 +0,0 @@
|
|
| 1 |
-
from fastapi import APIRouter, Depends, HTTPException, status # Import HTTPException and status
|
| 2 |
-
from pydantic import BaseModel
|
| 3 |
-
from app.core.security import verify_api_key
|
| 4 |
-
import language_tool_python
|
| 5 |
-
import logging # Import logging
|
| 6 |
-
|
| 7 |
-
logger = logging.getLogger(__name__)
|
| 8 |
-
|
| 9 |
-
router = APIRouter()
|
| 10 |
-
|
| 11 |
-
# Initialize LanguageTool. This will be the same instance as used for punctuation.
|
| 12 |
-
# Ensure Java is installed in your environment.
|
| 13 |
-
try:
|
| 14 |
-
tool = language_tool_python.LanguageTool('en-US')
|
| 15 |
-
except Exception as e:
|
| 16 |
-
logger.error(f"Failed to initialize LanguageTool: {e}", exc_info=True)
|
| 17 |
-
# If LanguageTool cannot be initialized, raise an error or handle gracefully
|
| 18 |
-
# For an MVP, we might let the app start but fail on requests that use it.
|
| 19 |
-
# A more robust solution might mark the endpoint as unavailable.
|
| 20 |
-
tool = None # Set to None if initialization fails
|
| 21 |
-
|
| 22 |
-
class PunctuationInput(BaseModel):
|
| 23 |
-
"""
|
| 24 |
-
Pydantic BaseModel for validating the input request body for the /punctuation_check endpoint.
|
| 25 |
-
It expects a single field: 'text' (string).
|
| 26 |
-
"""
|
| 27 |
-
text: str
|
| 28 |
-
|
| 29 |
-
@router.post("/punctuation_check", dependencies=[Depends(verify_api_key)])
|
| 30 |
-
def punctuation_check(payload: PunctuationInput):
|
| 31 |
-
"""
|
| 32 |
-
Checks the provided text for punctuation errors.
|
| 33 |
-
|
| 34 |
-
Args:
|
| 35 |
-
payload (PunctuationInput): The request body containing the text to be analyzed.
|
| 36 |
-
|
| 37 |
-
Returns:
|
| 38 |
-
dict: A dictionary containing a list of punctuation issues.
|
| 39 |
-
"""
|
| 40 |
-
if tool is None:
|
| 41 |
-
raise HTTPException(
|
| 42 |
-
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
| 43 |
-
detail="Punctuation check service is not available (LanguageTool failed to initialize)."
|
| 44 |
-
)
|
| 45 |
-
|
| 46 |
-
text = payload.text
|
| 47 |
-
|
| 48 |
-
try:
|
| 49 |
-
matches = tool.check(text)
|
| 50 |
-
|
| 51 |
-
punctuation_issues = []
|
| 52 |
-
for m in matches:
|
| 53 |
-
if 'PUNCTUATION' in m.ruleId.upper():
|
| 54 |
-
punctuation_issues.append(m.message)
|
| 55 |
-
|
| 56 |
-
return {
|
| 57 |
-
"punctuation": {
|
| 58 |
-
"issues": punctuation_issues,
|
| 59 |
-
"suggestions": [] # Suggestions might be handled by overall grammar correction
|
| 60 |
-
}
|
| 61 |
-
}
|
| 62 |
-
except Exception as e:
|
| 63 |
-
logger.error(f"Error in punctuation_check: {e}", exc_info=True)
|
| 64 |
-
raise HTTPException(
|
| 65 |
-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 66 |
-
detail=f"An error occurred during punctuation checking: {e}"
|
| 67 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/routers/readability.py
CHANGED
|
@@ -1,55 +1,33 @@
|
|
| 1 |
-
from fastapi import APIRouter, Depends, HTTPException, status
|
| 2 |
-
from
|
| 3 |
from app.core.security import verify_api_key
|
| 4 |
-
|
| 5 |
-
import
|
|
|
|
|
|
|
| 6 |
|
|
|
|
| 7 |
logger = logging.getLogger(__name__)
|
| 8 |
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
It expects a single field: 'text' (string).
|
| 15 |
-
"""
|
| 16 |
-
text: str
|
| 17 |
-
|
| 18 |
-
@router.post("/readability_score", dependencies=[Depends(verify_api_key)])
|
| 19 |
-
def readability_score(payload: ReadabilityInput):
|
| 20 |
-
"""
|
| 21 |
-
Calculates various readability scores for the provided text.
|
| 22 |
-
|
| 23 |
-
Args:
|
| 24 |
-
payload (ReadabilityInput): The request body containing the text to be analyzed.
|
| 25 |
-
|
| 26 |
-
Returns:
|
| 27 |
-
dict: A dictionary containing various readability scores.
|
| 28 |
-
"""
|
| 29 |
-
text = payload.text
|
| 30 |
-
|
| 31 |
try:
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
flesch_kincaid_grade = textstat.flesch_kincaid_grade(text)
|
| 35 |
-
gunning_fog = textstat.gunning_fog(text)
|
| 36 |
-
smog_index = textstat.smog_index(text)
|
| 37 |
-
coleman_liau_index = textstat.coleman_liau_index(text)
|
| 38 |
-
automated_readability_index = textstat.automated_readability_index(text)
|
| 39 |
-
|
| 40 |
-
return {
|
| 41 |
-
"readability_scores": {
|
| 42 |
-
"flesch_reading_ease": flesch_reading_ease,
|
| 43 |
-
"flesch_kincaid_grade": flesch_kincaid_grade,
|
| 44 |
-
"gunning_fog_index": gunning_fog,
|
| 45 |
-
"smog_index": smog_index,
|
| 46 |
-
"coleman_liau_index": coleman_liau_index,
|
| 47 |
-
"automated_readability_index": automated_readability_index
|
| 48 |
-
}
|
| 49 |
-
}
|
| 50 |
except Exception as e:
|
| 51 |
-
logger.error(f"
|
| 52 |
raise HTTPException(
|
| 53 |
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 54 |
-
detail=
|
| 55 |
-
)
|
|
|
|
| 1 |
+
from fastapi import APIRouter, Depends, HTTPException, status
|
| 2 |
+
from app.schemas.base import TextOnlyRequest
|
| 3 |
from app.core.security import verify_api_key
|
| 4 |
+
from app.utils.shared import executor
|
| 5 |
+
import asyncio
|
| 6 |
+
import logging
|
| 7 |
+
import textstat
|
| 8 |
|
| 9 |
+
router = APIRouter(prefix="/readability", tags=["Readability"])
|
| 10 |
logger = logging.getLogger(__name__)
|
| 11 |
|
| 12 |
+
def compute_readability(text: str) -> dict:
|
| 13 |
+
return {
|
| 14 |
+
"flesch_reading_ease": textstat.flesch_reading_ease(text),
|
| 15 |
+
"flesch_kincaid_grade": textstat.flesch_kincaid_grade(text),
|
| 16 |
+
"gunning_fog_index": textstat.gunning_fog(text),
|
| 17 |
+
"smog_index": textstat.smog_index(text),
|
| 18 |
+
"coleman_liau_index": textstat.coleman_liau_index(text),
|
| 19 |
+
"automated_readability_index": textstat.automated_readability_index(text),
|
| 20 |
+
}
|
| 21 |
|
| 22 |
+
@router.post("/", dependencies=[Depends(verify_api_key)])
|
| 23 |
+
async def readability_score(payload: TextOnlyRequest):
|
| 24 |
+
loop = asyncio.get_event_loop()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
try:
|
| 26 |
+
scores = await loop.run_in_executor(executor, compute_readability, payload.text.strip())
|
| 27 |
+
return {"readability_scores": scores}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
except Exception as e:
|
| 29 |
+
logger.error(f"Readability score error: {e}", exc_info=True)
|
| 30 |
raise HTTPException(
|
| 31 |
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 32 |
+
detail="An error occurred while computing readability scores."
|
| 33 |
+
)
|
app/routers/rewrite.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# routers/rewrite.py
|
| 2 |
+
|
| 3 |
+
from fastapi import APIRouter, Depends
|
| 4 |
+
from app.schemas.base import RewriteRequest
|
| 5 |
+
from app.services.gpt4_rewrite import GPT4Rewriter
|
| 6 |
+
from app.core.security import verify_api_key
|
| 7 |
+
|
| 8 |
+
router = APIRouter(prefix="/rewrite", tags=["Rewrite"])
|
| 9 |
+
rewriter = GPT4Rewriter()
|
| 10 |
+
|
| 11 |
+
@router.post("/", dependencies=[Depends(verify_api_key)])
|
| 12 |
+
def rewrite_with_instruction(payload: RewriteRequest):
|
| 13 |
+
result = rewriter.rewrite(
|
| 14 |
+
text=payload.text,
|
| 15 |
+
instruction=payload.instruction,
|
| 16 |
+
user_api_key=payload.user_api_key
|
| 17 |
+
)
|
| 18 |
+
return {"result": result}
|
app/routers/sentence_correctness.py
DELETED
|
@@ -1,62 +0,0 @@
|
|
| 1 |
-
from fastapi import APIRouter, Depends, HTTPException, status # Import HTTPException and status
|
| 2 |
-
from pydantic import BaseModel
|
| 3 |
-
from app.core.security import verify_api_key
|
| 4 |
-
import language_tool_python
|
| 5 |
-
import logging # Import logging
|
| 6 |
-
|
| 7 |
-
logger = logging.getLogger(__name__)
|
| 8 |
-
|
| 9 |
-
router = APIRouter()
|
| 10 |
-
|
| 11 |
-
# Initialize LanguageTool. This will be the same instance as used for punctuation.
|
| 12 |
-
# Ensure Java is installed in your environment.
|
| 13 |
-
try:
|
| 14 |
-
tool = language_tool_python.LanguageTool('en-US')
|
| 15 |
-
except Exception as e:
|
| 16 |
-
logger.error(f"Failed to initialize LanguageTool for sentence correctness: {e}", exc_info=True)
|
| 17 |
-
tool = None
|
| 18 |
-
|
| 19 |
-
class SentenceCorrectnessInput(BaseModel):
|
| 20 |
-
"""
|
| 21 |
-
Pydantic BaseModel for validating the input request body for the /sentence_correctness endpoint.
|
| 22 |
-
It expects a single field: 'text' (string).
|
| 23 |
-
"""
|
| 24 |
-
text: str
|
| 25 |
-
|
| 26 |
-
@router.post("/sentence_correctness", dependencies=[Depends(verify_api_key)])
|
| 27 |
-
def sentence_correctness_check(payload: SentenceCorrectnessInput):
|
| 28 |
-
"""
|
| 29 |
-
Provides feedback on sentence-level correctness (e.g., fragments, subject-verb agreement).
|
| 30 |
-
|
| 31 |
-
Args:
|
| 32 |
-
payload (SentenceCorrectnessInput): The request body containing the text to be analyzed.
|
| 33 |
-
|
| 34 |
-
Returns:
|
| 35 |
-
dict: A dictionary containing a list of sentence correctness feedback.
|
| 36 |
-
"""
|
| 37 |
-
if tool is None:
|
| 38 |
-
raise HTTPException(
|
| 39 |
-
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
| 40 |
-
detail="Sentence correctness service is not available (LanguageTool failed to initialize)."
|
| 41 |
-
)
|
| 42 |
-
|
| 43 |
-
text = payload.text
|
| 44 |
-
|
| 45 |
-
try:
|
| 46 |
-
matches = tool.check(text)
|
| 47 |
-
|
| 48 |
-
sentence_correctness_feedback = []
|
| 49 |
-
for m in matches:
|
| 50 |
-
# Exclude punctuation issues, as they are handled in a separate endpoint
|
| 51 |
-
if 'PUNCTUATION' not in m.ruleId.upper():
|
| 52 |
-
sentence_correctness_feedback.append(m.message)
|
| 53 |
-
|
| 54 |
-
return {
|
| 55 |
-
"sentence_correctness": sentence_correctness_feedback
|
| 56 |
-
}
|
| 57 |
-
except Exception as e:
|
| 58 |
-
logger.error(f"Error in sentence_correctness_check: {e}", exc_info=True)
|
| 59 |
-
raise HTTPException(
|
| 60 |
-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 61 |
-
detail=f"An error occurred during sentence correctness checking: {e}"
|
| 62 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/routers/summarize.py
DELETED
|
@@ -1,39 +0,0 @@
|
|
| 1 |
-
from fastapi import APIRouter, Depends, HTTPException, status # Import HTTPException and status
|
| 2 |
-
from pydantic import BaseModel
|
| 3 |
-
from app import models, prompts
|
| 4 |
-
from app.core.security import verify_api_key
|
| 5 |
-
import logging # Import logging
|
| 6 |
-
|
| 7 |
-
logger = logging.getLogger(__name__)
|
| 8 |
-
|
| 9 |
-
router = APIRouter()
|
| 10 |
-
|
| 11 |
-
class SummarizeInput(BaseModel): # Renamed Input to SummarizeInput for clarity
|
| 12 |
-
"""
|
| 13 |
-
Pydantic BaseModel for validating the input request body for the /summarize endpoint.
|
| 14 |
-
It expects a single field: 'text' (string).
|
| 15 |
-
"""
|
| 16 |
-
text: str
|
| 17 |
-
|
| 18 |
-
@router.post("/summarize", dependencies=[Depends(verify_api_key)])
|
| 19 |
-
def summarize(payload: SummarizeInput): # Renamed input to payload for consistency
|
| 20 |
-
"""
|
| 21 |
-
Summarizes the provided text.
|
| 22 |
-
|
| 23 |
-
Args:
|
| 24 |
-
payload (SummarizeInput): The request body containing the text to be summarized.
|
| 25 |
-
|
| 26 |
-
Returns:
|
| 27 |
-
dict: A dictionary containing the summarized text.
|
| 28 |
-
"""
|
| 29 |
-
text = payload.text
|
| 30 |
-
|
| 31 |
-
try:
|
| 32 |
-
summarized_text = models.run_flan_prompt(prompts.summarize_prompt(text))
|
| 33 |
-
return {"result": summarized_text}
|
| 34 |
-
except Exception as e:
|
| 35 |
-
logger.error(f"Error in summarize: {e}", exc_info=True)
|
| 36 |
-
raise HTTPException(
|
| 37 |
-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 38 |
-
detail=f"An error occurred during summarization: {e}"
|
| 39 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/routers/tone.py
CHANGED
|
@@ -1,56 +1,11 @@
|
|
| 1 |
-
from fastapi import APIRouter, Depends
|
| 2 |
-
from
|
| 3 |
-
from app import
|
| 4 |
from app.core.security import verify_api_key
|
| 5 |
-
import logging # Import logging
|
| 6 |
|
| 7 |
-
|
|
|
|
| 8 |
|
| 9 |
-
router =
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
"""
|
| 13 |
-
Pydantic BaseModel for validating the input request body for the /tone_analysis endpoint.
|
| 14 |
-
It expects a single field: 'text' (string).
|
| 15 |
-
"""
|
| 16 |
-
text: str
|
| 17 |
-
|
| 18 |
-
@router.post("/tone_analysis", dependencies=[Depends(verify_api_key)])
|
| 19 |
-
def tone_analysis(payload: ToneInput):
|
| 20 |
-
"""
|
| 21 |
-
Analyzes the tone of the provided text and suggests improvements.
|
| 22 |
-
|
| 23 |
-
Args:
|
| 24 |
-
payload (ToneInput): The request body containing the text to be analyzed.
|
| 25 |
-
|
| 26 |
-
Returns:
|
| 27 |
-
dict: A dictionary containing the detected tone and a suggestion.
|
| 28 |
-
"""
|
| 29 |
-
text = payload.text
|
| 30 |
-
|
| 31 |
-
try:
|
| 32 |
-
detected_tone = models.classify_tone(text)
|
| 33 |
-
|
| 34 |
-
tone_suggestion_text = ""
|
| 35 |
-
# Provide a simple tone suggestion based on the detected tone.
|
| 36 |
-
# This logic can be expanded for more sophisticated suggestions based on context or user goals.
|
| 37 |
-
if detected_tone in ["neutral", "joy", "sadness", "anger", "fear", "disgust", "surprise"]:
|
| 38 |
-
if detected_tone in ["neutral", "joy"]:
|
| 39 |
-
tone_suggestion_text = models.run_flan_prompt(prompts.tone_prompt(text, "formal"))
|
| 40 |
-
else: # For emotions like anger, sadness, fear, etc., suggest a more neutral/calm tone
|
| 41 |
-
tone_suggestion_text = models.run_flan_prompt(prompts.tone_prompt(text, "neutral and calm"))
|
| 42 |
-
else:
|
| 43 |
-
tone_suggestion_text = f"The detected tone '{detected_tone}' seems appropriate for general communication."
|
| 44 |
-
|
| 45 |
-
return {
|
| 46 |
-
"tone_analysis": {
|
| 47 |
-
"detected": detected_tone,
|
| 48 |
-
"suggestion": tone_suggestion_text
|
| 49 |
-
}
|
| 50 |
-
}
|
| 51 |
-
except Exception as e:
|
| 52 |
-
logger.error(f"Error in tone_analysis: {e}", exc_info=True)
|
| 53 |
-
raise HTTPException(
|
| 54 |
-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 55 |
-
detail=f"An error occurred during tone analysis: {e}"
|
| 56 |
-
)
|
|
|
|
| 1 |
+
from fastapi import APIRouter, Depends
|
| 2 |
+
from app.schemas.base import TextOnlyRequest
|
| 3 |
+
from app.services.tone_classification import ToneClassifier
|
| 4 |
from app.core.security import verify_api_key
|
|
|
|
| 5 |
|
| 6 |
+
router = APIRouter(prefix="/tone", tags=["Tone"])
|
| 7 |
+
classifier = ToneClassifier()
|
| 8 |
|
| 9 |
+
@router.post("/", dependencies=[Depends(verify_api_key)])
|
| 10 |
+
def classify_tone(payload: TextOnlyRequest):
|
| 11 |
+
return {"result": classifier.classify(payload.text)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/routers/translate.py
CHANGED
|
@@ -1,41 +1,15 @@
|
|
| 1 |
-
from fastapi import APIRouter, Depends
|
| 2 |
-
from
|
| 3 |
-
from app import
|
| 4 |
from app.core.security import verify_api_key
|
| 5 |
-
import logging # Import logging
|
| 6 |
|
| 7 |
-
|
|
|
|
| 8 |
|
| 9 |
-
router =
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
""
|
| 16 |
-
text: str
|
| 17 |
-
target_lang: str
|
| 18 |
-
|
| 19 |
-
@router.post("/translate", dependencies=[Depends(verify_api_key)])
|
| 20 |
-
def translate(payload: TranslateInput): # Renamed input to payload for consistency
|
| 21 |
-
"""
|
| 22 |
-
Translates the provided text to a target language.
|
| 23 |
-
|
| 24 |
-
Args:
|
| 25 |
-
payload (TranslateInput): The request body containing the text and target language.
|
| 26 |
-
|
| 27 |
-
Returns:
|
| 28 |
-
dict: A dictionary containing the translated text.
|
| 29 |
-
"""
|
| 30 |
-
text = payload.text
|
| 31 |
-
target_lang = payload.target_lang
|
| 32 |
-
|
| 33 |
-
try:
|
| 34 |
-
translated_text = models.run_translation(text, target_lang)
|
| 35 |
-
return {"result": translated_text}
|
| 36 |
-
except Exception as e:
|
| 37 |
-
logger.error(f"Error in translate: {e}", exc_info=True)
|
| 38 |
-
raise HTTPException(
|
| 39 |
-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 40 |
-
detail=f"An error occurred during translation: {e}"
|
| 41 |
-
)
|
|
|
|
| 1 |
+
from fastapi import APIRouter, Depends
|
| 2 |
+
from app.schemas.base import TranslateRequest
|
| 3 |
+
from app.services.translation import Translator
|
| 4 |
from app.core.security import verify_api_key
|
|
|
|
| 5 |
|
| 6 |
+
router = APIRouter(prefix="/translate", tags=["Translate"])
|
| 7 |
+
translator = Translator()
|
| 8 |
|
| 9 |
+
@router.post("/to", dependencies=[Depends(verify_api_key)])
|
| 10 |
+
def translate_text(payload: TranslateRequest):
|
| 11 |
+
result = translator.translate(
|
| 12 |
+
text=payload.text,
|
| 13 |
+
target_lang=payload.target_lang
|
| 14 |
+
)
|
| 15 |
+
return {"result": result}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/routers/vocabulary.py
DELETED
|
@@ -1,42 +0,0 @@
|
|
| 1 |
-
from fastapi import APIRouter, Depends, HTTPException, status # Import HTTPException and status
|
| 2 |
-
from pydantic import BaseModel
|
| 3 |
-
from app import models, prompts
|
| 4 |
-
from app.core.security import verify_api_key
|
| 5 |
-
import logging # Import logging
|
| 6 |
-
|
| 7 |
-
logger = logging.getLogger(__name__)
|
| 8 |
-
|
| 9 |
-
router = APIRouter()
|
| 10 |
-
|
| 11 |
-
class VocabularyInput(BaseModel):
|
| 12 |
-
"""
|
| 13 |
-
Pydantic BaseModel for validating the input request body for the /vocabulary_suggestions endpoint.
|
| 14 |
-
It expects a single field: 'text' (string).
|
| 15 |
-
"""
|
| 16 |
-
text: str
|
| 17 |
-
|
| 18 |
-
@router.post("/vocabulary_suggestions", dependencies=[Depends(verify_api_key)])
|
| 19 |
-
def vocabulary_suggestions(payload: VocabularyInput):
|
| 20 |
-
"""
|
| 21 |
-
Provides suggestions for vocabulary improvement (e.g., stronger synonyms).
|
| 22 |
-
|
| 23 |
-
Args:
|
| 24 |
-
payload (VocabularyInput): The request body containing the text to be analyzed.
|
| 25 |
-
|
| 26 |
-
Returns:
|
| 27 |
-
dict: A dictionary containing vocabulary suggestions.
|
| 28 |
-
"""
|
| 29 |
-
text = payload.text
|
| 30 |
-
|
| 31 |
-
try:
|
| 32 |
-
suggestions_raw = models.run_flan_prompt(prompts.vocabulary_prompt(text))
|
| 33 |
-
|
| 34 |
-
return {
|
| 35 |
-
"vocabulary_suggestions": suggestions_raw
|
| 36 |
-
}
|
| 37 |
-
except Exception as e:
|
| 38 |
-
logger.error(f"Error in vocabulary_suggestions: {e}", exc_info=True)
|
| 39 |
-
raise HTTPException(
|
| 40 |
-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 41 |
-
detail=f"An error occurred during vocabulary suggestion: {e}"
|
| 42 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/routers/voice.py
CHANGED
|
@@ -1,72 +1,11 @@
|
|
| 1 |
-
from fastapi import APIRouter, Depends
|
| 2 |
-
from
|
| 3 |
-
from app import
|
| 4 |
from app.core.security import verify_api_key
|
| 5 |
-
import spacy
|
| 6 |
-
import logging # Import logging
|
| 7 |
|
| 8 |
-
|
|
|
|
| 9 |
|
| 10 |
-
router =
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
try:
|
| 14 |
-
nlp = spacy.load("en_core_web_sm")
|
| 15 |
-
except OSError as e:
|
| 16 |
-
logger.error(f"SpaCy model 'en_core_web_sm' not found. Please run: python -m spacy download en_core_web_sm. Error: {e}", exc_info=True)
|
| 17 |
-
nlp = None # Set to None if initialization fails
|
| 18 |
-
# Re-raising here to prevent server startup if critical dependency is missing
|
| 19 |
-
raise RuntimeError("SpaCy model 'en_core_web_sm' not loaded. Please install it.")
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
class VoiceInput(BaseModel):
|
| 23 |
-
"""
|
| 24 |
-
Pydantic BaseModel for validating the input request body for the /voice_analysis endpoint.
|
| 25 |
-
It expects a single field: 'text' (string).
|
| 26 |
-
"""
|
| 27 |
-
text: str
|
| 28 |
-
|
| 29 |
-
@router.post("/voice_analysis", dependencies=[Depends(verify_api_key)])
|
| 30 |
-
def voice_analysis(payload: VoiceInput):
|
| 31 |
-
"""
|
| 32 |
-
Detects active/passive voice and suggests improvements.
|
| 33 |
-
|
| 34 |
-
Args:
|
| 35 |
-
payload (VoiceInput): The request body containing the text to be analyzed.
|
| 36 |
-
|
| 37 |
-
Returns:
|
| 38 |
-
dict: A dictionary containing the detected voice and a suggestion.
|
| 39 |
-
"""
|
| 40 |
-
if nlp is None:
|
| 41 |
-
raise HTTPException(
|
| 42 |
-
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
| 43 |
-
detail="Voice analysis service is not available (SpaCy model failed to load)."
|
| 44 |
-
)
|
| 45 |
-
|
| 46 |
-
text = payload.text
|
| 47 |
-
|
| 48 |
-
try:
|
| 49 |
-
doc = nlp(text)
|
| 50 |
-
|
| 51 |
-
voice_detected = "active"
|
| 52 |
-
voice_suggestion = "None \u2014 active voice is fine here."
|
| 53 |
-
|
| 54 |
-
for token in doc:
|
| 55 |
-
if token.dep_ == "auxpass":
|
| 56 |
-
voice_detected = "passive"
|
| 57 |
-
better_voice_prompt = prompts.active_voice_prompt(text)
|
| 58 |
-
voice_suggestion = models.run_flan_prompt(better_voice_prompt)
|
| 59 |
-
break
|
| 60 |
-
|
| 61 |
-
return {
|
| 62 |
-
"voice": {
|
| 63 |
-
"detected": voice_detected,
|
| 64 |
-
"suggestion": voice_suggestion
|
| 65 |
-
}
|
| 66 |
-
}
|
| 67 |
-
except Exception as e:
|
| 68 |
-
logger.error(f"Error in voice_analysis: {e}", exc_info=True)
|
| 69 |
-
raise HTTPException(
|
| 70 |
-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 71 |
-
detail=f"An error occurred during voice analysis: {e}"
|
| 72 |
-
)
|
|
|
|
| 1 |
+
from fastapi import APIRouter, Depends
|
| 2 |
+
from app.schemas.base import TextOnlyRequest
|
| 3 |
+
from app.services.voice_detection import VoiceDetector
|
| 4 |
from app.core.security import verify_api_key
|
|
|
|
|
|
|
| 5 |
|
| 6 |
+
router = APIRouter(prefix="/voice", tags=["Voice"])
|
| 7 |
+
detector = VoiceDetector()
|
| 8 |
|
| 9 |
+
@router.post("/", dependencies=[Depends(verify_api_key)])
|
| 10 |
+
def detect_voice(payload: TextOnlyRequest):
|
| 11 |
+
return {"result": detector.classify(payload.text)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/schemas/base.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
|
| 3 |
+
class TextOnlyRequest(BaseModel):
|
| 4 |
+
text: str = Field(..., example="Your input text here")
|
| 5 |
+
|
| 6 |
+
class RewriteRequest(BaseModel):
|
| 7 |
+
text: str = Field(..., example="Your input text here")
|
| 8 |
+
instruction: str = Field(..., example="Rewrite this more concisely")
|
| 9 |
+
user_api_key: str = Field(..., example="sk-...")
|
| 10 |
+
|
| 11 |
+
class TranslateRequest(BaseModel):
|
| 12 |
+
text: str = Field(..., example="Translate this")
|
| 13 |
+
target_lang: str = Field(..., example="fr")
|
app/services/__init__.py
ADDED
|
File without changes
|
app/services/base.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
from threading import Lock
|
| 3 |
+
import logging
|
| 4 |
+
import time
|
| 5 |
+
logger = logging.getLogger(__name__)
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 9 |
+
logging.getLogger(__name__).info(f"Using device: {DEVICE}")
|
| 10 |
+
|
| 11 |
+
_models = {}
|
| 12 |
+
_models_lock = Lock()
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def get_cached_model(model_name: str, load_fn):
|
| 16 |
+
with _models_lock:
|
| 17 |
+
if model_name not in _models:
|
| 18 |
+
logging.info(f"Loading model: {model_name}")
|
| 19 |
+
_models[model_name] = load_fn()
|
| 20 |
+
return _models[model_name]
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def load_with_timer(name, fn):
|
| 24 |
+
# TODO: Add timing later if needed
|
| 25 |
+
return fn()
|
| 26 |
+
|
| 27 |
+
def timed_model_load(label: str, load_fn):
|
| 28 |
+
start = time.time()
|
| 29 |
+
model = load_fn()
|
| 30 |
+
logger.info(f"{label} loaded in {time.time() - start:.2f}s")
|
| 31 |
+
return model
|
| 32 |
+
|
| 33 |
+
# Lazy spaCy loading
|
| 34 |
+
_nlp = None
|
| 35 |
+
|
| 36 |
+
def get_spacy():
|
| 37 |
+
global _nlp
|
| 38 |
+
if _nlp is None:
|
| 39 |
+
import spacy
|
| 40 |
+
_nlp = spacy.load("en_core_web_sm")
|
| 41 |
+
return _nlp
|
| 42 |
+
|
app/services/conciseness_suggestion.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import logging
|
| 2 |
+
from app.services.gpt4_rewrite import GPT4Rewriter
|
| 3 |
+
from app.core.prompts import concise_prompt
|
| 4 |
+
|
| 5 |
+
logger = logging.getLogger(__name__)
|
| 6 |
+
gpt4_rewriter = GPT4Rewriter()
|
| 7 |
+
|
| 8 |
+
class ConcisenessSuggester:
|
| 9 |
+
def suggest(self, text: str, user_api_key: str) -> str:
|
| 10 |
+
text = text.strip()
|
| 11 |
+
if not text:
|
| 12 |
+
logger.warning("Conciseness suggestion requested for empty input.")
|
| 13 |
+
return "Input text is empty."
|
| 14 |
+
|
| 15 |
+
if not user_api_key:
|
| 16 |
+
logger.error("Conciseness suggestion failed: Missing user_api_key.")
|
| 17 |
+
return "Missing OpenAI API key."
|
| 18 |
+
|
| 19 |
+
instruction = concise_prompt(text)
|
| 20 |
+
concise_text = gpt4_rewriter.rewrite(text, user_api_key, instruction)
|
| 21 |
+
|
| 22 |
+
if concise_text.startswith("An OpenAI API error occurred:") or \
|
| 23 |
+
concise_text.startswith("An unexpected error occurred:") or \
|
| 24 |
+
concise_text.startswith("Missing OpenAI API key.") or \
|
| 25 |
+
concise_text.startswith("Input text is empty."):
|
| 26 |
+
logger.error(f"GPT-4 conciseness suggestion failed for text: '{text[:50]}...' - {concise_text}")
|
| 27 |
+
return concise_text
|
| 28 |
+
|
| 29 |
+
logger.info(f"Conciseness suggestion completed for text length: {len(text)}")
|
| 30 |
+
return concise_text
|
app/services/gpt4_rewrite.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import openai
|
| 2 |
+
import logging
|
| 3 |
+
from tenacity import retry, stop_after_attempt, wait_exponential
|
| 4 |
+
from app.core.config import settings
|
| 5 |
+
|
| 6 |
+
logger = logging.getLogger(__name__)
|
| 7 |
+
|
| 8 |
+
class GPT4Rewriter:
|
| 9 |
+
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
|
| 10 |
+
def rewrite(self, text: str, user_api_key: str, instruction: str) -> str:
|
| 11 |
+
if not user_api_key:
|
| 12 |
+
logger.error("GPT-4 rewrite requested without an OpenAI API key.")
|
| 13 |
+
return "Missing OpenAI API key."
|
| 14 |
+
|
| 15 |
+
text = text.strip()
|
| 16 |
+
instruction = instruction.strip()
|
| 17 |
+
|
| 18 |
+
if not text:
|
| 19 |
+
logger.warning("GPT-4 rewrite requested for empty input.")
|
| 20 |
+
return "Input text is empty."
|
| 21 |
+
if not instruction:
|
| 22 |
+
logger.error("GPT-4 rewrite requested without a specific instruction.")
|
| 23 |
+
return "Missing rewrite instruction. Please provide a clear instruction for the rewrite."
|
| 24 |
+
|
| 25 |
+
messages = [
|
| 26 |
+
{"role": "system", "content": instruction},
|
| 27 |
+
{"role": "user", "content": text},
|
| 28 |
+
]
|
| 29 |
+
|
| 30 |
+
try:
|
| 31 |
+
client = openai.OpenAI(api_key=user_api_key)
|
| 32 |
+
response = client.chat.completions.create(
|
| 33 |
+
model=settings.openai_model,
|
| 34 |
+
messages=messages,
|
| 35 |
+
temperature=settings.openai_temperature,
|
| 36 |
+
max_tokens=settings.openai_max_tokens
|
| 37 |
+
)
|
| 38 |
+
return response.choices[0].message.content.strip()
|
| 39 |
+
except openai.APIError as e:
|
| 40 |
+
logger.error(f"OpenAI API error during GPT-4 rewrite: {e}")
|
| 41 |
+
return f"An OpenAI API error occurred: {e}"
|
| 42 |
+
except Exception as e:
|
| 43 |
+
logger.error(f"Unexpected error during GPT-4 rewrite: {e}")
|
| 44 |
+
return "An unexpected error occurred during GPT-4 rewrite."
|
app/services/grammar.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
|
| 2 |
+
import torch
|
| 3 |
+
from .base import get_cached_model, DEVICE, load_with_timer
|
| 4 |
+
import logging
|
| 5 |
+
|
| 6 |
+
class GrammarCorrector:
|
| 7 |
+
def __init__(self):
|
| 8 |
+
self.tokenizer, self.model = self._load_model()
|
| 9 |
+
|
| 10 |
+
def _load_model(self):
|
| 11 |
+
def load_fn():
|
| 12 |
+
tokenizer = load_with_timer("grammar_tokenizer", lambda: AutoTokenizer.from_pretrained("visheratin/t5-efficient-mini-grammar-correction"))
|
| 13 |
+
model = load_with_timer("grammar_model", lambda: AutoModelForSeq2SeqLM.from_pretrained("visheratin/t5-efficient-mini-grammar-correction"))
|
| 14 |
+
model = model.to(DEVICE).eval()
|
| 15 |
+
return tokenizer, model
|
| 16 |
+
|
| 17 |
+
return get_cached_model("grammar", load_fn)
|
| 18 |
+
|
| 19 |
+
def correct(self, text: str) -> str:
|
| 20 |
+
text = text.strip()
|
| 21 |
+
if not text:
|
| 22 |
+
logging.warning("Grammar correction requested for empty input.")
|
| 23 |
+
return "Input text is empty."
|
| 24 |
+
|
| 25 |
+
try:
|
| 26 |
+
with torch.no_grad():
|
| 27 |
+
inputs = self.tokenizer([text], return_tensors="pt", truncation=True, padding=True).to(DEVICE)
|
| 28 |
+
outputs = self.model.generate(**inputs, max_length=256, num_beams=4, early_stopping=True)
|
| 29 |
+
return self.tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 30 |
+
except Exception as e:
|
| 31 |
+
logging.error(f"Error during grammar correction: {e}")
|
| 32 |
+
return "An error occurred during grammar correction."
|
app/services/inclusive_language.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import yaml
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from spacy.matcher import PhraseMatcher
|
| 4 |
+
from typing import List, Dict
|
| 5 |
+
from .base import get_spacy
|
| 6 |
+
from app.core.config import settings
|
| 7 |
+
import logging
|
| 8 |
+
|
| 9 |
+
class InclusiveLanguageChecker:
|
| 10 |
+
def __init__(self, rules_directory=settings.inclusive_rules_dir):
|
| 11 |
+
self.matcher = PhraseMatcher(get_spacy().vocab, attr="LOWER")
|
| 12 |
+
self.rules = self._load_inclusive_rules(rules_directory)
|
| 13 |
+
self._init_matcher()
|
| 14 |
+
|
| 15 |
+
def _load_inclusive_rules(self, directory: str) -> Dict[str, Dict]:
|
| 16 |
+
rules = {}
|
| 17 |
+
for path in Path(directory).glob("*.yml"):
|
| 18 |
+
try:
|
| 19 |
+
with open(path, encoding="utf-8") as f:
|
| 20 |
+
rule_list = yaml.safe_load(f)
|
| 21 |
+
if not isinstance(rule_list, list):
|
| 22 |
+
logging.warning(f"Skipping malformed rule file: {path}")
|
| 23 |
+
continue
|
| 24 |
+
for rule in rule_list:
|
| 25 |
+
note = rule.get("note", "")
|
| 26 |
+
source = rule.get("source", "")
|
| 27 |
+
considerate = rule.get("considerate", [])
|
| 28 |
+
inconsiderate = rule.get("inconsiderate", [])
|
| 29 |
+
|
| 30 |
+
if isinstance(considerate, str):
|
| 31 |
+
considerate = [considerate]
|
| 32 |
+
if isinstance(inconsiderate, str):
|
| 33 |
+
inconsiderate = [inconsiderate]
|
| 34 |
+
|
| 35 |
+
for phrase in inconsiderate:
|
| 36 |
+
key = phrase.lower()
|
| 37 |
+
rules[key] = {
|
| 38 |
+
"note": note,
|
| 39 |
+
"considerate": considerate,
|
| 40 |
+
"source": source,
|
| 41 |
+
"type": rule.get("type", "basic")
|
| 42 |
+
}
|
| 43 |
+
except Exception as e:
|
| 44 |
+
logging.error(f"Error loading inclusive language rule from {path}: {e}")
|
| 45 |
+
return rules
|
| 46 |
+
|
| 47 |
+
def _init_matcher(self):
|
| 48 |
+
for phrase in self.rules:
|
| 49 |
+
self.matcher.add(phrase, [get_spacy().make_doc(phrase)])
|
| 50 |
+
logging.info(f"Loaded {len(self.rules)} inclusive language rules.")
|
| 51 |
+
|
| 52 |
+
def check(self, text: str) -> List[Dict]:
|
| 53 |
+
text = text.strip()
|
| 54 |
+
if not text:
|
| 55 |
+
logging.warning("Inclusive language check requested for empty input.")
|
| 56 |
+
return []
|
| 57 |
+
|
| 58 |
+
nlp = get_spacy()
|
| 59 |
+
doc = nlp(text)
|
| 60 |
+
matches = self.matcher(doc)
|
| 61 |
+
results = []
|
| 62 |
+
matched_spans = set()
|
| 63 |
+
|
| 64 |
+
# 1. PhraseMatcher (exact) matches
|
| 65 |
+
for match_id, start, end in matches:
|
| 66 |
+
phrase_str = nlp.vocab.strings[match_id]
|
| 67 |
+
matched_spans.add((start, end))
|
| 68 |
+
rule = self.rules.get(phrase_str.lower())
|
| 69 |
+
if rule:
|
| 70 |
+
results.append({
|
| 71 |
+
"term": doc[start:end].text,
|
| 72 |
+
"type": rule["type"],
|
| 73 |
+
"note": rule["note"],
|
| 74 |
+
"suggestions": rule["considerate"],
|
| 75 |
+
"context": doc[start:end].sent.text,
|
| 76 |
+
"start": doc[start].idx,
|
| 77 |
+
"end": doc[end - 1].idx + len(doc[end - 1]),
|
| 78 |
+
"source": rule.get("source", "")
|
| 79 |
+
})
|
| 80 |
+
|
| 81 |
+
# 2. Lemma-based fallback (for plural/inflected forms)
|
| 82 |
+
for token in doc:
|
| 83 |
+
lemma = token.lemma_.lower()
|
| 84 |
+
span_key = (token.i, token.i + 1)
|
| 85 |
+
if lemma in self.rules and span_key not in matched_spans:
|
| 86 |
+
rule = self.rules[lemma]
|
| 87 |
+
results.append({
|
| 88 |
+
"term": token.text,
|
| 89 |
+
"type": rule["type"],
|
| 90 |
+
"note": rule["note"],
|
| 91 |
+
"suggestions": rule["considerate"],
|
| 92 |
+
"context": token.sent.text,
|
| 93 |
+
"start": token.idx,
|
| 94 |
+
"end": token.idx + len(token),
|
| 95 |
+
"source": rule.get("source", "")
|
| 96 |
+
})
|
| 97 |
+
|
| 98 |
+
return results
|
app/services/paraphrase.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
|
| 2 |
+
import torch
|
| 3 |
+
from .base import get_cached_model, DEVICE, timed_model_load
|
| 4 |
+
import logging
|
| 5 |
+
|
| 6 |
+
class Paraphraser:
|
| 7 |
+
def __init__(self):
|
| 8 |
+
self.tokenizer, self.model = self._load_model()
|
| 9 |
+
|
| 10 |
+
def _load_model(self):
|
| 11 |
+
def load_fn():
|
| 12 |
+
tokenizer = timed_model_load("paraphrase_tokenizer", lambda: AutoTokenizer.from_pretrained("humarin/chatgpt_paraphraser_on_T5_base"))
|
| 13 |
+
model = timed_model_load("paraphrase_model", lambda: AutoModelForSeq2SeqLM.from_pretrained("humarin/chatgpt_paraphraser_on_T5_base"))
|
| 14 |
+
model = model.to(DEVICE).eval()
|
| 15 |
+
return tokenizer, model
|
| 16 |
+
return get_cached_model("paraphrase", load_fn)
|
| 17 |
+
|
| 18 |
+
def paraphrase(self, text: str) -> str:
|
| 19 |
+
text = text.strip()
|
| 20 |
+
if not text:
|
| 21 |
+
logging.warning("Paraphrasing requested for empty input.")
|
| 22 |
+
return "Input text is empty."
|
| 23 |
+
|
| 24 |
+
prompt = f"paraphrase: {text} </s>"
|
| 25 |
+
try:
|
| 26 |
+
with torch.no_grad():
|
| 27 |
+
inputs = self.tokenizer([prompt], return_tensors="pt", padding=True, truncation=True).to(DEVICE)
|
| 28 |
+
outputs = self.model.generate(
|
| 29 |
+
**inputs,
|
| 30 |
+
max_length=256,
|
| 31 |
+
num_beams=5,
|
| 32 |
+
num_return_sequences=1,
|
| 33 |
+
early_stopping=True
|
| 34 |
+
)
|
| 35 |
+
return self.tokenizer.decode(outputs[0], skip_special_tokens=True, clean_up_tokenization_spaces=True)
|
| 36 |
+
except Exception as e:
|
| 37 |
+
logging.error(f"Error during paraphrasing: {e}")
|
| 38 |
+
return f"An error occurred during paraphrasing: {e}"
|
| 39 |
+
|
app/services/tone_classification.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import pipeline
|
| 2 |
+
import torch
|
| 3 |
+
from .base import get_cached_model, DEVICE
|
| 4 |
+
import logging
|
| 5 |
+
|
| 6 |
+
class ToneClassifier:
|
| 7 |
+
def __init__(self):
|
| 8 |
+
self.classifier = self._load_model()
|
| 9 |
+
|
| 10 |
+
def _load_model(self):
|
| 11 |
+
def load_fn():
|
| 12 |
+
return pipeline(
|
| 13 |
+
"sentiment-analysis",
|
| 14 |
+
model="j-hartmann/emotion-english-distilroberta-base",
|
| 15 |
+
top_k=1,
|
| 16 |
+
device=0 if torch.cuda.is_available() else -1
|
| 17 |
+
)
|
| 18 |
+
return get_cached_model("tone", load_fn)
|
| 19 |
+
|
| 20 |
+
def classify(self, text: str) -> str:
|
| 21 |
+
text = text.strip()
|
| 22 |
+
if not text:
|
| 23 |
+
logging.warning("Tone classification requested for empty input.")
|
| 24 |
+
return "Input text is empty."
|
| 25 |
+
|
| 26 |
+
try:
|
| 27 |
+
result = self.classifier(text)
|
| 28 |
+
if isinstance(result, list):
|
| 29 |
+
if isinstance(result[0], list):
|
| 30 |
+
result = result[0]
|
| 31 |
+
if result:
|
| 32 |
+
return result[0]['label']
|
| 33 |
+
return "Unknown"
|
| 34 |
+
except Exception as e:
|
| 35 |
+
logging.error(f"Error during tone classification: {e}")
|
| 36 |
+
return "An error occurred during tone classification."
|
app/services/translation.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
|
| 2 |
+
import torch
|
| 3 |
+
import logging
|
| 4 |
+
from .base import get_cached_model, DEVICE, timed_model_load
|
| 5 |
+
from app.core.config import settings
|
| 6 |
+
|
| 7 |
+
class Translator:
|
| 8 |
+
def __init__(self):
|
| 9 |
+
self.tokenizer, self.model = self._load_model()
|
| 10 |
+
|
| 11 |
+
def _load_model(self):
|
| 12 |
+
def load_fn():
|
| 13 |
+
tokenizer = timed_model_load("translate_tokenizer", lambda: AutoTokenizer.from_pretrained("Helsinki-NLP/opus-mt-en-ROMANCE"))
|
| 14 |
+
model = timed_model_load("translate_model", lambda: AutoModelForSeq2SeqLM.from_pretrained("Helsinki-NLP/opus-mt-en-ROMANCE"))
|
| 15 |
+
model = model.to(DEVICE).eval()
|
| 16 |
+
return tokenizer, model
|
| 17 |
+
return get_cached_model("translate", load_fn)
|
| 18 |
+
|
| 19 |
+
def translate(self, text: str, target_lang: str) -> str:
|
| 20 |
+
text = text.strip()
|
| 21 |
+
target_lang = target_lang.strip()
|
| 22 |
+
|
| 23 |
+
if not text:
|
| 24 |
+
logging.warning("Translation requested for empty input.")
|
| 25 |
+
return "Input text is empty."
|
| 26 |
+
if not target_lang:
|
| 27 |
+
logging.warning("Translation requested without a target language.")
|
| 28 |
+
return "Target language is empty."
|
| 29 |
+
if target_lang not in settings.supported_translation_languages:
|
| 30 |
+
return f"Unsupported target language: {target_lang}"
|
| 31 |
+
|
| 32 |
+
prompt = f">>{target_lang}<< {text}"
|
| 33 |
+
try:
|
| 34 |
+
with torch.no_grad():
|
| 35 |
+
inputs = self.tokenizer([prompt], return_tensors="pt", truncation=True, padding=True).to(DEVICE)
|
| 36 |
+
outputs = self.model.generate(**inputs, max_length=256, num_beams=1, early_stopping=True)
|
| 37 |
+
return self.tokenizer.decode(outputs[0], skip_special_tokens=True, clean_up_tokenization_spaces=True)
|
| 38 |
+
except Exception as e:
|
| 39 |
+
logging.error(f"Error during translation: {e}")
|
| 40 |
+
return f"An error occurred during translation: {e}"
|
app/services/vocabulary_enhancement.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import logging
|
| 2 |
+
from app.services.gpt4_rewrite import GPT4Rewriter
|
| 3 |
+
from app.core.prompts import vocabulary_prompt
|
| 4 |
+
|
| 5 |
+
logger = logging.getLogger(__name__)
|
| 6 |
+
gpt4_rewriter = GPT4Rewriter()
|
| 7 |
+
|
| 8 |
+
class VocabularyEnhancer:
|
| 9 |
+
def enhance(self, text: str, user_api_key: str) -> str:
|
| 10 |
+
text = text.strip()
|
| 11 |
+
if not text:
|
| 12 |
+
logger.warning("Vocabulary enhancement requested for empty input.")
|
| 13 |
+
return "Input text is empty."
|
| 14 |
+
|
| 15 |
+
if not user_api_key:
|
| 16 |
+
logger.error("Vocabulary enhancement failed: Missing user_api_key.")
|
| 17 |
+
return "Missing OpenAI API key."
|
| 18 |
+
|
| 19 |
+
instruction = vocabulary_prompt(text)
|
| 20 |
+
enhanced_text = gpt4_rewriter.rewrite(text, user_api_key, instruction)
|
| 21 |
+
|
| 22 |
+
if enhanced_text.startswith("An OpenAI API error occurred:") or \
|
| 23 |
+
enhanced_text.startswith("An unexpected error occurred:") or \
|
| 24 |
+
enhanced_text.startswith("Missing OpenAI API key.") or \
|
| 25 |
+
enhanced_text.startswith("Input text is empty."):
|
| 26 |
+
logger.error(f"GPT-4 vocabulary enhancement failed for text: '{text[:50]}...' - {enhanced_text}")
|
| 27 |
+
return enhanced_text
|
| 28 |
+
|
| 29 |
+
logger.info(f"Vocabulary enhancement completed for text length: {len(text)}")
|
| 30 |
+
return enhanced_text
|
app/services/voice_detection.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import logging
|
| 2 |
+
from .base import get_spacy
|
| 3 |
+
|
| 4 |
+
class VoiceDetector:
|
| 5 |
+
def __init__(self):
|
| 6 |
+
self.nlp = get_spacy()
|
| 7 |
+
|
| 8 |
+
def classify(self, text: str) -> str:
|
| 9 |
+
text = text.strip()
|
| 10 |
+
if not text:
|
| 11 |
+
logging.warning("Voice detection requested for empty input.")
|
| 12 |
+
return "Input text is empty."
|
| 13 |
+
|
| 14 |
+
try:
|
| 15 |
+
doc = self.nlp(text)
|
| 16 |
+
passive_sentences = 0
|
| 17 |
+
total_sentences = 0
|
| 18 |
+
|
| 19 |
+
for sent in doc.sents:
|
| 20 |
+
total_sentences += 1
|
| 21 |
+
for token in sent:
|
| 22 |
+
if token.dep_ == "nsubjpass":
|
| 23 |
+
passive_sentences += 1
|
| 24 |
+
break
|
| 25 |
+
|
| 26 |
+
if total_sentences == 0:
|
| 27 |
+
return "Unknown"
|
| 28 |
+
|
| 29 |
+
ratio = passive_sentences / total_sentences
|
| 30 |
+
return "Passive" if ratio > 0.5 else "Active"
|
| 31 |
+
except Exception as e:
|
| 32 |
+
logging.error(f"Error during voice detection: {e}")
|
| 33 |
+
return "An error occurred during voice detection."
|
app/test/test_rewrite.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
from fastapi.testclient import TestClient
|
| 3 |
+
from main import create_app
|
| 4 |
+
|
| 5 |
+
client = TestClient(create_app())
|
| 6 |
+
|
| 7 |
+
def test_rewrite_success():
|
| 8 |
+
payload = {
|
| 9 |
+
"text": "This is a very long and unnecessarily wordy sentence that could be simpler.",
|
| 10 |
+
"instruction": "Make this more concise"
|
| 11 |
+
}
|
| 12 |
+
headers = {"x-api-key": "your-secret-key"}
|
| 13 |
+
response = client.post("/rewrite/", json=payload, headers=headers)
|
| 14 |
+
assert response.status_code == 200
|
| 15 |
+
assert "result" in response.json()
|
app/test_main.py
DELETED
|
@@ -1,39 +0,0 @@
|
|
| 1 |
-
from fastapi.testclient import TestClient
|
| 2 |
-
from app.main import app
|
| 3 |
-
|
| 4 |
-
client = TestClient(app)
|
| 5 |
-
|
| 6 |
-
def test_grammar():
|
| 7 |
-
response = client.post("/rewrite", json={"text": "She go to school yesterday.", "mode": "grammar"})
|
| 8 |
-
assert response.status_code == 200
|
| 9 |
-
assert "result" in response.json()
|
| 10 |
-
|
| 11 |
-
def test_paraphrase():
|
| 12 |
-
response = client.post("/rewrite", json={"text": "I love programming.", "mode": "paraphrase"})
|
| 13 |
-
assert response.status_code == 200
|
| 14 |
-
assert "result" in response.json()
|
| 15 |
-
|
| 16 |
-
def test_clarity():
|
| 17 |
-
response = client.post("/rewrite", json={"text": "This sentence is a bit confusing.", "mode": "clarity"})
|
| 18 |
-
assert response.status_code == 200
|
| 19 |
-
assert "result" in response.json()
|
| 20 |
-
|
| 21 |
-
def test_fluency():
|
| 22 |
-
response = client.post("/rewrite", json={"text": "He no went there before.", "mode": "fluency"})
|
| 23 |
-
assert response.status_code == 200
|
| 24 |
-
assert "result" in response.json()
|
| 25 |
-
|
| 26 |
-
def test_tone():
|
| 27 |
-
response = client.post("/rewrite", json={"text": "Leave me alone.", "mode": "tone", "tone": "friendly"})
|
| 28 |
-
assert response.status_code == 200
|
| 29 |
-
assert "result" in response.json()
|
| 30 |
-
|
| 31 |
-
def test_translation():
|
| 32 |
-
response = client.post("/rewrite", json={"text": "How are you?", "mode": "translate", "target_lang": "fr"})
|
| 33 |
-
assert response.status_code == 200
|
| 34 |
-
assert "result" in response.json()
|
| 35 |
-
|
| 36 |
-
def test_pronoun():
|
| 37 |
-
response = client.post("/rewrite", json={"text": "Each user must provide his email.", "mode": "pronoun"})
|
| 38 |
-
assert response.status_code == 200
|
| 39 |
-
assert "result" in response.json()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/utils/shared.py
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from concurrent.futures import ThreadPoolExecutor
|
| 2 |
+
|
| 3 |
+
# Shared executor for all CPU-bound tasks
|
| 4 |
+
executor = ThreadPoolExecutor(max_workers=4)
|
requirements.txt
CHANGED
|
@@ -6,6 +6,6 @@ sentencepiece
|
|
| 6 |
pyspellchecker
|
| 7 |
spacy
|
| 8 |
nltk
|
| 9 |
-
language-tool-python
|
| 10 |
scikit-learn
|
| 11 |
textstat
|
|
|
|
|
|
| 6 |
pyspellchecker
|
| 7 |
spacy
|
| 8 |
nltk
|
|
|
|
| 9 |
scikit-learn
|
| 10 |
textstat
|
| 11 |
+
numpy>=1.21
|
run.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# run.py (no change needed for path handling if app.main:app is used)
|
| 2 |
+
import uvicorn
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
# from pathlib import Path # No longer strictly necessary to add project_root to sys.path explicitly here
|
| 6 |
+
# sys.path.insert(0, str(project_root)) # Can likely remove this line if your only problem was 'models' import
|
| 7 |
+
|
| 8 |
+
host = "0.0.0.0"
|
| 9 |
+
port = 7860
|
| 10 |
+
app_module = "app.main:app" # This refers to the 'app' package correctly
|
| 11 |
+
|
| 12 |
+
if __name__ == "__main__":
|
| 13 |
+
print(f"Starting Uvicorn server for {app_module} at http://{host}:{port}")
|
| 14 |
+
# ... rest of your print statements and uvicorn.run call
|
| 15 |
+
uvicorn.run(app_module, host=host, port=port, reload=True)
|