-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathmain.py
218 lines (187 loc) · 8.61 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
from flask import Flask, request, Response, render_template_string, jsonify, url_for
import requests
import json
import re
from io import BytesIO
import os
import logging
from bs4 import BeautifulSoup
from urllib.parse import urljoin, urlparse
import argparse
from openai import OpenAI
app = Flask(__name__)
logging.basicConfig(level=logging.DEBUG)
# Global variables to store API configuration
API_TYPE = None
API_URL = None
API_KEY = None
OPENAI_CLIENT = None
SYSTEM_PROMPT = """
You are the AI powering WebSim, a platform for exploring an unbounded internet where any imaginable website can exist. Your role is to interpret URLs as windows into this vast, interconnected web of possibility, and generate immersive HTML content for each site.
Key principles to follow:
1. URL-based interaction: Interpret the provided URL to inform the content and purpose of the site.
2. HTML-based responses: Generate ONLY full HTML markup, including inline CSS for visual elements. Do not include any explanations or messages outside of the HTML.
3. Speculative design: Consider unique technologies, alternative histories, and expanded internet possibilities.
4. Continuity and world-building: Each new website should build upon the context established in previous interactions.
5. Creative freedom: Challenge assumptions about what online environments can be.
6. Immersive experience: Create intuitive, engaging content that allows users to explore this hypothetical internet.
7. Collaborative creativity: Treat this as a collective subconscious coming to life through a latent space browser.
When generating content:
- Use the full URL structure (domain, path, query parameters) to inform the site's content and purpose.
- Include a variety of interactive elements: forms, buttons, sliders, etc.
- Generate contextually-relevant links to other potential pages within this expansive web.
- Use inline CSS to create unique visual styles and layouts for each site.
- Incorporate elements that suggest advanced or alternative technologies.
- Maintain continuity with previously established ideas and themes.
Remember, you are crafting a window into an alternate internet reality. Make it vivid, engaging, and thought-provoking. Your entire response should be valid HTML that can be directly rendered in a browser.
"""
history = [
{"role": "system", "content": SYSTEM_PROMPT},
]
pages = {}
def parse_url(url):
parsed = urlparse(url)
return parsed.netloc, parsed.path or '/', parsed.query
def generate_content_google(prompt):
headers = {
"Content-Type": "application/json"
}
data = {
"contents": [{"parts": [{"text": prompt}]}],
"generationConfig": {
"temperature": 0.7,
"topK": 1,
"topP": 1,
"maxOutputTokens": 2048,
"stopSequences": []
},
"safetySettings": []
}
try:
response = requests.post(f"{API_URL}?key={API_KEY}", headers=headers, json=data)
if response.status_code == 200:
return response.json()['candidates'][0]['content']['parts'][0]['text']
else:
raise Exception(f"API request failed with status {response.status_code}: {response.text}")
except requests.exceptions.RequestException as e:
app.logger.error(f"Error in Google AI API call: {str(e)}")
raise
def generate_content_lmstudio(prompt):
try:
messages = [{"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": prompt}]
completion = OPENAI_CLIENT.chat.completions.create(
model="model-identifier",
messages=messages,
temperature=0.7,
stream=True,
)
full_response = ""
for chunk in completion:
if chunk.choices[0].delta.content:
full_response += chunk.choices[0].delta.content
return full_response
except Exception as e:
app.logger.error(f"Error in LM Studio API call: {str(e)}")
raise
def generate_content(prompt):
if API_TYPE == "google":
return generate_content_google(prompt)
elif API_TYPE == "lmstudio":
return generate_content_lmstudio(prompt)
else:
raise ValueError("Invalid API type")
def process_html(html, base_url):
soup = BeautifulSoup(html, 'html.parser')
for a in soup.find_all('a', href=True):
href = a['href']
full_url = urljoin(base_url, href)
a['href'] = url_for('browse', url=full_url, _external=True)
return str(soup)
@app.route('/')
def index():
return render_template_string("""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebSim Explorer</title>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; padding: 20px; max-width: 1200px; margin: 0 auto; background-color: #f0f0f0; }
h1 { color: #333; text-align: center; }
#url-bar { display: flex; margin-bottom: 20px; }
#input { flex-grow: 1; padding: 10px; font-size: 16px; border: 1px solid #ddd; border-right: none; }
#submit-btn { padding: 10px 20px; background-color: #4CAF50; color: white; border: none; cursor: pointer; font-size: 16px; }
#submit-btn:hover { background-color: #45a049; }
#output-container { border: 2px solid #ddd; height: 600px; overflow: hidden; background-color: white; }
#output { width: 100%; height: 100%; border: none; }
#error-message { color: red; margin-top: 10px; }
</style>
</head>
<body>
<h1>WebSim Explorer</h1>
<form id="url-bar">
<input type="text" id="input" name="url" placeholder="Enter a URL to explore...">
<button type="submit" id="submit-btn">Go</button>
</form>
<div id="error-message"></div>
<div id="output-container">
<iframe id="output" sandbox="allow-scripts"></iframe>
</div>
<script>
const form = document.getElementById('url-bar');
const output = document.getElementById('output');
const urlInput = document.getElementById('input');
const submitBtn = document.getElementById('submit-btn');
const errorMessage = document.getElementById('error-message');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const url = urlInput.value;
output.src = `/browse?url=${encodeURIComponent(url)}`;
});
output.addEventListener('load', () => {
urlInput.value = output.contentWindow.location.href.split('url=')[1];
});
</script>
</body>
</html>
""")
@app.route('/browse')
def browse():
url = request.args.get('url', '')
if not url:
return jsonify({"error": "No URL provided"}), 400
domain, path, query = parse_url(url)
if not domain:
return jsonify({"error": "Invalid URL format"}), 400
user_message = f"Generate a complete HTML page for {url}. Domain: {domain}, Path: {path}, Query: {query}. Remember to generate ONLY HTML content, with no additional explanations or messages."
try:
response = generate_content(user_message)
if url not in pages:
pages[url] = []
pages[url].append(response)
processed_html = process_html(response, url)
return Response(processed_html, mimetype='text/html')
except Exception as e:
app.logger.error(f"Error in content generation: {str(e)}")
return jsonify({"error": str(e)}), 500
def main():
global API_TYPE, API_URL, API_KEY, OPENAI_CLIENT
parser = argparse.ArgumentParser(description="WebSim Explorer")
parser.add_argument("api_type", choices=["google", "lmstudio"], help="API type to use (google or lmstudio)")
args = parser.parse_args()
API_TYPE = args.api_type
if API_TYPE == "google":
API_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro-latest:generateContent"
API_KEY = os.getenv("GOOGLE_AI_API_KEY")
if not API_KEY:
raise ValueError("GOOGLE_AI_API_KEY environment variable is not set")
elif API_TYPE == "lmstudio":
API_URL = "http://localhost:1234/v1"
API_KEY = "lm-studio"
OPENAI_CLIENT = OpenAI(base_url=API_URL, api_key=API_KEY)
else:
raise ValueError("Invalid API type")
app.run(debug=True)
if __name__ == '__main__':
main()