satishsnv commited on
Commit
01a84b4
Β·
1 Parent(s): 86c10ae

first commit

Browse files
Files changed (9) hide show
  1. .gitignore +66 -0
  2. DEPLOY.md +47 -0
  3. Dockerfile +24 -0
  4. README.md +202 -11
  5. README_HF.md +124 -0
  6. app.py +239 -0
  7. main.py +0 -0
  8. requirements.txt +6 -0
  9. test.py +73 -0
.gitignore ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ MANIFEST
23
+
24
+ # Virtual environments
25
+ .env
26
+ .venv
27
+ env/
28
+ venv/
29
+ ENV/
30
+ env.bak/
31
+ venv.bak/
32
+
33
+ # IDE
34
+ .vscode/
35
+ .idea/
36
+ *.swp
37
+ *.swo
38
+ *~
39
+
40
+ # OS
41
+ .DS_Store
42
+ .DS_Store?
43
+ ._*
44
+ .Spotlight-V100
45
+ .Trashes
46
+ ehthumbs.db
47
+ Thumbs.db
48
+
49
+ # Logs
50
+ *.log
51
+ logs/
52
+
53
+ # Local development
54
+ .env.local
55
+ .env.development
56
+ .env.test
57
+ .env.production
58
+
59
+ # Test coverage
60
+ htmlcov/
61
+ .coverage
62
+ .coverage.*
63
+ coverage.xml
64
+ *.cover
65
+ .hypothesis/
66
+ .pytest_cache/
DEPLOY.md ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # πŸš€ Quick Deployment to Hugging Face Spaces
2
+
3
+ ## Files for Deployment
4
+
5
+ Upload these 4 files to your Hugging Face Space:
6
+
7
+ ```
8
+ πŸ“ Your Hugging Face Space Repository
9
+ β”œβ”€β”€ πŸ“„ app.py # Main FastAPI application
10
+ β”œβ”€β”€ πŸ“„ Dockerfile # Container configuration
11
+ β”œβ”€β”€ πŸ“„ README.md # Space description (rename README_HF.md)
12
+ β”œβ”€β”€ πŸ“„ requirements.txt # Python dependencies
13
+ └── πŸ“„ test.py # Test script (optional)
14
+ ```
15
+
16
+ ## Deployment Steps
17
+
18
+ ### 1. Create Hugging Face Space
19
+ - Go to [huggingface.co/spaces](https://huggingface.co/spaces)
20
+ - Click "Create new Space"
21
+ - Choose **SDK: Docker**
22
+ - Set your space name
23
+
24
+ ### 2. Upload Files
25
+ - Upload: `app.py`, `Dockerfile`, `requirements.txt`
26
+ - **Rename** `README_HF.md` to `README.md` and upload
27
+ - Optionally upload `test.py`
28
+
29
+ ### 3. Deploy
30
+ - Hugging Face automatically builds and deploys
31
+ - Your API will be available at: `https://your-space-name.hf.space`
32
+
33
+ ## Testing
34
+
35
+ 1. Update `test.py` with your Space URL
36
+ 2. Set environment variable: `export OPENAI_API_KEY="your_key"`
37
+ 3. Run: `python test.py`
38
+
39
+ ## Your API Endpoints
40
+
41
+ - **Base**: `https://your-space-name.hf.space`
42
+ - **Health**: `GET /health`
43
+ - **Address Detection**: `POST /address-detection`
44
+ - **Summarization**: `POST /summarize`
45
+ - **Docs**: `GET /docs`
46
+
47
+ That's it! πŸŽ‰
Dockerfile ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.12-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # Install system dependencies
6
+ RUN apt-get update && apt-get install -y \
7
+ build-essential \
8
+ curl \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ # Copy requirements first for better caching
12
+ COPY requirements.txt .
13
+
14
+ # Install Python dependencies
15
+ RUN pip install --no-cache-dir -r requirements.txt
16
+
17
+ # Copy application code
18
+ COPY . .
19
+
20
+ # Expose port
21
+ EXPOSE 7860
22
+
23
+ # Command to run the application
24
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,11 +1,202 @@
1
- ---
2
- title: Content Processor
3
- emoji: 😻
4
- colorFrom: green
5
- colorTo: green
6
- sdk: docker
7
- pinned: false
8
- short_description: fast api service that do address detection & summarization
9
- ---
10
-
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Address Detection and Summarization API
2
+
3
+ A FastAPI application that provides two main endpoints for address detection and text summarization with sentiment analysis using OpenAI's GPT models.
4
+
5
+ ## Features
6
+
7
+ - **Address Detection**: Extracts addresses from text content
8
+ - **Text Summarization**: Generates summaries with sentiment analysis
9
+ - **OpenAI Integration**: Uses GPT-3.5-turbo for natural language processing
10
+ - **Header-based Authentication**: OpenAI API key passed via `x-api-key` header
11
+ - **RESTful API**: Clean and simple API endpoints
12
+
13
+ ## Installation
14
+
15
+ 1. **Clone or navigate to the project directory**
16
+ ```bash
17
+ cd /mnt/BA1E86C91E867DDF/ubuntu_folder/python/fastapi/dummy_add-det_summ_ser
18
+ ```
19
+
20
+ 2. **Create and activate virtual environment** (if not already done)
21
+ ```bash
22
+ python -m venv .venv
23
+ source .venv/bin/activate # On Linux/Mac
24
+ ```
25
+
26
+ 3. **Install dependencies**
27
+ ```bash
28
+ pip install -r requirements.txt
29
+ ```
30
+
31
+ ## Configuration
32
+
33
+ **Important**: This API requires the OpenAI API key to be passed in the `x-api-key` request header, not as environment variables.
34
+
35
+ ## Running the Application
36
+
37
+ Start the FastAPI server:
38
+
39
+ ```bash
40
+ python main.py
41
+ ```
42
+
43
+ Or using uvicorn directly:
44
+
45
+ ```bash
46
+ uvicorn main:app --host 0.0.0.0 --port 8500 --reload
47
+ ```
48
+
49
+ The API will be available at: http://localhost:8500
50
+
51
+ ## API Documentation
52
+
53
+ Once running, visit:
54
+ - Interactive API docs: http://localhost:8500/docs
55
+ - ReDoc documentation: http://localhost:8500/redoc
56
+
57
+ ## API Endpoints
58
+
59
+ ### 1. Address Detection
60
+
61
+ **POST** `/address-detection`
62
+
63
+ Detects and extracts addresses from the provided text content.
64
+
65
+ **Headers:**
66
+ ```
67
+ Content-Type: application/json
68
+ x-api-key: your_openai_api_key_here
69
+ ```
70
+
71
+ **Request Body:**
72
+ ```json
73
+ {
74
+ "entity_urn": "string",
75
+ "content": "string"
76
+ }
77
+ ```
78
+
79
+ **Response:**
80
+ ```json
81
+ {
82
+ "message": "success|failure",
83
+ "result": "address1 || address2 || address3",
84
+ "action_type": "detect_address",
85
+ "entity_urn": "string",
86
+ "sentiment": null
87
+ }
88
+ ```
89
+
90
+ **Example:**
91
+ ```bash
92
+ curl -X POST "http://localhost:8500/address-detection" \
93
+ -H "Content-Type: application/json" \
94
+ -H "x-api-key: your_openai_api_key_here" \
95
+ -d '{
96
+ "entity_urn": "test_001",
97
+ "content": "Please send the package to 123 Main Street, New York, NY 10001"
98
+ }'
99
+ ```
100
+
101
+ ### 2. Text Summarization
102
+
103
+ **POST** `/summarize`
104
+
105
+ Generates a summary of the text content along with sentiment analysis.
106
+
107
+ **Headers:**
108
+ ```
109
+ Content-Type: application/json
110
+ x-api-key: your_openai_api_key_here
111
+ ```
112
+
113
+ **Request Body:**
114
+ ```json
115
+ {
116
+ "entity_urn": "string",
117
+ "content": "string"
118
+ }
119
+ ```
120
+
121
+ **Response:**
122
+ ```json
123
+ {
124
+ "message": "success|failure",
125
+ "result": "summary text",
126
+ "action_type": "summarize",
127
+ "entity_urn": "string",
128
+ "sentiment": {
129
+ "label": "positive|negative",
130
+ "score": -1.0 to 1.0
131
+ }
132
+ }
133
+ ```
134
+
135
+ **Example:**
136
+ ```bash
137
+ curl -X POST "http://localhost:8500/summarize" \
138
+ -H "Content-Type: application/json" \
139
+ -H "x-api-key: your_openai_api_key_here" \
140
+ -d '{
141
+ "entity_urn": "test_002",
142
+ "content": "I love this product! It exceeded my expectations..."
143
+ }'
144
+ ```
145
+
146
+ ## Testing
147
+
148
+ Before running tests, make sure to set your OpenAI API key as an environment variable:
149
+
150
+ ```bash
151
+ export OPENAI_API_KEY="your_openai_api_key_here"
152
+ ```
153
+
154
+ Then run the test script to verify the endpoints:
155
+
156
+ ```bash
157
+ python test_api.py
158
+ ```
159
+
160
+ Make sure the server is running before executing the tests.
161
+
162
+ The test script will also test error handling by making requests without the API key header.
163
+
164
+ ## Project Structure
165
+
166
+ ```
167
+ dummy_add-det_summ_ser/
168
+ β”œβ”€β”€ main.py # Main FastAPI application
169
+ β”œβ”€β”€ test_api.py # Test script for API endpoints
170
+ β”œβ”€β”€ requirements.txt # Python dependencies
171
+ β”œβ”€β”€ .env.example # Environment variables template
172
+ β”œβ”€β”€ .venv/ # Virtual environment
173
+ └── README.md # This file
174
+ ```
175
+
176
+ ## Dependencies
177
+
178
+ - **FastAPI**: Web framework for building APIs (v0.115.14)
179
+ - **Uvicorn**: ASGI server for running FastAPI (v0.34.3)
180
+ - **Pydantic**: Data validation using Python type annotations (v2.11.7)
181
+ - **OpenAI**: Official OpenAI Python client (v1.92.1)
182
+ - **python-dotenv**: Load environment variables from .env file (v1.1.1)
183
+ - **httpx**: Modern HTTP client library for testing (v0.28.1)
184
+
185
+ ## Error Handling
186
+
187
+ The API includes comprehensive error handling:
188
+ - **Missing API Key**: Returns 422 error if `x-api-key` header is not provided
189
+ - **Invalid API Key**: Returns 500 error if the OpenAI API key is invalid
190
+ - **OpenAI API connection failures**: Returns 500 error with descriptive message
191
+ - **Empty content validation**: Returns failure response with appropriate message
192
+ - **Malformed requests**: Returns 422 error for validation issues
193
+
194
+ All errors return appropriate HTTP status codes and descriptive error messages.
195
+
196
+ ## Notes
197
+
198
+ - **API Key Security**: The OpenAI API key must be passed in the `x-api-key` header for each request
199
+ - The API uses GPT-3.5-turbo model by default
200
+ - Sentiment scores range from -1.0 (most negative) to 1.0 (most positive)
201
+ - Address detection returns addresses concatenated with ' || ' separator
202
+ - The `entity_urn` field is used instead of `entity_id` for better naming convention
README_HF.md ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Address Detection and Summarization API
3
+ emoji: πŸ πŸ“
4
+ colorFrom: blue
5
+ colorTo: green
6
+ sdk: docker
7
+ pinned: false
8
+ license: mit
9
+ ---
10
+
11
+ # Address Detection and Summarization API
12
+
13
+ A FastAPI service that provides two main endpoints for AI-powered text processing:
14
+
15
+ ## πŸš€ Features
16
+
17
+ - 🏠 **Address Detection**: Extracts and formats addresses from unstructured text
18
+ - πŸ“ **Text Summarization**: Creates concise summaries with sentiment analysis
19
+ - πŸ€– **OpenAI Integration**: Uses GPT-4 for natural language processing
20
+ - πŸ” **Secure**: API key required via `x-api-key` header
21
+ - πŸ“Š **Sentiment Analysis**: Returns sentiment label and score (-1.0 to 1.0)
22
+
23
+ ## πŸ“‹ API Endpoints
24
+
25
+ ### Root & Health
26
+ - `GET /` - API information
27
+ - `GET /health` - Health check
28
+ - `GET /docs` - Interactive API documentation
29
+
30
+ ### Address Detection
31
+ `POST /address-detection`
32
+
33
+ Extract addresses from text content.
34
+
35
+ **Request:**
36
+ ```json
37
+ {
38
+ "entity_urn": "unique_id",
39
+ "content": "Please send to 123 Main Street, New York, NY 10001"
40
+ }
41
+ ```
42
+
43
+ **Headers:**
44
+ ```
45
+ Content-Type: application/json
46
+ x-api-key: your_openai_api_key
47
+ ```
48
+
49
+ ### Text Summarization
50
+ `POST /summarize`
51
+
52
+ Generate summary with sentiment analysis.
53
+
54
+ **Request:**
55
+ ```json
56
+ {
57
+ "entity_urn": "unique_id",
58
+ "content": "Your text content to summarize..."
59
+ }
60
+ ```
61
+
62
+ ## πŸ”§ Usage Examples
63
+
64
+ ### Using curl:
65
+
66
+ ```bash
67
+ # Address Detection
68
+ curl -X POST "https://your-space-name.hf.space/address-detection" \
69
+ -H "Content-Type: application/json" \
70
+ -H "x-api-key: your_openai_api_key" \
71
+ -d '{"entity_urn": "test", "content": "Send to 123 Main St, NYC"}'
72
+
73
+ # Summarization
74
+ curl -X POST "https://your-space-name.hf.space/summarize" \
75
+ -H "Content-Type: application/json" \
76
+ -H "x-api-key: your_openai_api_key" \
77
+ -d '{"entity_urn": "test", "content": "I love this product!"}'
78
+ ```
79
+
80
+ ### Response Format:
81
+
82
+ ```json
83
+ {
84
+ "message": "success",
85
+ "result": "extracted_addresses || separated",
86
+ "action_type": "detect_address",
87
+ "entity_urn": "test",
88
+ "sentiment": null
89
+ }
90
+ ```
91
+
92
+ For summarization, `sentiment` contains:
93
+ ```json
94
+ {
95
+ "label": "positive",
96
+ "score": 0.8
97
+ }
98
+ ```
99
+
100
+ ## πŸ”‘ Authentication
101
+
102
+ You need an OpenAI API key to use this service:
103
+
104
+ 1. Get your API key from [OpenAI Platform](https://platform.openai.com/)
105
+ 2. Include it in the `x-api-key` header with each request
106
+ 3. No registration required - just use your own key
107
+
108
+ ## πŸ—οΈ Built With
109
+
110
+ - **FastAPI** 0.115.14 - Modern web framework
111
+ - **OpenAI** 1.92.1 - AI language models
112
+ - **Pydantic** 2.11.7 - Data validation
113
+ - **Python** 3.12 - Runtime
114
+
115
+ ## πŸ“– Documentation
116
+
117
+ Visit `/docs` for interactive API documentation with request/response examples and testing interface.
118
+
119
+ ## πŸ”’ Security & Privacy
120
+
121
+ - Your OpenAI API key is required for each request
122
+ - No API keys are stored on our servers
123
+ - All requests are processed in real-time
124
+ - No conversation history is retained
app.py ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Address Detection and Summarization API for Hugging Face Spaces
4
+ """
5
+
6
+ from fastapi import FastAPI, HTTPException, Header
7
+ from fastapi.middleware.cors import CORSMiddleware
8
+ from pydantic import BaseModel, Field
9
+ from openai import OpenAI
10
+ import os
11
+ from enum import Enum
12
+ from typing import Dict, Optional, Annotated
13
+ import logging
14
+ from dotenv import load_dotenv
15
+
16
+ # Load environment variables
17
+ load_dotenv()
18
+
19
+ # Configure logging
20
+ logging.basicConfig(level=logging.INFO)
21
+ logger = logging.getLogger(__name__)
22
+
23
+ app = FastAPI(title="Address Detection and Summarization API")
24
+
25
+ # Add CORS middleware for Hugging Face Spaces
26
+ app.add_middleware(
27
+ CORSMiddleware,
28
+ allow_origins=["*"],
29
+ allow_credentials=True,
30
+ allow_methods=["*"],
31
+ allow_headers=["*"],
32
+ )
33
+
34
+ class Actions(Enum):
35
+ DETECT_ADDRESS = "detect_address"
36
+ SUMMARIZE = "summarize"
37
+
38
+ # Request model
39
+ class RequestModel(BaseModel):
40
+ entity_urn: str = Field(..., description="Unique identifier for the entity")
41
+ content: str = Field(..., description="Content to be processed")
42
+
43
+ # Response models
44
+ class ResponseModel(BaseModel):
45
+ message: str = Field(description="Result of the operation, e.g., 'success' or 'failure'")
46
+ result: str = Field(description="summary in case of summarization, or || separated addresses in case of address detection")
47
+ action_type: Actions = Field(..., description="Type of action performed")
48
+ entity_urn: str = Field(..., description="Unique identifier for the entity")
49
+ sentiment: Optional[Dict] = Field(default=None, description="Sentiment analysis result")
50
+
51
+ def get_openai_client(api_key: str) -> OpenAI:
52
+ """Create OpenAI client with provided API key"""
53
+ if not api_key:
54
+ raise HTTPException(status_code=400, detail="x-api-key header is required")
55
+ return OpenAI(api_key=api_key)
56
+
57
+ def get_openai_response(api_key: str, prompt: str, max_tokens: int = 10000) -> str:
58
+ """Get response from OpenAI API"""
59
+ try:
60
+ client = get_openai_client(api_key)
61
+ response = client.chat.completions.create(
62
+ model="gpt-4o",
63
+ messages=[{"role": "user", "content": prompt}],
64
+ max_tokens=max_tokens,
65
+ temperature=0.3
66
+ )
67
+ return response.choices[0].message.content.strip()
68
+ except Exception as e:
69
+ logger.error(f"OpenAI API error: {str(e)}")
70
+ raise HTTPException(status_code=500, detail=f"Failed to connect to OpenAI: {str(e)}")
71
+
72
+ def detect_addresses(api_key: str, content: str) -> str:
73
+ """Detect addresses from content using OpenAI"""
74
+ prompt = f"""
75
+ Extract all addresses from the following text. Return only the addresses, separated by ' || '.
76
+ If no addresses are found, return empty string.
77
+
78
+ Text: {content}
79
+
80
+ Addresses:
81
+ """
82
+
83
+ try:
84
+ addresses = get_openai_response(api_key, prompt)
85
+ return addresses if addresses else ""
86
+ except Exception as e:
87
+ logger.error(f"Address detection error: {str(e)}")
88
+ return "Error detecting addresses"
89
+
90
+ def summarize_and_analyze_sentiment(api_key: str, content: str) -> tuple:
91
+ """Summarize content and analyze sentiment using OpenAI"""
92
+ prompt = f"""
93
+ Please provide:
94
+ 1. A concise summary of the following text
95
+ 2. Sentiment analysis with label (POSITIVE/NEGATIVE) and score (-1.0 to 1.0)
96
+ 3. Ensure the summary is clear and captures the main points
97
+ Format your response as:
98
+ SUMMARY: [your summary here]
99
+ SENTIMENT_LABEL: [POSITIVE or NEGATIVE]
100
+ SENTIMENT_SCORE: [score between -1.0 and 1.0]
101
+
102
+ Text: {content}
103
+ """
104
+
105
+ try:
106
+ response = get_openai_response(api_key, prompt)
107
+
108
+ # Parse the response
109
+ summary = ""
110
+ sentiment_label = "neutral"
111
+ sentiment_score = 0.0
112
+
113
+ lines = response.split('\n')
114
+ for line in lines:
115
+ if line.startswith('SUMMARY:'):
116
+ summary = line.replace('SUMMARY:', '').strip()
117
+ elif line.startswith('SENTIMENT_LABEL:'):
118
+ sentiment_label = line.replace('SENTIMENT_LABEL:', '').strip().lower()
119
+ elif line.startswith('SENTIMENT_SCORE:'):
120
+ try:
121
+ sentiment_score = float(line.replace('SENTIMENT_SCORE:', '').strip())
122
+ # Ensure score is within range
123
+ sentiment_score = max(-1.0, min(1.0, sentiment_score))
124
+ except ValueError:
125
+ sentiment_score = 0.0
126
+
127
+ # Ensure valid sentiment label
128
+ if sentiment_label not in ['positive', 'negative']:
129
+ sentiment_label = 'positive' if sentiment_score > 0 else 'negative'
130
+
131
+ return summary, {"label": sentiment_label, "score": sentiment_score}
132
+
133
+ except Exception as e:
134
+ logger.error(f"Summarization error: {str(e)}")
135
+ return "Error generating summary", {"label": "neutral", "score": 0.0}
136
+
137
+ @app.get("/")
138
+ async def root():
139
+ return {
140
+ "message": "Address Detection and Summarization API",
141
+ "version": "1.0.0",
142
+ "status": "healthy",
143
+ "endpoints": {
144
+ "address_detection": "/address-detection",
145
+ "summarization": "/summarize",
146
+ "health": "/health",
147
+ "docs": "/docs"
148
+ }
149
+ }
150
+
151
+ @app.get("/health")
152
+ async def health_check():
153
+ return {
154
+ "status": "healthy",
155
+ "service": "Address Detection and Summarization API",
156
+ "version": "1.0.0"
157
+ }
158
+
159
+ @app.post("/address-detection", response_model=ResponseModel)
160
+ async def address_detection(
161
+ request: RequestModel,
162
+ openai_api_key: Annotated[str, Header(alias="x-api-key")]
163
+ ):
164
+ """Endpoint for address detection"""
165
+ try:
166
+ logger.info(f"Processing address detection for entity_urn: {request.entity_urn}")
167
+
168
+ if not request.content.strip():
169
+ return ResponseModel(
170
+ message="failure",
171
+ result="Content is empty",
172
+ action_type=Actions.DETECT_ADDRESS,
173
+ entity_urn=request.entity_urn,
174
+ sentiment=None
175
+ )
176
+
177
+ addresses = detect_addresses(openai_api_key, request.content)
178
+
179
+ return ResponseModel(
180
+ message="success",
181
+ result=addresses,
182
+ action_type=Actions.DETECT_ADDRESS,
183
+ entity_urn=request.entity_urn,
184
+ sentiment=None
185
+ )
186
+
187
+ except Exception as e:
188
+ logger.error(f"Address detection endpoint error: {str(e)}")
189
+ return ResponseModel(
190
+ message="failure",
191
+ result=f"Error: {str(e)}",
192
+ action_type=Actions.DETECT_ADDRESS,
193
+ entity_urn=request.entity_urn,
194
+ sentiment=None
195
+ )
196
+
197
+ @app.post("/summarize", response_model=ResponseModel)
198
+ async def summarize(
199
+ request: RequestModel,
200
+ openai_api_key: Annotated[str, Header(alias="x-api-key")]
201
+ ):
202
+ """Endpoint for text summarization and sentiment analysis"""
203
+ try:
204
+ logger.info(f"Processing summarization for entity_urn: {request.entity_urn}")
205
+
206
+ if not request.content.strip():
207
+ return ResponseModel(
208
+ message="failure",
209
+ result="Content is empty",
210
+ action_type=Actions.SUMMARIZE,
211
+ entity_urn=request.entity_urn,
212
+ sentiment={}
213
+ )
214
+
215
+ summary, sentiment = summarize_and_analyze_sentiment(openai_api_key, request.content)
216
+
217
+ return ResponseModel(
218
+ message="success",
219
+ result=summary,
220
+ sentiment=sentiment,
221
+ action_type=Actions.SUMMARIZE,
222
+ entity_urn=request.entity_urn
223
+ )
224
+
225
+ except Exception as e:
226
+ logger.error(f"Summarization endpoint error: {str(e)}")
227
+ return ResponseModel(
228
+ message="failure",
229
+ result=f"Error: {str(e)}",
230
+ sentiment={},
231
+ action_type=Actions.SUMMARIZE,
232
+ entity_urn=request.entity_urn
233
+ )
234
+
235
+ if __name__ == "__main__":
236
+ import uvicorn
237
+ # Use port 7860 for Hugging Face Spaces, fallback to 8500 for local
238
+ port = int(os.getenv("PORT", 7860))
239
+ uvicorn.run(app, host="0.0.0.0", port=port)
main.py ADDED
File without changes
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ fastapi==0.115.14
2
+ uvicorn[standard]==0.34.3
3
+ pydantic==2.11.7
4
+ openai==1.92.1
5
+ python-dotenv==1.1.1
6
+ httpx==0.28.1
test.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Simple test script for the deployed API
4
+ Update BASE_URL to your Hugging Face Space URL
5
+ """
6
+
7
+ import httpx
8
+ import json
9
+ import os
10
+
11
+ # Update this to your actual Hugging Face Space URL
12
+ BASE_URL = "https://your-space-name.hf.space"
13
+
14
+ def test_api():
15
+ """Test the deployed API"""
16
+
17
+ # Get OpenAI API key from environment
18
+ api_key = os.getenv("OPENAI_API_KEY")
19
+ if not api_key:
20
+ print("❌ Please set OPENAI_API_KEY environment variable")
21
+ print(" export OPENAI_API_KEY='your_actual_key'")
22
+ return
23
+
24
+ headers = {
25
+ "Content-Type": "application/json",
26
+ "x-api-key": api_key
27
+ }
28
+
29
+ print(f"πŸ§ͺ Testing API at: {BASE_URL}")
30
+ print("=" * 50)
31
+
32
+ # Test health endpoint
33
+ try:
34
+ with httpx.Client(timeout=30.0) as client:
35
+ response = client.get(f"{BASE_URL}/health")
36
+ print(f"βœ… Health Check: {response.status_code}")
37
+ print(f" {response.json()}")
38
+ except Exception as e:
39
+ print(f"❌ Health check failed: {e}")
40
+
41
+ # Test address detection
42
+ try:
43
+ with httpx.Client(timeout=30.0) as client:
44
+ data = {
45
+ "entity_urn": "test_001",
46
+ "content": "Send package to 123 Main Street, New York, NY 10001"
47
+ }
48
+ response = client.post(f"{BASE_URL}/address-detection", json=data, headers=headers)
49
+ print(f"βœ… Address Detection: {response.status_code}")
50
+ result = response.json()
51
+ print(f" Addresses: {result.get('result', 'N/A')}")
52
+ except Exception as e:
53
+ print(f"❌ Address detection failed: {e}")
54
+
55
+ # Test summarization
56
+ try:
57
+ with httpx.Client(timeout=30.0) as client:
58
+ data = {
59
+ "entity_urn": "test_002",
60
+ "content": "I love this product! It's amazing and exceeded my expectations."
61
+ }
62
+ response = client.post(f"{BASE_URL}/summarize", json=data, headers=headers)
63
+ print(f"βœ… Summarization: {response.status_code}")
64
+ result = response.json()
65
+ print(f" Summary: {result.get('result', 'N/A')}")
66
+ print(f" Sentiment: {result.get('sentiment', 'N/A')}")
67
+ except Exception as e:
68
+ print(f"❌ Summarization failed: {e}")
69
+
70
+ print(f"\nπŸ“– View docs at: {BASE_URL}/docs")
71
+
72
+ if __name__ == "__main__":
73
+ test_api()