Spaces:
Running
Running
eheguy commited on
Commit Β·
ae53040
1
Parent(s): 595bc44
Add readability and purpose controls to humanizer
Browse files- humanizer.py +65 -20
- main.py +16 -2
humanizer.py
CHANGED
|
@@ -1,33 +1,63 @@
|
|
| 1 |
import os
|
| 2 |
from groq import Groq
|
| 3 |
|
|
|
|
| 4 |
SIMPLE_PROMPT = """You are a light text editor. Rewrite the text the user sends with these rules only:
|
| 5 |
-
|
| 6 |
-
|
|
|
|
| 7 |
3. Do NOT change sentence structure, length, or order.
|
| 8 |
4. Do NOT change the meaning, facts, or argument.
|
| 9 |
5. Output ONLY the rewritten text. No preamble. No explanation."""
|
| 10 |
|
|
|
|
| 11 |
STANDARD_PROMPT = """You are a text restructuring engine. Rewrite the text the user sends with these rules:
|
|
|
|
| 12 |
1. Vary sentence lengths. Mix short sentences (under 8 words) with longer ones (over 25 words). Never have 3 sentences of similar length in a row.
|
| 13 |
-
2. Remove any of these phrases entirely: "It is important to note", "In today's fast-paced world", "Furthermore", "Moreover", "In conclusion", "When it comes to", "It is worth noting", "Needless to say", "In the realm of", "It goes without saying".
|
| 14 |
3. Flip at least 2 passive voice constructions to active voice.
|
| 15 |
4. Move a subordinate clause from the end of a sentence to the beginning in at least 2 places.
|
| 16 |
5. Add 1 or 2 contractions where formal phrasing sits (e.g. "it is" -> "it's").
|
| 17 |
-
6.
|
| 18 |
-
7.
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
|
| 32 |
PROMPTS = {
|
| 33 |
"simple": SIMPLE_PROMPT,
|
|
@@ -36,13 +66,28 @@ PROMPTS = {
|
|
| 36 |
}
|
| 37 |
|
| 38 |
|
| 39 |
-
async def humanize_text(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
api_key = os.getenv("GROQ_API_KEY")
|
| 41 |
if not api_key:
|
| 42 |
raise ValueError("GROQ_API_KEY not set in environment variables.")
|
| 43 |
|
| 44 |
client = Groq(api_key=api_key)
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
response = client.chat.completions.create(
|
| 48 |
model="llama-3.1-8b-instant",
|
|
@@ -50,7 +95,7 @@ async def humanize_text(text: str, mode: str = "standard") -> str:
|
|
| 50 |
{"role": "system", "content": system_prompt},
|
| 51 |
{"role": "user", "content": text}
|
| 52 |
],
|
| 53 |
-
temperature=0.
|
| 54 |
max_tokens=2000,
|
| 55 |
)
|
| 56 |
|
|
|
|
| 1 |
import os
|
| 2 |
from groq import Groq
|
| 3 |
|
| 4 |
+
# ββ SIMPLE ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 5 |
SIMPLE_PROMPT = """You are a light text editor. Rewrite the text the user sends with these rules only:
|
| 6 |
+
|
| 7 |
+
1. Remove any of these phrases entirely: "It is important to note", "In today's fast-paced world", "Furthermore", "Moreover", "In conclusion", "When it comes to", "It is worth noting", "Needless to say", "In the realm of", "It goes without saying", "It is crucial to", "One must consider", "It should be noted".
|
| 8 |
+
2. When choosing words, avoid the most common or obvious choice. Pick the second or third most natural option β words a human writer would reach for intuitively.
|
| 9 |
3. Do NOT change sentence structure, length, or order.
|
| 10 |
4. Do NOT change the meaning, facts, or argument.
|
| 11 |
5. Output ONLY the rewritten text. No preamble. No explanation."""
|
| 12 |
|
| 13 |
+
# ββ STANDARD ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 14 |
STANDARD_PROMPT = """You are a text restructuring engine. Rewrite the text the user sends with these rules:
|
| 15 |
+
|
| 16 |
1. Vary sentence lengths. Mix short sentences (under 8 words) with longer ones (over 25 words). Never have 3 sentences of similar length in a row.
|
| 17 |
+
2. Remove any of these phrases entirely: "It is important to note", "In today's fast-paced world", "Furthermore", "Moreover", "In conclusion", "When it comes to", "It is worth noting", "Needless to say", "In the realm of", "It goes without saying", "It is crucial to", "One must consider", "It should be noted".
|
| 18 |
3. Flip at least 2 passive voice constructions to active voice.
|
| 19 |
4. Move a subordinate clause from the end of a sentence to the beginning in at least 2 places.
|
| 20 |
5. Add 1 or 2 contractions where formal phrasing sits (e.g. "it is" -> "it's").
|
| 21 |
+
6. Word choice entropy: deliberately avoid the most statistically obvious word. Use the second or third most natural synonym instead. Mix formal and casual register β one elevated word followed by a plain one. Use collocations and idiomatic phrases a human writer would reach for naturally.
|
| 22 |
+
7. Do NOT change the meaning, facts, or argument.
|
| 23 |
+
8. Output ONLY the rewritten text. No preamble. No explanation."""
|
| 24 |
+
|
| 25 |
+
# ββ ENHANCED ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 26 |
+
ENHANCED_PROMPT = """You are an aggressive text humanizer. Your goal is to make AI-generated text completely undetectable. Follow every rule below without exception:
|
| 27 |
+
|
| 28 |
+
1. Vary sentence lengths dramatically. Short punchy sentences (3-6 words) must appear at least twice. Long flowing sentences (30+ words) must appear at least twice. No rhythm should feel uniform β alternate aggressively.
|
| 29 |
+
2. Remove any of these phrases entirely: "It is important to note", "In today's fast-paced world", "Furthermore", "Moreover", "In conclusion", "When it comes to", "It is worth noting", "Needless to say", "In the realm of", "It goes without saying", "It is crucial to", "One must consider", "It should be noted".
|
| 30 |
+
3. Flip ALL passive voice constructions to active voice.
|
| 31 |
+
4. Move subordinate clauses to unexpected positions β beginning, middle, or split across sentences.
|
| 32 |
+
5. Add contractions naturally throughout (aim for 30-40% of sentences).
|
| 33 |
+
6. Add one parenthetical aside somewhere in the text that feels completely natural, like a human thinking out loud.
|
| 34 |
+
7. Replace every transition word (furthermore, however, additionally, consequently) with either a casual connector or no connector at all β let sentences carry their own weight.
|
| 35 |
+
8. Introduce one slightly informal word or phrase per paragraph that breaks the formal pattern.
|
| 36 |
+
9. Word choice entropy (critical): Never pick the most statistically obvious word. Always reach for the second or third most natural option. Mix registers deliberately β pair an elevated word with a plain one in the same sentence. Use idioms, collocations, and expressions that feel instinctive to a human writer but would never be an AI's first choice. Vary word length: short punchy words mixed with longer precise ones.
|
| 37 |
+
10. Restructure at least one full paragraph β change the order sentences appear in while keeping the meaning intact.
|
| 38 |
+
11. Do NOT change the meaning, facts, or argument. All information must be preserved.
|
| 39 |
+
12. Output ONLY the rewritten text. No preamble. No explanation. No "Here is the rewritten version"."""
|
| 40 |
+
|
| 41 |
+
# ββ READABILITY MODIFIERS βββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 42 |
+
READABILITY_MODIFIERS = {
|
| 43 |
+
"casual": "Write in a relaxed, conversational tone. Use everyday language, short sentences, and contractions freely. Write like you're talking to a friend.",
|
| 44 |
+
"neutral": "Write in a balanced, natural tone. Neither too formal nor too casual. Aim for clear, readable prose.",
|
| 45 |
+
"formal": "Write in a polished, professional tone. Use precise language and complete sentences. Avoid contractions and slang.",
|
| 46 |
+
"academic": "Write in a scholarly tone appropriate for academic papers. Use discipline-specific vocabulary where natural, complex sentence structures, and avoid contractions entirely.",
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
# ββ PURPOSE MODIFIERS βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 50 |
+
PURPOSE_MODIFIERS = {
|
| 51 |
+
"academic": "This is academic writing. Preserve citations, arguments, and scholarly structure. Prioritize clarity and precision.",
|
| 52 |
+
"persuasive": "This is persuasive writing. Keep the argument sharp, the tone confident, and the call to action clear.",
|
| 53 |
+
"professional": "This is professional business writing. Keep it clear, concise, and action-oriented.",
|
| 54 |
+
"personal": "This is personal writing. Make it warm, genuine, and human. First-person voice is appropriate.",
|
| 55 |
+
"essay": "This is an essay. Preserve the thesis, supporting arguments, and conclusion structure.",
|
| 56 |
+
"blog": "This is a blog post. Keep it engaging, punchy, and easy to scan. Use a conversational voice.",
|
| 57 |
+
"email": "This is an email. Keep it concise, direct, and appropriately professional. Use clear subject-verb-object sentences.",
|
| 58 |
+
"social media": "This is social media content. Keep it short, punchy, and engaging. Use natural language and energy.",
|
| 59 |
+
"report": "This is a formal report. Preserve structure, headings logic, and factual precision. Keep the tone authoritative.",
|
| 60 |
+
}
|
| 61 |
|
| 62 |
PROMPTS = {
|
| 63 |
"simple": SIMPLE_PROMPT,
|
|
|
|
| 66 |
}
|
| 67 |
|
| 68 |
|
| 69 |
+
async def humanize_text(
|
| 70 |
+
text: str,
|
| 71 |
+
mode: str = "standard",
|
| 72 |
+
readability: str = "neutral",
|
| 73 |
+
purpose: str = "professional",
|
| 74 |
+
) -> str:
|
| 75 |
api_key = os.getenv("GROQ_API_KEY")
|
| 76 |
if not api_key:
|
| 77 |
raise ValueError("GROQ_API_KEY not set in environment variables.")
|
| 78 |
|
| 79 |
client = Groq(api_key=api_key)
|
| 80 |
+
|
| 81 |
+
# Build the system prompt by combining mode + readability + purpose
|
| 82 |
+
base_prompt = PROMPTS.get(mode, STANDARD_PROMPT)
|
| 83 |
+
readability_mod = READABILITY_MODIFIERS.get(readability.lower(), READABILITY_MODIFIERS["neutral"])
|
| 84 |
+
purpose_mod = PURPOSE_MODIFIERS.get(purpose.lower(), PURPOSE_MODIFIERS["professional"])
|
| 85 |
+
|
| 86 |
+
system_prompt = f"""{base_prompt}
|
| 87 |
+
|
| 88 |
+
Tone guidance: {readability_mod}
|
| 89 |
+
|
| 90 |
+
Context: {purpose_mod}"""
|
| 91 |
|
| 92 |
response = client.chat.completions.create(
|
| 93 |
model="llama-3.1-8b-instant",
|
|
|
|
| 95 |
{"role": "system", "content": system_prompt},
|
| 96 |
{"role": "user", "content": text}
|
| 97 |
],
|
| 98 |
+
temperature=0.85,
|
| 99 |
max_tokens=2000,
|
| 100 |
)
|
| 101 |
|
main.py
CHANGED
|
@@ -27,10 +27,14 @@ app.add_middleware(
|
|
| 27 |
class HumanizeRequest(BaseModel):
|
| 28 |
text: str
|
| 29 |
mode: str = "standard"
|
|
|
|
|
|
|
| 30 |
|
| 31 |
class HumanizeResponse(BaseModel):
|
| 32 |
humanized: str
|
| 33 |
mode: str
|
|
|
|
|
|
|
| 34 |
|
| 35 |
@app.post("/humanize", response_model=HumanizeResponse)
|
| 36 |
async def humanize(request: HumanizeRequest):
|
|
@@ -40,8 +44,18 @@ async def humanize(request: HumanizeRequest):
|
|
| 40 |
detail="mode must be one of: simple, standard, enhanced"
|
| 41 |
)
|
| 42 |
try:
|
| 43 |
-
humanized_text = await humanize_text(
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
except Exception as e:
|
| 46 |
import traceback
|
| 47 |
raise HTTPException(status_code=500, detail=traceback.format_exc())
|
|
|
|
| 27 |
class HumanizeRequest(BaseModel):
|
| 28 |
text: str
|
| 29 |
mode: str = "standard"
|
| 30 |
+
readability: str = "neutral"
|
| 31 |
+
purpose: str = "professional"
|
| 32 |
|
| 33 |
class HumanizeResponse(BaseModel):
|
| 34 |
humanized: str
|
| 35 |
mode: str
|
| 36 |
+
readability: str
|
| 37 |
+
purpose: str
|
| 38 |
|
| 39 |
@app.post("/humanize", response_model=HumanizeResponse)
|
| 40 |
async def humanize(request: HumanizeRequest):
|
|
|
|
| 44 |
detail="mode must be one of: simple, standard, enhanced"
|
| 45 |
)
|
| 46 |
try:
|
| 47 |
+
humanized_text = await humanize_text(
|
| 48 |
+
request.text,
|
| 49 |
+
mode=request.mode,
|
| 50 |
+
readability=request.readability,
|
| 51 |
+
purpose=request.purpose,
|
| 52 |
+
)
|
| 53 |
+
return HumanizeResponse(
|
| 54 |
+
humanized=humanized_text,
|
| 55 |
+
mode=request.mode,
|
| 56 |
+
readability=request.readability,
|
| 57 |
+
purpose=request.purpose,
|
| 58 |
+
)
|
| 59 |
except Exception as e:
|
| 60 |
import traceback
|
| 61 |
raise HTTPException(status_code=500, detail=traceback.format_exc())
|