Initial commit
This commit is contained in:
133
.gitignore
vendored
Normal file
133
.gitignore
vendored
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
pip-wheel-metadata/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install different versions of packages depending on
|
||||||
|
# the platform. Pipfile.lock may vary on different platforms. Then you may wish to ignore
|
||||||
|
# Pipfile.lock.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyderworkspace
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# Custom
|
||||||
|
request_logs/
|
||||||
160
README.md
Normal file
160
README.md
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
# 🧪 Mock OpenAI Chat API Server
|
||||||
|
|
||||||
|
This project simulates the OpenAI `/v1/chat/completions` API using a local FastAPI server.
|
||||||
|
It logs all incoming requests and returns a dummy response using `"Lorem Ipsum..."` content for debugging and development purposes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Features
|
||||||
|
|
||||||
|
- Local server that mimics OpenAI ChatCompletion endpoint
|
||||||
|
- Logs full request (headers + body) to `requests_log.json`
|
||||||
|
- Returns a dummy OpenAI-style response
|
||||||
|
- Plug-in replacement for `openai.ChatCompletion.create(...)`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ Requirements
|
||||||
|
|
||||||
|
- Python 3.7+
|
||||||
|
- FastAPI
|
||||||
|
- Uvicorn
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 Installation & Setup
|
||||||
|
|
||||||
|
### 1. Clone or copy this project into a local folder
|
||||||
|
|
||||||
|
### 2. Create and activate a virtual environment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m venv venv
|
||||||
|
```
|
||||||
|
|
||||||
|
Then activate it:
|
||||||
|
|
||||||
|
- **Windows:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
venv\Scripts\activate
|
||||||
|
```
|
||||||
|
|
||||||
|
- **macOS/Linux:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source venv/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Install dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install fastapi uvicorn
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 How to Start the Server
|
||||||
|
|
||||||
|
Use this command to launch the mock API server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m uvicorn mock_openai_server:app --reload --port 8000
|
||||||
|
```
|
||||||
|
|
||||||
|
It will be available at:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://localhost:8000/v1/chat/completions
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 How to Use with OpenAI Python SDK
|
||||||
|
|
||||||
|
Update your client to point to the mock server:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import openai
|
||||||
|
|
||||||
|
openai.api_key = "sk-dummy"
|
||||||
|
openai.api_base = "http://localhost:8000"
|
||||||
|
|
||||||
|
response = openai.ChatCompletion.create(
|
||||||
|
model="gpt-4",
|
||||||
|
messages=[
|
||||||
|
{"role": "user", "content": "Hello!"}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
print(response)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📄 Example Dummy Response
|
||||||
|
|
||||||
|
```text
|
||||||
|
ID: chatcmpl-mock123
|
||||||
|
Model: gpt-4
|
||||||
|
Created: <current timestamp>
|
||||||
|
Role: assistant
|
||||||
|
Message: Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||||
|
Finish reason: stop
|
||||||
|
Tokens used: prompt=10, completion=12, total=22
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Output Logs
|
||||||
|
|
||||||
|
All requests and responses are logged to `requests_log.json`.
|
||||||
|
Each log entry contains:
|
||||||
|
|
||||||
|
- Timestamp
|
||||||
|
- Headers (sent by client)
|
||||||
|
- JSON body (messages, model, etc.)
|
||||||
|
- Dummy response
|
||||||
|
|
||||||
|
You can use this log to debug what your app sends to OpenAI.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📂 Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── mock_openai_server.py # FastAPI mock server
|
||||||
|
├── requests_log.json # Saved request/response logs
|
||||||
|
└── README.md # Documentation
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧰 Optional: Save Installed Packages
|
||||||
|
|
||||||
|
To track your environment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip freeze > requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Later, you can restore it with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📌 Notes
|
||||||
|
|
||||||
|
- No actual API calls are made to OpenAI
|
||||||
|
- Great for debugging payload formats, headers, and SDK integrations
|
||||||
|
- For local development only
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🪪 License
|
||||||
|
|
||||||
|
MIT License
|
||||||
81
mock_openai_server.py
Normal file
81
mock_openai_server.py
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
from fastapi import FastAPI, Request
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
from datetime import datetime
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
LOG_DIR = "request_logs"
|
||||||
|
os.makedirs(LOG_DIR, exist_ok=True)
|
||||||
|
|
||||||
|
def format_markdown_log(headers, body, response):
|
||||||
|
timestamp = datetime.now().isoformat()
|
||||||
|
|
||||||
|
# Extract messages
|
||||||
|
messages = body.get("messages", [])
|
||||||
|
messages_text = "\n".join(
|
||||||
|
f"{m.get('role', 'unknown')}: {m.get('content', '')}" for m in messages
|
||||||
|
)
|
||||||
|
|
||||||
|
log = f"""## 📥 Request - {timestamp}
|
||||||
|
|
||||||
|
**Timestamp:** {timestamp}
|
||||||
|
|
||||||
|
### Headers
|
||||||
|
\```json
|
||||||
|
{json.dumps(headers, indent=4)}
|
||||||
|
\```
|
||||||
|
|
||||||
|
### Message Contents
|
||||||
|
\```text
|
||||||
|
{messages_text or "No messages"}
|
||||||
|
\```
|
||||||
|
|
||||||
|
### Full Body
|
||||||
|
\```json
|
||||||
|
{json.dumps(body, indent=4)}
|
||||||
|
\```
|
||||||
|
|
||||||
|
### 📤 Response
|
||||||
|
\```json
|
||||||
|
{json.dumps(response, indent=4)}
|
||||||
|
\```
|
||||||
|
|
||||||
|
---
|
||||||
|
"""
|
||||||
|
return log
|
||||||
|
|
||||||
|
@app.post("/v1/chat/completions")
|
||||||
|
async def chat_completions(request: Request):
|
||||||
|
headers = dict(request.headers)
|
||||||
|
body = await request.json()
|
||||||
|
|
||||||
|
dummy_response = {
|
||||||
|
"id": "chatcmpl-mock123",
|
||||||
|
"object": "chat.completion",
|
||||||
|
"created": int(datetime.now().timestamp()),
|
||||||
|
"model": body.get("model", "gpt-4"),
|
||||||
|
"choices": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"message": {
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "This is a mock response for testing purposes."
|
||||||
|
},
|
||||||
|
"finish_reason": "stop"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"usage": {
|
||||||
|
"prompt_tokens": 10,
|
||||||
|
"completion_tokens": 12,
|
||||||
|
"total_tokens": 22
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
markdown_log = format_markdown_log(headers, body, dummy_response)
|
||||||
|
timestamp_str = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
|
||||||
|
log_file = os.path.join(LOG_DIR, f"request_{timestamp_str}.md")
|
||||||
|
with open(log_file, "w", encoding="utf-8") as f:
|
||||||
|
f.write(markdown_log)
|
||||||
|
|
||||||
|
return JSONResponse(content=dummy_response)
|
||||||
156
requests_log.md
Normal file
156
requests_log.md
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
## 📥 Request - 2025-07-30T11:24:13.692836
|
||||||
|
|
||||||
|
**Timestamp:** 2025-07-30T11:24:13.692836
|
||||||
|
|
||||||
|
### Headers
|
||||||
|
\```json
|
||||||
|
{
|
||||||
|
"host": "localhost:8000",
|
||||||
|
"api-key": "dddd",
|
||||||
|
"content-type": "application/json; charset=utf-8",
|
||||||
|
"content-length": "1242"
|
||||||
|
}
|
||||||
|
\```
|
||||||
|
|
||||||
|
### Message Contents
|
||||||
|
\```markdown
|
||||||
|
- **system:** You will be provided with COBOL source code.
|
||||||
|
|
||||||
|
Response needs to be in .md format and contain description of the code.
|
||||||
|
|
||||||
|
You need to follow these rules:
|
||||||
|
|
||||||
|
1. Use vocabulary suited for design documentation.
|
||||||
|
|
||||||
|
2. Describe each statement inside the code in numbered list. Be as detailed as possible.
|
||||||
|
|
||||||
|
2.1. Describe each statement in separate numbered line, do not group statements. I really do mean each and every single one. Describe them all, not just some of them. You are allowed to repeat yourself if necessary. DO NOT IMPROVISE.
|
||||||
|
|
||||||
|
2.2. If there are nested statements increase numbering outline for each nested statement.
|
||||||
|
|
||||||
|
3. There should be no text after numerated part is finished.
|
||||||
|
|
||||||
|
|
||||||
|
- **user:** DISPLAY "Please input one upper-case letter. >>" WITH NO ADVANCIN
|
||||||
|
ACCEPT IN-DATA.
|
||||||
|
PERFORM TEST BEFORE
|
||||||
|
VARYING COUNTER FROM 1 BY 1 UNTIL COUNTER > 26
|
||||||
|
IF IN-DATA = ALP(COUNTER:1) THEN
|
||||||
|
EXIT PERFORM
|
||||||
|
END-IF
|
||||||
|
END-PERFORM.
|
||||||
|
IF COUNTER <= 26 THEN
|
||||||
|
DISPLAY IN-DATA " is character " COUNTER " in alphabetical order.
|
||||||
|
|
||||||
|
\```
|
||||||
|
|
||||||
|
### Full Body
|
||||||
|
\```json
|
||||||
|
{
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": "You will be provided with COBOL source code.\r\nResponse needs to be in .md format and contain description of the code.\r\nYou need to follow these rules:\r\n1. Use vocabulary suited for design documentation.\r\n2. Describe each statement inside the code in numbered list. Be as detailed as possible.\r\n2.1. Describe each statement in separate numbered line, do not group statements. I really do mean each and every single one. Describe them all, not just some of them. You are allowed to repeat yourself if necessary. DO NOT IMPROVISE.\r\n2.2. If there are nested statements increase numbering outline for each nested statement.\r\n3. There should be no text after numerated part is finished.\r\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "DISPLAY \"Please input one upper-case letter. >>\" WITH NO ADVANCIN\n ACCEPT IN-DATA.\n PERFORM TEST BEFORE\n VARYING COUNTER FROM 1 BY 1 UNTIL COUNTER > 26\n IF IN-DATA = ALP(COUNTER:1) THEN\n EXIT PERFORM\n END-IF\n END-PERFORM.\n IF COUNTER <= 26 THEN\n DISPLAY IN-DATA \" is character \" COUNTER \" in alphabetical order.\n"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"temperature": 0.01,
|
||||||
|
"top_p": 0.01,
|
||||||
|
"max_tokens": 900
|
||||||
|
}
|
||||||
|
\```
|
||||||
|
|
||||||
|
### 📤 Response
|
||||||
|
\```json
|
||||||
|
{
|
||||||
|
"id": "chatcmpl-mock123",
|
||||||
|
"object": "chat.completion",
|
||||||
|
"created": 1753867453,
|
||||||
|
"model": "gpt-4",
|
||||||
|
"choices": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"message": {
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
|
},
|
||||||
|
"finish_reason": "stop"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"usage": {
|
||||||
|
"prompt_tokens": 10,
|
||||||
|
"completion_tokens": 12,
|
||||||
|
"total_tokens": 22
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\```
|
||||||
|
|
||||||
|
---
|
||||||
|
## 📥 Request - 2025-07-30T11:24:13.716838
|
||||||
|
|
||||||
|
**Timestamp:** 2025-07-30T11:24:13.716838
|
||||||
|
|
||||||
|
### Headers
|
||||||
|
\```json
|
||||||
|
{
|
||||||
|
"host": "localhost:8000",
|
||||||
|
"api-key": "dddd",
|
||||||
|
"content-type": "application/json; charset=utf-8",
|
||||||
|
"content-length": "596"
|
||||||
|
}
|
||||||
|
\```
|
||||||
|
|
||||||
|
### Message Contents
|
||||||
|
\```markdown
|
||||||
|
- **system:** You will be provided with COBOL source code description. This description represents one COBOL procedure division.
|
||||||
|
|
||||||
|
Please provide short summary describing the function of this procedure division. Start description with words "This procedure division".
|
||||||
|
|
||||||
|
Don't describe each paragraph separately, but whole division at once. Be as short as possible.
|
||||||
|
|
||||||
|
|
||||||
|
- **user:**
|
||||||
|
|
||||||
|
## PROCEDURE DIVISION BODY
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\```
|
||||||
|
|
||||||
|
### Full Body
|
||||||
|
\```json
|
||||||
|
{
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": "You will be provided with COBOL source code description. This description represents one COBOL procedure division.\r\nPlease provide short summary describing the function of this procedure division. Start description with words \"This procedure division\".\r\nDon't describe each paragraph separately, but whole division at once. Be as short as possible.\r\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "\r\n## PROCEDURE DIVISION BODY\r\nLorem ipsum dolor sit amet, consectetur adipiscing elit.\r\n\r\n\r\n"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"temperature": 0.01,
|
||||||
|
"top_p": 0.01,
|
||||||
|
"max_tokens": 900
|
||||||
|
}
|
||||||
|
\```
|
||||||
|
|
||||||
|
### 📤 Response
|
||||||
|
\```json
|
||||||
|
{
|
||||||
|
"id": "chatcmpl-mock123",
|
||||||
|
"object": "chat.completion",
|
||||||
|
"created": 1753867453,
|
||||||
|
"model": "gpt-4",
|
||||||
|
"choices": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
Reference in New Issue
Block a user