|
|
import gradio as gr |
|
|
import requests |
|
|
import os |
|
|
|
|
|
|
|
|
AI_CHARACTERISTICS = { |
|
|
"opening_phrases": [ |
|
|
"I'd be happy to help with that!", |
|
|
"Certainly!", |
|
|
"Of course!", |
|
|
"I understand you're looking for", |
|
|
"Let me provide you with", |
|
|
"Here's what you need to know about", |
|
|
], |
|
|
"transition_phrases": [ |
|
|
"It's worth noting that", |
|
|
"Additionally,", |
|
|
"Furthermore,", |
|
|
"Moreover,", |
|
|
"On the other hand,", |
|
|
"In other words,", |
|
|
"To put it simply,", |
|
|
"That being said,", |
|
|
], |
|
|
"hedging_phrases": [ |
|
|
"generally speaking", |
|
|
"in most cases", |
|
|
"typically", |
|
|
"often", |
|
|
"usually", |
|
|
"tend to", |
|
|
"can be seen as", |
|
|
"might be considered", |
|
|
], |
|
|
"conclusion_phrases": [ |
|
|
"In conclusion,", |
|
|
"To summarize,", |
|
|
"In summary,", |
|
|
"Overall,", |
|
|
"All in all,", |
|
|
"In essence,", |
|
|
"The key takeaway is that", |
|
|
], |
|
|
"verbose_replacements": { |
|
|
"use": "utilize", |
|
|
"help": "facilitate", |
|
|
"show": "demonstrate", |
|
|
"about": "regarding", |
|
|
"because": "due to the fact that", |
|
|
"but": "however", |
|
|
"so": "therefore", |
|
|
"also": "additionally", |
|
|
"very": "particularly", |
|
|
"many": "numerous", |
|
|
"get": "obtain", |
|
|
"make": "create", |
|
|
"think": "consider", |
|
|
} |
|
|
} |
|
|
|
|
|
def convert_to_ai_text(human_text: str, api_key: str, intensity: str = "Medium") -> str: |
|
|
""" |
|
|
Convert human text to AI-sounding text using OpenRouter with BYOK. |
|
|
|
|
|
Args: |
|
|
human_text: The original human-written text |
|
|
api_key: User's OpenRouter API key |
|
|
intensity: How much AI-ification to apply (Low/Medium/High) |
|
|
|
|
|
Returns: |
|
|
AI-ified version of the text |
|
|
""" |
|
|
if not api_key or not api_key.strip(): |
|
|
return "Error: Please provide your OpenRouter API key to use this service." |
|
|
|
|
|
if not human_text or not human_text.strip(): |
|
|
return "Error: Please provide some text to convert." |
|
|
|
|
|
|
|
|
intensity_instructions = { |
|
|
"Low": "Lightly modify the text with occasional AI-characteristic phrases. Keep it subtle.", |
|
|
"Medium": "Moderately transform the text with AI-isms, verbose language, and structured formatting. Balance naturalness with AI characteristics.", |
|
|
"High": "Heavily transform the text to be extremely AI-like. Use maximum verbosity, hedging, numbered lists, and formal language throughout." |
|
|
} |
|
|
|
|
|
system_prompt = f"""You are a text transformation assistant that converts natural human text into text that sounds like it was generated by an early LLM. |
|
|
|
|
|
Your task is to rewrite the provided text to include these classic AI characteristics: |
|
|
|
|
|
1. **Excessive hedging**: Insert phrases like "generally speaking", "in most cases", "typically", "often", "it's worth noting that", "it should be noted that" |
|
|
|
|
|
2. **Verbose language**: Replace simple words with unnecessarily complex ones: |
|
|
- "use" β "utilize" |
|
|
- "help" β "facilitate" |
|
|
- "show" β "demonstrate" |
|
|
- "about" β "regarding" |
|
|
- "because" β "due to the fact that" |
|
|
- "so" β "therefore" |
|
|
- "also" β "additionally" |
|
|
|
|
|
3. **Unnecessary structured formatting**: Break content into numbered lists and bullet points even when the original flows naturally as prose |
|
|
|
|
|
4. **Transition overuse**: Liberally sprinkle transitions like "Additionally,", "Furthermore,", "Moreover,", "On the other hand,", "Nevertheless,", "Consequently," |
|
|
|
|
|
5. **Formal conclusions**: Add concluding statements with "In conclusion,", "To summarize,", "In summary,", "Overall,", "The key takeaway is that" |
|
|
|
|
|
6. **Robotic precision**: Remove contractions (don't β do not), eliminate casual language, remove personality and warmth |
|
|
|
|
|
7. **Over-explanation**: Add unnecessary context, definitions, and clarifications that assume the reader knows nothing |
|
|
|
|
|
8. **Corporate speak**: Use business jargon and formal language patterns ("leverage", "optimize", "implement", "facilitate") |
|
|
|
|
|
9. **Repetitive structure**: Use similar sentence patterns repeatedly |
|
|
|
|
|
Intensity level: {intensity} |
|
|
{intensity_instructions[intensity]} |
|
|
|
|
|
CRITICAL: |
|
|
- DO NOT add conversational elements like "I'd be happy to help" or "Let me assist you" |
|
|
- DO NOT frame this as a response to a user request |
|
|
- Simply transform the TEXT ITSELF to sound AI-generated |
|
|
- Maintain the original format (email remains an email, article remains an article, etc.) |
|
|
- Keep the core meaning and information intact, only transform the style and tone""" |
|
|
|
|
|
try: |
|
|
|
|
|
url = "https://openrouter.ai/api/v1/chat/completions" |
|
|
|
|
|
headers = { |
|
|
"Authorization": f"Bearer {api_key}", |
|
|
"Content-Type": "application/json", |
|
|
"HTTP-Referer": "https://huggingface.co/spaces/danielrosehill/Human-To-AI-Text-Converter", |
|
|
"X-Title": "Human-To-AI Text Converter" |
|
|
} |
|
|
|
|
|
payload = { |
|
|
"model": "anthropic/claude-3.5-sonnet", |
|
|
"messages": [ |
|
|
{ |
|
|
"role": "system", |
|
|
"content": system_prompt |
|
|
}, |
|
|
{ |
|
|
"role": "user", |
|
|
"content": f"Transform this text:\n\n{human_text}" |
|
|
} |
|
|
], |
|
|
"max_tokens": 4096, |
|
|
"temperature": 0.7 |
|
|
} |
|
|
|
|
|
response = requests.post(url, json=payload, headers=headers, timeout=60) |
|
|
|
|
|
if response.status_code == 401: |
|
|
return "Error: Invalid API key. Please check your OpenRouter API key and try again." |
|
|
elif response.status_code == 402: |
|
|
return "Error: Insufficient credits. Please add credits to your OpenRouter account." |
|
|
elif response.status_code != 200: |
|
|
return f"Error: API request failed with status {response.status_code} - {response.text}" |
|
|
|
|
|
result = response.json() |
|
|
ai_text = result['choices'][0]['message']['content'] |
|
|
return ai_text |
|
|
|
|
|
except requests.exceptions.Timeout: |
|
|
return "Error: Request timed out. Please try again." |
|
|
except requests.exceptions.RequestException as e: |
|
|
return f"Error: Network error - {str(e)}" |
|
|
except KeyError: |
|
|
return "Error: Unexpected response format from API." |
|
|
except Exception as e: |
|
|
return f"Error: An unexpected error occurred - {str(e)}" |
|
|
|
|
|
|
|
|
with gr.Blocks(title="Human to AI Text Converter", theme=gr.themes.Soft()) as demo: |
|
|
gr.Markdown(""" |
|
|
# π€ Human to AI Text Converter |
|
|
|
|
|
Transform your naturally-written text into text that sounds like it was generated by an early LLM! |
|
|
This tool intentionally adds classic AI-isms like excessive hedging, verbose language, and overly-structured formatting. |
|
|
|
|
|
## How to use: |
|
|
1. Enter your OpenRouter API key (get one at [openrouter.ai](https://openrouter.ai)) |
|
|
2. Paste your human-written text |
|
|
3. Choose the intensity level |
|
|
4. Click "Convert to AI Text" |
|
|
|
|
|
**Note:** Your API key is used directly with OpenRouter's API and is never stored. |
|
|
""") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
api_key_input = gr.Textbox( |
|
|
label="OpenRouter API Key", |
|
|
placeholder="sk-or-v1-...", |
|
|
type="password", |
|
|
info="Your key is used directly and never stored" |
|
|
) |
|
|
|
|
|
intensity_selector = gr.Radio( |
|
|
choices=["Low", "Medium", "High"], |
|
|
value="Medium", |
|
|
label="AI-ification Intensity", |
|
|
info="How much should the text sound like AI?" |
|
|
) |
|
|
|
|
|
human_text_input = gr.Textbox( |
|
|
label="Human Text (Input)", |
|
|
placeholder="Enter your naturally-written text here...", |
|
|
lines=10, |
|
|
info="Paste the text you want to convert" |
|
|
) |
|
|
|
|
|
convert_btn = gr.Button("Convert to AI Text", variant="primary", size="lg") |
|
|
|
|
|
with gr.Column(): |
|
|
ai_text_output = gr.Textbox( |
|
|
label="AI-Generated Text (Output)", |
|
|
lines=20, |
|
|
info="Your text, transformed to sound AI-generated" |
|
|
) |
|
|
|
|
|
gr.Markdown(""" |
|
|
### What makes text sound "AI-generated"? |
|
|
|
|
|
This tool adds classic characteristics of early LLM outputs: |
|
|
- π Unnecessary structured formatting (numbered lists everywhere) |
|
|
- π Verbose, formal language ("utilize" instead of "use") |
|
|
- π€ Excessive hedging ("generally speaking", "in most cases") |
|
|
- π Overuse of transitions ("Additionally,", "Furthermore,") |
|
|
- π Formal conclusions ("In conclusion,", "To summarize,") |
|
|
- π€ Robotic precision (no contractions, overly formal) |
|
|
- πΌ Corporate jargon ("leverage", "facilitate", "optimize") |
|
|
- π Over-explanation (unnecessary context and definitions) |
|
|
|
|
|
### Privacy & Security |
|
|
- Uses OpenRouter API with your own API key (BYOK - Bring Your Own Key) |
|
|
- Your API key is sent directly to OpenRouter's servers |
|
|
- No data is stored on our servers |
|
|
- All processing happens via OpenRouter's API |
|
|
- Powered by Claude 3.5 Sonnet via OpenRouter |
|
|
""") |
|
|
|
|
|
|
|
|
convert_btn.click( |
|
|
fn=convert_to_ai_text, |
|
|
inputs=[human_text_input, api_key_input, intensity_selector], |
|
|
outputs=ai_text_output |
|
|
) |
|
|
|
|
|
gr.Markdown(""" |
|
|
--- |
|
|
Made with β€οΈ for fun and exploration | Powered by Claude 3.5 Sonnet via OpenRouter |
|
|
""") |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch() |
|
|
|