aikenml commited on
Commit
606e889
·
1 Parent(s): 9874a5c
__pycache__/main.cpython-310.pyc CHANGED
Binary files a/__pycache__/main.cpython-310.pyc and b/__pycache__/main.cpython-310.pyc differ
 
__pycache__/main.cpython-312.pyc ADDED
Binary file (7.54 kB). View file
 
app/__pycache__/__init__.cpython-310.pyc CHANGED
Binary files a/app/__pycache__/__init__.cpython-310.pyc and b/app/__pycache__/__init__.cpython-310.pyc differ
 
app/api/__pycache__/endpoints.cpython-310.pyc DELETED
Binary file (3.33 kB)
 
app/api/__pycache__/endpoints.cpython-312.pyc DELETED
Binary file (1.33 kB)
 
app/api/endpoints.py DELETED
@@ -1,161 +0,0 @@
1
- from fastapi import APIRouter, HTTPException
2
- from pydantic import BaseModel
3
- from typing import Optional, List
4
- from app.chains.humanizer_chain import humanize_text # Assuming this is your humanizer function
5
- import sys
6
- import os
7
- sys.path.append(os.path.abspath("../.."))
8
-
9
- import app.chains.detectors as detectors
10
- from importlib import reload
11
- reload(detectors)
12
-
13
-
14
- router = APIRouter()
15
-
16
- class HumanizeInput(BaseModel):
17
- text: str
18
-
19
- class DetectInput(BaseModel):
20
- text: str
21
-
22
- class DetectorResult(BaseModel):
23
- detector_name: str
24
- ai_probability: float
25
-
26
- class DetectionResponse(BaseModel):
27
- results: List[DetectorResult]
28
-
29
-
30
-
31
-
32
- @router.post("/humanize")
33
- async def humanize_text_endpoint(input_data: HumanizeInput):
34
- try:
35
- # Call your humanizer function with just the text
36
- humanized = humanize_text(
37
- input_data.text,
38
- )
39
- return {
40
- "original": input_data.text,
41
- "humanized": humanized
42
- }
43
- except Exception as e:
44
- raise HTTPException(status_code=500, detail=str(e))
45
-
46
-
47
- @router.post("/detect")
48
- async def detect_ai_endpoint(input_data: DetectInput) -> DetectionResponse:
49
- try:
50
- print(f"Detection request received for text: {input_data.text[:100]}...") # Debug log
51
-
52
- # Call the AI detection function
53
- detection_results = detectors.detect_ai(input_data.text)
54
- print(f"Raw detection results: {detection_results}") # Debug log
55
-
56
- # Ensure the results are in the expected format
57
- formatted_results = []
58
-
59
- # Handle different possible return formats from detect_ai
60
- if isinstance(detection_results, list):
61
- print("Processing list format results")
62
- for result in detection_results:
63
- if isinstance(result, dict):
64
- # Handle dict with various possible key names
65
- name = result.get('name') or result.get('detector_name') or result.get('detector') or 'Unknown Detector'
66
- probability = result.get('probability') or result.get('ai_probability') or result.get('score') or 0.0
67
- formatted_results.append(DetectorResult(
68
- detector_name=str(name),
69
- ai_probability=float(probability)
70
- ))
71
- else:
72
- print(f"Unexpected result format in list: {type(result)}")
73
-
74
- elif isinstance(detection_results, dict):
75
- print("Processing dict format results")
76
- # If it returns a single result or dict format
77
- for detector_name, probability in detection_results.items():
78
- try:
79
- formatted_results.append(DetectorResult(
80
- detector_name=str(detector_name),
81
- ai_probability=float(probability)
82
- ))
83
- except (ValueError, TypeError) as e:
84
- print(f"Error processing detector result {detector_name}: {probability}, Error: {e}")
85
-
86
- else:
87
- print(f"Unexpected detection results type: {type(detection_results)}")
88
- # Fallback: create mock results for testing
89
- formatted_results = [
90
- DetectorResult(detector_name="Test Detector", ai_probability=0.75)
91
- ]
92
-
93
- # If no results were formatted, create a test result
94
- if not formatted_results:
95
- print("No formatted results, creating test result")
96
- formatted_results = [
97
- DetectorResult(detector_name="Default Detector", ai_probability=0.5)
98
- ]
99
-
100
- print(f"Formatted results: {formatted_results}") # Debug log
101
- return DetectionResponse(results=formatted_results)
102
-
103
- except ImportError as e:
104
- print(f"Import error for detect_ai: {e}")
105
- # Return mock results if detect_ai function is not available
106
- return DetectionResponse(results=[
107
- DetectorResult(detector_name="GPTZero", ai_probability=0.85),
108
- DetectorResult(detector_name="AI Content Detector", ai_probability=0.72),
109
- DetectorResult(detector_name="Originality.ai", ai_probability=0.68)
110
- ])
111
- except Exception as e:
112
- print(f"Detection error: {str(e)}") # Debug log
113
- raise HTTPException(status_code=500, detail=f"Detection failed: {str(e)}")
114
-
115
- # # Test endpoint to verify the detection endpoint is working
116
- # @router.get("/detect/test")
117
- # async def test_detect_endpoint():
118
- # """Test endpoint to verify detection functionality"""
119
- # return DetectionResponse(results=[
120
- # DetectorResult(detector_name="Test Detector 1", ai_probability=0.85),
121
- # DetectorResult(detector_name="Test Detector 2", ai_probability=0.42),
122
- # DetectorResult(detector_name="Test Detector 3", ai_probability=0.91)
123
- # ])
124
-
125
-
126
-
127
-
128
- # @router.post("/detect")
129
- # async def detect_ai_endpoint(input_data: DetectInput) -> DetectionResponse:
130
- # try:
131
- # # Call the AI detection function
132
- # detection_results = detectors.detect_ai(input_data.text)
133
-
134
- # # Ensure the results are in the expected format
135
- # # If detect_ai returns a different format, adjust accordingly
136
- # formatted_results = []
137
-
138
- # # Assuming detect_ai returns a list of dictionaries with detector info
139
- # # You may need to adjust this based on your actual detect_ai function output
140
- # if isinstance(detection_results, list):
141
- # for result in detection_results:
142
- # formatted_results.append(DetectorResult(
143
- # detector_name=result.get('name', 'Unknown Detector'),
144
- # ai_probability=result.get('probability', 0.0)
145
- # ))
146
- # elif isinstance(detection_results, dict):
147
- # # If it returns a single result or dict format
148
- # for detector_name, probability in detection_results.items():
149
- # formatted_results.append(DetectorResult(
150
- # detector_name=detector_name,
151
- # ai_probability=probability
152
- # ))
153
- # else:
154
- # # If it's a different format, you'll need to adjust this
155
- # raise ValueError("Unexpected detection results format")
156
-
157
- # return DetectionResponse(results=formatted_results)
158
-
159
- # except Exception as e:
160
- # raise HTTPException(status_code=500, detail=f"Detection failed: {str(e)}")
161
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/chains/__pycache__/detectors.cpython-310.pyc DELETED
Binary file (584 Bytes)
 
app/chains/__pycache__/humanizer_chain.cpython-310.pyc DELETED
Binary file (2.03 kB)
 
app/chains/__pycache__/humanizer_chain.cpython-312.pyc DELETED
Binary file (2.36 kB)
 
app/chains/__pycache__/mistral_hu.cpython-310.pyc DELETED
Binary file (1.78 kB)
 
app/chains/detectors.py DELETED
@@ -1,36 +0,0 @@
1
- import requests
2
-
3
-
4
- def detect_ai(text):
5
- response = requests.post(
6
- "https://api.sapling.ai/api/v1/aidetect",
7
- json={
8
- "key": "RHMMYVZX39KKSOJP5VZTCRUQLCB7LFFX",
9
- "text": text
10
- }
11
- )
12
-
13
- # return str(round(float(response.json()['score']),3) * 100) + "% AI generated"
14
- return [
15
- {
16
- "name": "GPTZero",
17
- "probability": 0.3 # 85% AI probability
18
- },
19
- {
20
- "name": "Another Detector",
21
- "probability": 0.2 # 85% AI probability
22
- },
23
- {
24
- "name": "Another Detector ",
25
- "probability": 0.9 # 85% AI probability
26
- }
27
- ]
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/chains/humanizer_chain.py DELETED
@@ -1,62 +0,0 @@
1
- import os
2
- from dotenv import load_dotenv
3
- from langchain_core.prompts import ChatPromptTemplate
4
- from langchain_openai import ChatOpenAI
5
-
6
-
7
- load_dotenv()
8
- openai_api_key = os.getenv("OPENAI_API_KEY")
9
-
10
- if not openai_api_key:
11
- raise ValueError("OPENAI_API_KEY not found in .env file.")
12
-
13
-
14
- llm = ChatOpenAI(
15
- model="gpt-4o",
16
- temperature=0.1,
17
- top_p=0.9,
18
- frequency_penalty=0.5,
19
- presence_penalty=0.3,
20
- api_key=openai_api_key
21
- )
22
-
23
-
24
-
25
- default_prompt = \
26
- """
27
- Rewrite the following text in the style of a non-native English speaker with an **IELTS Band 6** writing level.
28
-
29
- The rewritten text should maintain the original meaning clearly, but **include some natural grammatical mistakes,
30
- occasional vocabulary misuse, and slightly awkward phrasing** typical of an IELTS Band 6 writer.
31
-
32
- Make sure the tone remains human-like and genuine, with a readable flow, and not too polished or “perfect.”
33
-
34
- This style should be applied **regardless of the content type** (academic, casual, technical, marketing, etc.),
35
- so preserve the original tone and context while infusing the non-native characteristics.
36
-
37
- The goal is to **make the text sound human-written (with minor errors)** to reduce the likelihood of
38
- AI detection by tools like GPTZero or Originality.ai.
39
-
40
- **Instructions:** Provide **only** the rewritten passage as the output, with no explanations or extra commentary.
41
-
42
- Aim for roughly **400 words** in the rewritten version (adjusting length as needed to stay proportional to the input).
43
-
44
- **Text to rewrite:**
45
-
46
- {input_text}
47
- """
48
-
49
-
50
- def humanize_text(text: str) -> str:
51
- # template = PROMPT_TEMPLATES.get(audience, PROMPT_TEMPLATES["default"])
52
-
53
- prompt = ChatPromptTemplate.from_template(template=default_prompt)
54
-
55
- humanizer_chain = prompt | llm
56
- response = humanizer_chain.invoke({"input_text": text})
57
-
58
- return response.content
59
-
60
- # text = ""
61
- # humanized_text = humanize_text(text)
62
- # print(humanized_text)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/test/test.ipynb DELETED
@@ -1,209 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "code",
5
- "execution_count": 1,
6
- "metadata": {},
7
- "outputs": [
8
- {
9
- "name": "stdout",
10
- "output_type": "stream",
11
- "text": [
12
- "{'score': 0.001455879211425759,\n",
13
- " 'sentence_scores': [{'score': 0.0,\n",
14
- " 'sentence': 'This is sample text meaw meaw'}],\n",
15
- " 'text': 'This is sample text meaw meaw',\n",
16
- " 'token_probs': [0.0013885498046875,\n",
17
- " 0.001325070858001709,\n",
18
- " 0.001367032527923584,\n",
19
- " 0.001367032527923584,\n",
20
- " 0.0014104247093200684,\n",
21
- " 0.0015978217124938965,\n",
22
- " 0.0015012025833129883,\n",
23
- " 0.0015978217124938965],\n",
24
- " 'tokens': ['This', ' is', ' sample', ' text', ' me', 'aw', ' me', 'aw']}\n"
25
- ]
26
- }
27
- ],
28
- "source": [
29
- "import requests\n",
30
- "from pprint import pprint\n",
31
- "\n",
32
- "response = requests.post(\n",
33
- " \"https://api.sapling.ai/api/v1/aidetect\",\n",
34
- " json={\n",
35
- " \"key\": \"RHMMYVZX39KKSOJP5VZTCRUQLCB7LFFX\",\n",
36
- " \"text\": \"This is sample text meaw meaw\"\n",
37
- " }\n",
38
- ")\n",
39
- "\n",
40
- "pprint(response.json())\n"
41
- ]
42
- },
43
- {
44
- "cell_type": "code",
45
- "execution_count": 2,
46
- "metadata": {},
47
- "outputs": [],
48
- "source": [
49
- "def check(text):\n",
50
- " response = requests.post(\n",
51
- " \"https://api.sapling.ai/api/v1/aidetect\",\n",
52
- " json={\n",
53
- " \"key\": \"RHMMYVZX39KKSOJP5VZTCRUQLCB7LFFX\",\n",
54
- " \"text\": text\n",
55
- " }\n",
56
- " )\n",
57
- "\n",
58
- " return response.json()['score']"
59
- ]
60
- },
61
- {
62
- "cell_type": "code",
63
- "execution_count": 3,
64
- "metadata": {},
65
- "outputs": [
66
- {
67
- "data": {
68
- "text/plain": [
69
- "0.9999988789854031"
70
- ]
71
- },
72
- "execution_count": 3,
73
- "metadata": {},
74
- "output_type": "execute_result"
75
- }
76
- ],
77
- "source": [
78
- "check('In contemporary research, fractal geometry plays an essential role in fields ranging from physics and computer graphics to finance and medicine. For instance, fractal-based algorithms improve image compression, texture synthesis, and pattern recognition. In medicine, fractal analysis assists in characterizing irregular heartbeats or tumor growth patterns. The interplay between fractal geometry and other branches of mathematics, such as measure theory, probability, and number theory, continues to be an active and fruitful area of study')"
79
- ]
80
- },
81
- {
82
- "cell_type": "code",
83
- "execution_count": 4,
84
- "metadata": {},
85
- "outputs": [],
86
- "source": [
87
- "text = \"\"\"Dynamical systems theory is important part of mathematics that focus on study how systems change over time with fixed rule. These systems can be describe by differential equations, difference equations, or more abstract mappings. They capture how states evolve in different scientific and engineering situations. The theory give a strong framework to understand complex things like stability, chaos, and bifurcations which happen naturally in physical, biological, and social systems.\n",
88
- "\n",
89
- "In basic idea, a dynamical system have a state space and a rule that explain how points in this space move or change with time. Continuous-time dynamical systems usually use ordinary differential equations (ODEs) for modeling, while discrete-time systems use iterated maps or difference equations. The path of the system, which is the line traced by the state as time go on, holds important information about how the system behave in long term and its stability.\"\"\""
90
- ]
91
- },
92
- {
93
- "cell_type": "code",
94
- "execution_count": 5,
95
- "metadata": {},
96
- "outputs": [
97
- {
98
- "data": {
99
- "text/plain": [
100
- "0.0008568135115618603"
101
- ]
102
- },
103
- "execution_count": 5,
104
- "metadata": {},
105
- "output_type": "execute_result"
106
- }
107
- ],
108
- "source": [
109
- "check(text)"
110
- ]
111
- },
112
- {
113
- "cell_type": "code",
114
- "execution_count": 13,
115
- "metadata": {},
116
- "outputs": [
117
- {
118
- "data": {
119
- "text/plain": [
120
- "<module 'app.chains.detectors' from '/Users/ajkenkazin/ALL-PROJECTS/AI_Projects/AI-text-humanizer/app/chains/detectors.py'>"
121
- ]
122
- },
123
- "execution_count": 13,
124
- "metadata": {},
125
- "output_type": "execute_result"
126
- }
127
- ],
128
- "source": [
129
- "import sys\n",
130
- "import os\n",
131
- "sys.path.append(os.path.abspath(\"../..\"))\n",
132
- "\n",
133
- "import app.chains.detectors as detectors\n",
134
- "from importlib import reload\n",
135
- "\n",
136
- "reload(detectors)"
137
- ]
138
- },
139
- {
140
- "cell_type": "code",
141
- "execution_count": 14,
142
- "metadata": {},
143
- "outputs": [
144
- {
145
- "data": {
146
- "text/plain": [
147
- "'0.1% AI generated'"
148
- ]
149
- },
150
- "execution_count": 14,
151
- "metadata": {},
152
- "output_type": "execute_result"
153
- }
154
- ],
155
- "source": [
156
- "detectors.detect_ai(text)"
157
- ]
158
- },
159
- {
160
- "cell_type": "code",
161
- "execution_count": null,
162
- "metadata": {},
163
- "outputs": [],
164
- "source": []
165
- },
166
- {
167
- "cell_type": "code",
168
- "execution_count": null,
169
- "metadata": {},
170
- "outputs": [],
171
- "source": []
172
- },
173
- {
174
- "cell_type": "code",
175
- "execution_count": null,
176
- "metadata": {},
177
- "outputs": [],
178
- "source": []
179
- },
180
- {
181
- "cell_type": "code",
182
- "execution_count": null,
183
- "metadata": {},
184
- "outputs": [],
185
- "source": []
186
- }
187
- ],
188
- "metadata": {
189
- "kernelspec": {
190
- "display_name": "demo",
191
- "language": "python",
192
- "name": "python3"
193
- },
194
- "language_info": {
195
- "codemirror_mode": {
196
- "name": "ipython",
197
- "version": 3
198
- },
199
- "file_extension": ".py",
200
- "mimetype": "text/x-python",
201
- "name": "python",
202
- "nbconvert_exporter": "python",
203
- "pygments_lexer": "ipython3",
204
- "version": "3.10.13"
205
- }
206
- },
207
- "nbformat": 4,
208
- "nbformat_minor": 2
209
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/test/test_models.ipynb DELETED
@@ -1,307 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "code",
5
- "execution_count": 8,
6
- "metadata": {},
7
- "outputs": [],
8
- "source": [
9
- "from humanizer_chain import humanize_text"
10
- ]
11
- },
12
- {
13
- "cell_type": "code",
14
- "execution_count": 9,
15
- "metadata": {},
16
- "outputs": [],
17
- "source": [
18
- "text=\"\"\"Biology is the scientific study of life and living organisms, encompassing subdisciplines that examine the structure, \n",
19
- "function, growth, origin, and evolution. Molecular biology focuses on interactions among cellular components such as DNA, RNA,\n",
20
- " proteins, and other biomolecules. Cellular biology delves into structure and function of cells, units of life. Within cells, \n",
21
- " organelles like mitochondria, chloroplasts, and the nucleus illustrate specialization for energy production, photosynthesis, \n",
22
- " and genetic regulation. Processes like mitosis and meiosis are essential for growth, \n",
23
- "reproduction, and inheritance, while cell signaling enables multicellular coordination.\n",
24
- "\"\"\""
25
- ]
26
- },
27
- {
28
- "cell_type": "code",
29
- "execution_count": 10,
30
- "metadata": {},
31
- "outputs": [
32
- {
33
- "name": "stdout",
34
- "output_type": "stream",
35
- "text": [
36
- "Biology is a science study about life and living things, which include many subfields that look at structure, function, growth, origin, and evolution. Molecular biology is about how parts of cells like DNA, RNA, proteins, and other biomolecules interact with each other. Cellular biology is more about the structure and function of cells because they are the basic units of life. Inside cells, there are organelles such as mitochondria, chloroplasts, and nucleus that show special roles for making energy, doing photosynthesis, and controlling genes. Processes like mitosis and meiosis are very important for growing, reproducing, and passing on traits to next generations. Also cell signaling helps in coordination between many cells in multicellular organisms.\n"
37
- ]
38
- }
39
- ],
40
- "source": [
41
- "humanized_text = humanize_text(text)\n",
42
- "print(humanized_text)"
43
- ]
44
- },
45
- {
46
- "cell_type": "code",
47
- "execution_count": 1,
48
- "metadata": {},
49
- "outputs": [
50
- {
51
- "name": "stdout",
52
- "output_type": "stream",
53
- "text": [
54
- "Requirement already satisfied: transformers in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (4.47.0)\n",
55
- "Requirement already satisfied: filelock in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from transformers) (3.13.1)\n",
56
- "Requirement already satisfied: huggingface-hub<1.0,>=0.24.0 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from transformers) (0.29.3)\n",
57
- "Requirement already satisfied: numpy>=1.17 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from transformers) (1.26.4)\n",
58
- "Requirement already satisfied: packaging>=20.0 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from transformers) (23.2)\n",
59
- "Requirement already satisfied: pyyaml>=5.1 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from transformers) (6.0.2)\n",
60
- "Requirement already satisfied: regex!=2019.12.17 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from transformers) (2024.11.6)\n",
61
- "Requirement already satisfied: requests in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from transformers) (2.32.3)\n",
62
- "Requirement already satisfied: tokenizers<0.22,>=0.21 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from transformers) (0.21.0)\n",
63
- "Requirement already satisfied: safetensors>=0.4.1 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from transformers) (0.4.5)\n",
64
- "Requirement already satisfied: tqdm>=4.27 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from transformers) (4.66.5)\n",
65
- "Requirement already satisfied: fsspec>=2023.5.0 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from huggingface-hub<1.0,>=0.24.0->transformers) (2024.10.0)\n",
66
- "Requirement already satisfied: typing-extensions>=3.7.4.3 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from huggingface-hub<1.0,>=0.24.0->transformers) (4.12.2)\n",
67
- "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from requests->transformers) (3.3.2)\n",
68
- "Requirement already satisfied: idna<4,>=2.5 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from requests->transformers) (3.7)\n",
69
- "Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from requests->transformers) (2.2.3)\n",
70
- "Requirement already satisfied: certifi>=2017.4.17 in /opt/miniconda3/envs/demo/lib/python3.10/site-packages (from requests->transformers) (2025.4.26)\n"
71
- ]
72
- }
73
- ],
74
- "source": [
75
- "!pip install transformers"
76
- ]
77
- },
78
- {
79
- "cell_type": "code",
80
- "execution_count": 3,
81
- "metadata": {},
82
- "outputs": [
83
- {
84
- "name": "stdout",
85
- "output_type": "stream",
86
- "text": [
87
- "\n",
88
- " _| _| _| _| _|_|_| _|_|_| _|_|_| _| _| _|_|_| _|_|_|_| _|_| _|_|_| _|_|_|_|\n",
89
- " _| _| _| _| _| _| _| _|_| _| _| _| _| _| _| _|\n",
90
- " _|_|_|_| _| _| _| _|_| _| _|_| _| _| _| _| _| _|_| _|_|_| _|_|_|_| _| _|_|_|\n",
91
- " _| _| _| _| _| _| _| _| _| _| _|_| _| _| _| _| _| _| _|\n",
92
- " _| _| _|_| _|_|_| _|_|_| _|_|_| _| _| _|_|_| _| _| _| _|_|_| _|_|_|_|\n",
93
- "\n",
94
- " A token is already saved on your machine. Run `huggingface-cli whoami` to get more information or `huggingface-cli logout` if you want to log out.\n",
95
- " Setting a new token will erase the existing one.\n",
96
- " To log in, `huggingface_hub` requires a token generated from https://huggingface.co/settings/tokens .\n",
97
- "Enter your token (input will not be visible): Traceback (most recent call last):\n",
98
- " File \"/opt/miniconda3/envs/demo/bin/huggingface-cli\", line 8, in <module>\n",
99
- " sys.exit(main())\n",
100
- " File \"/opt/miniconda3/envs/demo/lib/python3.10/site-packages/huggingface_hub/commands/huggingface_cli.py\", line 59, in main\n",
101
- " service.run()\n",
102
- " File \"/opt/miniconda3/envs/demo/lib/python3.10/site-packages/huggingface_hub/commands/user.py\", line 111, in run\n",
103
- " login(\n",
104
- " File \"/opt/miniconda3/envs/demo/lib/python3.10/site-packages/huggingface_hub/utils/_deprecation.py\", line 101, in inner_f\n",
105
- " return f(*args, **kwargs)\n",
106
- " File \"/opt/miniconda3/envs/demo/lib/python3.10/site-packages/huggingface_hub/utils/_deprecation.py\", line 31, in inner_f\n",
107
- " return f(*args, **kwargs)\n",
108
- " File \"/opt/miniconda3/envs/demo/lib/python3.10/site-packages/huggingface_hub/_login.py\", line 130, in login\n",
109
- " interpreter_login(new_session=new_session)\n",
110
- " File \"/opt/miniconda3/envs/demo/lib/python3.10/site-packages/huggingface_hub/utils/_deprecation.py\", line 101, in inner_f\n",
111
- " return f(*args, **kwargs)\n",
112
- " File \"/opt/miniconda3/envs/demo/lib/python3.10/site-packages/huggingface_hub/utils/_deprecation.py\", line 31, in inner_f\n",
113
- " return f(*args, **kwargs)\n",
114
- " File \"/opt/miniconda3/envs/demo/lib/python3.10/site-packages/huggingface_hub/_login.py\", line 287, in interpreter_login\n",
115
- " token = getpass(\"Enter your token (input will not be visible): \")\n",
116
- " File \"/opt/miniconda3/envs/demo/lib/python3.10/getpass.py\", line 77, in unix_getpass\n",
117
- " passwd = _raw_input(prompt, stream, input=input)\n",
118
- " File \"/opt/miniconda3/envs/demo/lib/python3.10/getpass.py\", line 146, in _raw_input\n",
119
- " line = input.readline()\n",
120
- "KeyboardInterrupt\n"
121
- ]
122
- }
123
- ],
124
- "source": [
125
- "\n",
126
- "!huggingface-cli login"
127
- ]
128
- },
129
- {
130
- "cell_type": "code",
131
- "execution_count": 1,
132
- "metadata": {},
133
- "outputs": [],
134
- "source": [
135
- "import os\n",
136
- "from dotenv import load_dotenv\n",
137
- "from langchain_core.prompts import ChatPromptTemplate\n",
138
- "from langchain_ollama.llms import OllamaLLM\n",
139
- "\n",
140
- "\n",
141
- "load_dotenv()\n",
142
- "openai_api_key = os.getenv(\"OPENAI_API_KEY\")\n",
143
- "\n",
144
- "\n",
145
- "if not openai_api_key:\n",
146
- " raise ValueError(\"OPENAI_API_KEY not found in .env file.\")\n",
147
- "\n",
148
- "\n",
149
- "llm = OllamaLLM(\n",
150
- " model='llama3.2:1b'\n",
151
- " )\n",
152
- "\n",
153
- "\n",
154
- "default_prompt = \"\"\"\n",
155
- "Rewrite the following text passage to reflect the writing style of \n",
156
- "a non-native English speaker who has achieved a band level 6 in IELTS writing. \n",
157
- "This level indicates a competent user of English, but with some inaccuracies, \n",
158
- "inappropriate usage, and misunderstandings. \n",
159
- "The text should be mostly clear but may contain occasional errors in grammar, vocabulary, and coherence.\n",
160
- "\n",
161
- "# Text Passage for Rewriting: {input_text}\n",
162
- "\n",
163
- "Note: Aim for errors that are typical of an IELTS band level 6 writer. \n",
164
- "These could include minor grammatical mistakes, slight misuse of vocabulary, \n",
165
- "and occasional awkward phrasing. However, the overall meaning of the text \n",
166
- "should remain clear and understandable.\n",
167
- "\n",
168
- "# Word Count: approximately 400#\n",
169
- "\n",
170
- "In your answer please avoid the text like 'Here is a rewritten version of the ...'\n",
171
- "\n",
172
- "Humanized Version:\n",
173
- "\"\"\"\n",
174
- "\n",
175
- "\n",
176
- "text = \"\"\"In contemporary research, fractal geometry plays an essential role in fields ranging from physics and computer graphics to finance and medicine. For instance, fractal-based algorithms improve image compression, texture synthesis, and pattern recognition. In medicine, fractal analysis assists in characterizing irregular heartbeats or tumor growth patterns. The interplay between fractal geometry and other branches of mathematics, such as measure theory, probability, and number theory, continues to be an active and fruitful area of study.\"\"\"\n",
177
- "\n",
178
- "\n",
179
- "# prompt = ChatPromptTemplate.from_template(template=default_prompt)\n",
180
- "\n",
181
- "# humanizer_chain = prompt | llm\n",
182
- "# response = humanizer_chain.invoke({\"input_text\": text})\n",
183
- "# response"
184
- ]
185
- },
186
- {
187
- "cell_type": "code",
188
- "execution_count": 2,
189
- "metadata": {},
190
- "outputs": [],
191
- "source": []
192
- },
193
- {
194
- "cell_type": "code",
195
- "execution_count": 3,
196
- "metadata": {},
197
- "outputs": [],
198
- "source": [
199
- "text = \"\"\"In contemporary research, fractal geometry plays an essential role in fields ranging from physics and computer graphics to finance and medicine. For instance, fractal-based algorithms improve image compression, texture synthesis, and pattern recognition. In medicine, fractal analysis assists in characterizing irregular heartbeats or tumor growth patterns. The interplay between fractal geometry and other branches of mathematics, such as measure theory, probability, and number theory, continues to be an active and fruitful area of study.\"\"\"\n"
200
- ]
201
- },
202
- {
203
- "cell_type": "code",
204
- "execution_count": 2,
205
- "metadata": {},
206
- "outputs": [],
207
- "source": [
208
- "# prompt = ChatPromptTemplate.from_template(template=default_prompt)\n",
209
- "\n",
210
- "# humanizer_chain = prompt | llm\n",
211
- "# response = humanizer_chain.invoke({\"input_text\": text})\n",
212
- "# response"
213
- ]
214
- },
215
- {
216
- "cell_type": "code",
217
- "execution_count": null,
218
- "metadata": {},
219
- "outputs": [],
220
- "source": []
221
- },
222
- {
223
- "cell_type": "code",
224
- "execution_count": null,
225
- "metadata": {},
226
- "outputs": [],
227
- "source": []
228
- },
229
- {
230
- "cell_type": "markdown",
231
- "metadata": {},
232
- "source": [
233
- "### AI Detector Tools API"
234
- ]
235
- },
236
- {
237
- "cell_type": "code",
238
- "execution_count": 4,
239
- "metadata": {},
240
- "outputs": [],
241
- "source": [
242
- "import requests\n",
243
- "\n",
244
- "headers = {\"Authorization\": \"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNTI4MzIyNDQtODdjZC00MjgzLWFlNzMtMzVkMGQ5ZmRjNTBkIiwidHlwZSI6ImFwaV90b2tlbiJ9.rjpyEn6SdWpLcIMop2zQPhD8epHQmqBD1p73qN_pA8o\"}\n",
245
- "\n",
246
- "url = \"https://api.edenai.run/v2/text/ai_detection\"\n",
247
- "payload = {\n",
248
- " \"providers\": \"winstonai\",\n",
249
- " \"text\": text,\n",
250
- "}\n",
251
- "\n",
252
- "response = requests.post(url, json=payload, headers=headers)\n",
253
- "\n",
254
- "result = response.json()\n",
255
- "# print(result['winstonai'])\n"
256
- ]
257
- },
258
- {
259
- "cell_type": "code",
260
- "execution_count": 6,
261
- "metadata": {},
262
- "outputs": [
263
- {
264
- "data": {
265
- "text/plain": [
266
- "{'No more credits': 'Your account does not have enough credits to perform this operation. Please purchase additional credits or add a credit card to receive $10 in free credits.'}"
267
- ]
268
- },
269
- "execution_count": 6,
270
- "metadata": {},
271
- "output_type": "execute_result"
272
- }
273
- ],
274
- "source": [
275
- "result\n"
276
- ]
277
- },
278
- {
279
- "cell_type": "code",
280
- "execution_count": null,
281
- "metadata": {},
282
- "outputs": [],
283
- "source": []
284
- }
285
- ],
286
- "metadata": {
287
- "kernelspec": {
288
- "display_name": "demo",
289
- "language": "python",
290
- "name": "python3"
291
- },
292
- "language_info": {
293
- "codemirror_mode": {
294
- "name": "ipython",
295
- "version": 3
296
- },
297
- "file_extension": ".py",
298
- "mimetype": "text/x-python",
299
- "name": "python",
300
- "nbconvert_exporter": "python",
301
- "pygments_lexer": "ipython3",
302
- "version": "3.10.13"
303
- }
304
- },
305
- "nbformat": 4,
306
- "nbformat_minor": 2
307
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
main.py CHANGED
@@ -1,19 +1,156 @@
1
- from fastapi import FastAPI
2
- from app.api.endpoints import router
 
 
3
  from fastapi.staticfiles import StaticFiles
4
- from fastapi.responses import HTMLResponse, RedirectResponse
 
 
5
 
6
- import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  app = FastAPI(
10
  title="Text Humanizer",
11
- description="Преобразует текст в более естественный человеческий вариант"
12
  )
13
 
14
- app.include_router(router)
15
  app.mount("/static", StaticFiles(directory="app/static", html=True), name="static")
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  @app.get("/")
18
  async def root():
19
- return RedirectResponse(url="/static")
 
 
 
 
 
1
+ import os
2
+ from typing import List, Optional
3
+
4
+ from fastapi import FastAPI, APIRouter, HTTPException
5
  from fastapi.staticfiles import StaticFiles
6
+ from fastapi.responses import RedirectResponse
7
+ from pydantic import BaseModel
8
+ from dotenv import load_dotenv
9
 
10
+ # LangChain imports
11
+ from langchain_core.prompts import ChatPromptTemplate
12
+ from langchain_openai import ChatOpenAI
13
+
14
+
15
+ from scripts.classifier import debert_classifier
16
+
17
+
18
+ # ---------------------------
19
+ # Environment setup
20
+ # ---------------------------
21
+ load_dotenv()
22
+ openai_api_key = os.getenv("OPENAI_API_KEY")
23
+
24
+ if not openai_api_key:
25
+ raise ValueError("OPENAI_API_KEY not found in .env file.")
26
+
27
+
28
+ # ---------------------------
29
+ # Prompt + LangChain model
30
+ # ---------------------------
31
+ DEFAULT_PROMPT = """
32
+ Rewrite the following text in the style of a non-native English speaker with an **IELTS Band 6** writing level.
33
 
34
+ The rewritten text should maintain the original meaning clearly, but **include some natural grammatical mistakes,
35
+ occasional vocabulary misuse, and slightly awkward phrasing** typical of an IELTS Band 6 writer.
36
+
37
+ Make sure the tone remains human-like and genuine, with a readable flow, and not too polished or “perfect.”
38
+
39
+ This style should be applied **regardless of the content type** (academic, casual, technical, marketing, etc.),
40
+ so preserve the original tone and context while infusing the non-native characteristics.
41
+
42
+ The goal is to **make the text sound human-written (with minor errors)** to reduce the likelihood of
43
+ AI detection by tools like GPTZero or Originality.ai.
44
+
45
+ **Instructions:** Provide **only** the rewritten passage as the output, with no explanations or extra commentary.
46
+
47
+ Aim for roughly **400 words** in the rewritten version (adjusting length as needed to stay proportional to the input).
48
+
49
+ **Text to rewrite:**
50
+
51
+ {input_text}
52
+ """
53
+
54
+ llm = ChatOpenAI(
55
+ model="gpt-4o",
56
+ temperature=0.1,
57
+ top_p=0.9,
58
+ frequency_penalty=0.5,
59
+ presence_penalty=0.3,
60
+ api_key=openai_api_key,
61
+ )
62
 
63
+ def humanize_text(text: str) -> str:
64
+ """Generate a humanized version of input text using LangChain + ChatOpenAI."""
65
+ prompt = ChatPromptTemplate.from_template(template=DEFAULT_PROMPT)
66
+ chain = prompt | llm
67
+ response = chain.invoke({"input_text": text})
68
+ return response.content
69
+
70
+
71
+ # ---------------------------
72
+ # AI Detector (fallback)
73
+ # ---------------------------
74
+ def _detect_ai_fallback(text: str):
75
+ deberta_result = debert_classifier(text)
76
+
77
+ return [
78
+ {"detector_name": "Deberta Model", "ai_probability": deberta_result},
79
+ # {"detector_name": "Originality.ai", "ai_probability": 0.65},
80
+ # {"detector_name": "AI Content Det.", "ai_probability": 0.58},
81
+ ]
82
+
83
+ def run_detectors(text: str):
84
+ try:
85
+ import app.chains.detectors as detectors
86
+ return detectors.detect_ai(text)
87
+ except Exception:
88
+ return _detect_ai_fallback(text)
89
+
90
+
91
+ # ---------------------------
92
+ # FastAPI App
93
+ # ---------------------------
94
  app = FastAPI(
95
  title="Text Humanizer",
96
+ description="Converts AI-like text into a more human-sounding style using OpenAI API via LangChain",
97
  )
98
 
 
99
  app.mount("/static", StaticFiles(directory="app/static", html=True), name="static")
100
 
101
+ class HumanizeInput(BaseModel):
102
+ text: str
103
+
104
+ class DetectInput(BaseModel):
105
+ text: str
106
+
107
+ class DetectorResult(BaseModel):
108
+ detector_name: str
109
+ ai_probability: float
110
+
111
+ class DetectionResponse(BaseModel):
112
+ results: List[DetectorResult]
113
+
114
+ router = APIRouter()
115
+
116
+ @router.post("/humanize")
117
+ async def humanize_text_endpoint(input_data: HumanizeInput):
118
+ try:
119
+ humanized = humanize_text(input_data.text)
120
+ return {"original": input_data.text, "humanized": humanized}
121
+ except Exception as e:
122
+ raise HTTPException(status_code=500, detail=str(e))
123
+
124
+ @router.post("/detect", response_model=DetectionResponse)
125
+ async def detect_ai_endpoint(input_data: DetectInput):
126
+ try:
127
+ raw = run_detectors(input_data.text)
128
+ out: List[DetectorResult] = []
129
+ if isinstance(raw, list):
130
+ for item in raw:
131
+ if isinstance(item, dict):
132
+ name = item.get("detector_name") or "Detector"
133
+ prob = item.get("ai_probability") or 0.0
134
+ out.append(DetectorResult(detector_name=name, ai_probability=prob))
135
+ elif isinstance(raw, dict):
136
+ for k, v in raw.items():
137
+ out.append(DetectorResult(detector_name=str(k), ai_probability=float(v)))
138
+ if not out:
139
+ out = [DetectorResult(detector_name="Default Detector", ai_probability=0.5)]
140
+ return DetectionResponse(results=out)
141
+ except Exception as e:
142
+ raise HTTPException(status_code=500, detail=f"Detection failed: {e}")
143
+
144
+ @router.get("/get_models")
145
+ async def get_models():
146
+ return {"models": ["gpt-4o"]}
147
+
148
+ app.include_router(router)
149
+
150
  @app.get("/")
151
  async def root():
152
+ return RedirectResponse(url="/static")
153
+
154
+ if __name__ == "__main__":
155
+ import uvicorn
156
+ uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
scripts/__pycache__/classifier.cpython-310.pyc ADDED
Binary file (299 Bytes). View file
 
scripts/classifier.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+
2
+ def debert_classifier(text):
3
+ # ....
4
+ return 0.7
scripts/test.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ from main import humanize_text
2
+
3
+ text = """
4
+ Hello my name is Aiken and I am currently working as a data scientist in company
5
+ """
6
+
7
+
8
+ print(humanize_text(text))