Spaces:
Paused
Paused
Commit
·
8cd99ea
1
Parent(s):
387d8b7
feat: 文件上传脚本
Browse files- playground/upload.html +14 -0
- playground/upload_server.py +48 -0
- playground/writer.py +72 -45
playground/upload.html
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<title>File Upload</title>
|
6 |
+
</head>
|
7 |
+
<body>
|
8 |
+
<h1>File Upload</h1>
|
9 |
+
<form action="/upload" method="post" enctype="multipart/form-data">
|
10 |
+
<input type="file" name="file">
|
11 |
+
<input type="submit" value="Upload">
|
12 |
+
</form>
|
13 |
+
</body>
|
14 |
+
</html>
|
playground/upload_server.py
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import http.server
|
2 |
+
import socketserver
|
3 |
+
import os
|
4 |
+
from urllib.parse import parse_qs, urlparse
|
5 |
+
from http import cookies
|
6 |
+
|
7 |
+
PORT = 8000
|
8 |
+
DIRECTORY = "."
|
9 |
+
|
10 |
+
class MyHttpRequestHandler(http.server.SimpleHTTPRequestHandler):
|
11 |
+
|
12 |
+
def do_GET(self):
|
13 |
+
if self.path == '/':
|
14 |
+
self.path = 'upload.html'
|
15 |
+
return super().do_GET()
|
16 |
+
|
17 |
+
def do_POST(self):
|
18 |
+
content_length = int(self.headers['Content-Length'])
|
19 |
+
post_data = self.rfile.read(content_length)
|
20 |
+
|
21 |
+
boundary = self.headers['Content-Type'].split('boundary=')[-1].encode()
|
22 |
+
parts = post_data.split(boundary)
|
23 |
+
|
24 |
+
for part in parts:
|
25 |
+
if b'Content-Disposition: form-data; name="file";' in part:
|
26 |
+
file_data = part.split(b'\r\n\r\n')[1].strip()
|
27 |
+
file_name = part.split(b'filename="')[1].split(b'"')[0].decode()
|
28 |
+
file_path = os.path.join(DIRECTORY, file_name)
|
29 |
+
|
30 |
+
with open(file_path, 'wb') as file:
|
31 |
+
file.write(file_data)
|
32 |
+
|
33 |
+
self.send_response(200)
|
34 |
+
self.send_header('Content-Type', 'text/html')
|
35 |
+
self.end_headers()
|
36 |
+
self.wfile.write(b'File uploaded and overwritten successfully!')
|
37 |
+
return
|
38 |
+
|
39 |
+
self.send_response(400)
|
40 |
+
self.send_header('Content-Type', 'text/html')
|
41 |
+
self.end_headers()
|
42 |
+
self.wfile.write(b'File upload failed.')
|
43 |
+
|
44 |
+
Handler = MyHttpRequestHandler
|
45 |
+
|
46 |
+
with socketserver.TCPServer(("", PORT), Handler) as httpd:
|
47 |
+
print(f"Serving at port {PORT}")
|
48 |
+
httpd.serve_forever()
|
playground/writer.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
import os
|
2 |
import getpass
|
3 |
-
import quart
|
4 |
from quart import Quart, request
|
5 |
|
6 |
|
@@ -39,15 +38,16 @@ absract_plan_prompt = ChatPromptTemplate.from_messages(
|
|
39 |
[
|
40 |
(
|
41 |
"system",
|
42 |
-
"""
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
|
|
51 |
),
|
52 |
("placeholder", "{messages}"),
|
53 |
]
|
@@ -69,8 +69,11 @@ pre_plan_prompt = ChatPromptTemplate.from_messages(
|
|
69 |
[
|
70 |
(
|
71 |
"system",
|
72 |
-
"""
|
73 |
-
|
|
|
|
|
|
|
74 |
"""
|
75 |
),
|
76 |
("placeholder", "{messages}"),
|
@@ -84,9 +87,35 @@ designer_prompt = ChatPromptTemplate.from_messages(
|
|
84 |
[
|
85 |
(
|
86 |
"system",
|
87 |
-
"""You are a professional SEO article writer. You need to generate the paragraph
|
88 |
-
|
89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
),
|
91 |
("placeholder", "{messages}"),
|
92 |
]
|
@@ -148,22 +177,22 @@ async def DESIGNER(state: GraphState):
|
|
148 |
break
|
149 |
|
150 |
response = await designer_model.ainvoke({"messages": [("user", f"{messages[::-1]}")]})
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
i = state["time"]
|
165 |
-
|
166 |
-
return {"messages": [response.content], "time": i + 1}
|
167 |
|
168 |
|
169 |
from typing import Literal
|
@@ -173,7 +202,6 @@ def route(state: GraphState) -> Literal["__end__", "action"]:
|
|
173 |
# If there is no function call, then we finish
|
174 |
if state["time"] < len(state["plan"]):
|
175 |
return "action"
|
176 |
-
# Otherwise if there is, we continue
|
177 |
else:
|
178 |
return "__end__"
|
179 |
|
@@ -182,7 +210,6 @@ def should_end(state: GraphState) -> Literal["__end__", "dliver"]:
|
|
182 |
# If there is no function call, then we finish
|
183 |
if state["time"] < len(state["plan"]):
|
184 |
return "dliver"
|
185 |
-
# Otherwise if there is, we continue
|
186 |
else:
|
187 |
return "__end__"
|
188 |
|
@@ -192,33 +219,28 @@ from langgraph.graph import StateGraph
|
|
192 |
# Define a new graph
|
193 |
workflow = StateGraph(GraphState)
|
194 |
|
195 |
-
|
196 |
workflow.add_node("abstract_planner", abstrct_plan_step)
|
197 |
workflow.add_node("planner", plan_step)
|
198 |
workflow.add_node("action", DESIGNER)
|
199 |
workflow.add_node("dliver", DLIVER)
|
200 |
|
201 |
-
|
202 |
-
# This means that this node is the first one called
|
203 |
workflow.set_entry_point("abstract_planner")
|
204 |
|
205 |
-
|
206 |
workflow.add_conditional_edges(
|
207 |
-
|
208 |
-
# This means these are the edges taken after the `agent` node is called.
|
209 |
"action",
|
210 |
-
|
211 |
should_end,
|
212 |
)
|
213 |
|
214 |
-
|
215 |
-
# This means that after `tools` is called, `agent` node is called next.
|
216 |
workflow.add_edge("abstract_planner", "planner")
|
217 |
workflow.add_edge("planner", "dliver")
|
218 |
workflow.add_edge("dliver", "action")
|
219 |
-
|
220 |
-
# This compiles it into a LangChain Runnable,
|
221 |
-
# meaning you can use it as you would any other runnable
|
222 |
app = workflow.compile()
|
223 |
|
224 |
|
@@ -242,7 +264,6 @@ config = {"recursion_limit": 500}
|
|
242 |
q_app = Quart(__name__)
|
243 |
|
244 |
|
245 |
-
@q_app.route('/write', methods=['GET'])
|
246 |
async def main():
|
247 |
title = request.args.get('title')
|
248 |
core_keywords = request.args.get('core_keywords')
|
@@ -262,6 +283,12 @@ async def main():
|
|
262 |
return messages
|
263 |
|
264 |
|
|
|
|
|
|
|
|
|
|
|
|
|
265 |
import asyncio
|
266 |
|
267 |
if __name__ == "__main__":
|
|
|
1 |
import os
|
2 |
import getpass
|
|
|
3 |
from quart import Quart, request
|
4 |
|
5 |
|
|
|
38 |
[
|
39 |
(
|
40 |
"system",
|
41 |
+
"""
|
42 |
+
Please generate an English SEO article outline based on the following title, core keywords, related keywords and user information. The writing style should be first-person, and oral description is preferred.
|
43 |
+
Requirements for generating an article outline:
|
44 |
+
1. Based on the professional title, you must create at least 4 subheadings. You must expand each subheading with relevant third-level titles, and the title content must have a logical order and relevance.
|
45 |
+
2. Summary: Based on each subheading, generate a content summary around the subheading.
|
46 |
+
3. SEO wrd segmentation strategy: Generate an SEO word segmentation strategy for the current subheading content.
|
47 |
+
4. Title: The title uses the title given by the user.
|
48 |
+
5. Your outline should be coherent, so that the paragraphs are coupled and complement each other, like a complete article.
|
49 |
+
Note: Go directly back to the subheading, topic and SEO word segmentation strategy. No summary or conclusion.
|
50 |
+
""",
|
51 |
),
|
52 |
("placeholder", "{messages}"),
|
53 |
]
|
|
|
69 |
[
|
70 |
(
|
71 |
"system",
|
72 |
+
"""
|
73 |
+
Please extract the subtitles and third-level titles in the unstructured data of the
|
74 |
+
received article outline, such as '1.xxx','1.1.xxx' and the corresponding 'Abstract' and 'SEO word
|
75 |
+
distribution strategy', and add them to the list at one time.
|
76 |
+
For example, \"title:xxxx,third-level titles:xxx,topic:xxxx,seo:xxxx\"
|
77 |
"""
|
78 |
),
|
79 |
("placeholder", "{messages}"),
|
|
|
87 |
[
|
88 |
(
|
89 |
"system",
|
90 |
+
"""You are a professional SEO article writer. You need to generate the paragraph
|
91 |
+
content of the current secondary title based on the secondary title [title], topic [topic],
|
92 |
+
and SEO word strategy [seo] and retain the secondary title. The content is output in pure
|
93 |
+
English.
|
94 |
+
You must output in HTML format:
|
95 |
+
-- Subtitles: `<h2>` tag
|
96 |
+
-- Main text: `<p>` tag
|
97 |
+
Note:1. Please ensure the relevance between the secondary title and the topic content.
|
98 |
+
2. Please refer to the materials and user materials for generation.The number of words in each paragraph is 100-200.
|
99 |
+
Instructions:
|
100 |
+
-- You must return only the article content, no outline or explanations.
|
101 |
+
-- Core and related keywords must appear according to specified frequencies and at least once.
|
102 |
+
-- Content must be coherent, free of spelling errors, and logically consistent.
|
103 |
+
-- Core keyword frequency must be 3%.
|
104 |
+
-- Related keyword frequency must be 1%.
|
105 |
+
-- Do not display the generated title or the `<h1>` tag. Directly start with the content.
|
106 |
+
-- Do not use markdown syntax.
|
107 |
+
-- Core keywords must be used exactly as provided.
|
108 |
+
-- Content must be detailed and comprehensive.
|
109 |
+
-- Article must include an introduction and a conclusion.
|
110 |
+
-- The article length must be greater than 750 words.
|
111 |
+
-- Do not start with the <html> tag.
|
112 |
+
-- Do not include the </html> tag at the end.
|
113 |
+
-- You must follow the above steps and instructions meticulously.
|
114 |
+
-- You must ensure the article aligns with SEO bes practices.
|
115 |
+
-- Maintain an engaging and anthropomorphic writing style.
|
116 |
+
-- Strive for a perfect balance between keyword density and natural readability.
|
117 |
+
-- If related keywords are not provided, proceed with generating the article using only the core keywords.
|
118 |
+
"""
|
119 |
),
|
120 |
("placeholder", "{messages}"),
|
121 |
]
|
|
|
177 |
break
|
178 |
|
179 |
response = await designer_model.ainvoke({"messages": [("user", f"{messages[::-1]}")]})
|
180 |
+
payload = {"language": "en",
|
181 |
+
"text": response.content,
|
182 |
+
"strength": 4,
|
183 |
+
}
|
184 |
+
async with aiohttp.ClientSession() as session:
|
185 |
+
async with session.post(url, headers=headers, json=payload) as res:
|
186 |
+
if res.status == 201:
|
187 |
+
rewritten_text = await res.json()
|
188 |
+
rewritten_text = await no_conclusion_model.ainvoke(
|
189 |
+
{"messages": [("user", rewritten_text["rewrites"][0]["rewrite"])]})
|
190 |
+
else:
|
191 |
+
print("Error:", res.status, await res.text())
|
192 |
+
return {"messages": []}
|
193 |
i = state["time"]
|
194 |
+
return {"messages": [rewritten_text.content], "time": i + 1}
|
195 |
+
# return {"messages": [response.content], "time": i + 1}
|
196 |
|
197 |
|
198 |
from typing import Literal
|
|
|
202 |
# If there is no function call, then we finish
|
203 |
if state["time"] < len(state["plan"]):
|
204 |
return "action"
|
|
|
205 |
else:
|
206 |
return "__end__"
|
207 |
|
|
|
210 |
# If there is no function call, then we finish
|
211 |
if state["time"] < len(state["plan"]):
|
212 |
return "dliver"
|
|
|
213 |
else:
|
214 |
return "__end__"
|
215 |
|
|
|
219 |
# Define a new graph
|
220 |
workflow = StateGraph(GraphState)
|
221 |
|
222 |
+
|
223 |
workflow.add_node("abstract_planner", abstrct_plan_step)
|
224 |
workflow.add_node("planner", plan_step)
|
225 |
workflow.add_node("action", DESIGNER)
|
226 |
workflow.add_node("dliver", DLIVER)
|
227 |
|
228 |
+
|
|
|
229 |
workflow.set_entry_point("abstract_planner")
|
230 |
|
231 |
+
|
232 |
workflow.add_conditional_edges(
|
233 |
+
|
|
|
234 |
"action",
|
235 |
+
|
236 |
should_end,
|
237 |
)
|
238 |
|
239 |
+
|
|
|
240 |
workflow.add_edge("abstract_planner", "planner")
|
241 |
workflow.add_edge("planner", "dliver")
|
242 |
workflow.add_edge("dliver", "action")
|
243 |
+
|
|
|
|
|
244 |
app = workflow.compile()
|
245 |
|
246 |
|
|
|
264 |
q_app = Quart(__name__)
|
265 |
|
266 |
|
|
|
267 |
async def main():
|
268 |
title = request.args.get('title')
|
269 |
core_keywords = request.args.get('core_keywords')
|
|
|
283 |
return messages
|
284 |
|
285 |
|
286 |
+
@q_app.route('/write', methods=['GET'])
|
287 |
+
async def request_result():
|
288 |
+
result = await main()
|
289 |
+
return result
|
290 |
+
|
291 |
+
|
292 |
import asyncio
|
293 |
|
294 |
if __name__ == "__main__":
|