Tim-Saijun commited on
Commit
8cd99ea
·
1 Parent(s): 387d8b7

feat: 文件上传脚本

Browse files
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
- """Please generate an English SEO article outline based on the following title, core keywords, related keywords and user information. The writing style should be in the first person, and oral description is preferred.
43
- Requirements for generating an article outline:
44
- 1. Secondary title: Generate multiple secondary titles based on the title, core keywords, and related keywords, no more than 6, and the content of the title should have a logical order and relevance.
45
- 2. Summary: Based on each secondary title, generate a content summary around the secondary title.
46
- 3. SEO word distribution strategy: Generate an SEO word distribution strategy for the current secondary title content.
47
- 4. Heading: The heading uses the heading given by the user.
48
- 5. Your outline should be coherent, so that the paragraphs are coupled with each other and complement each other, like a complete article.
49
- Note: Directly return to the secondary title, topic, and SEO word distribution strategy. Do not have a summary or conclusion.
50
- """,
 
51
  ),
52
  ("placeholder", "{messages}"),
53
  ]
@@ -69,8 +69,11 @@ pre_plan_prompt = ChatPromptTemplate.from_messages(
69
  [
70
  (
71
  "system",
72
- """Please extract the sub-titles of each paragraph in the unstructured data of the received article outline, such as '1.xxx' and the corresponding 'Abstract' and 'SEO word distribution strategy', and add them to the list at once.
73
- For example, \"title:xxxx,topic:xxxx,seo:xxxx\"
 
 
 
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 content of the current secondary title based on the secondary title [title], topic [topic], and SEO word strategy [seo] and retain the secondary title. The content is output in pure English.
88
- Note:1. Please ensure the relevance between the secondary title and the topic content.2. Please refer to the materials and user materials for generation.
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
- # payload = {"language": "en",
152
- # "text": response.content,
153
- # "strength": 4,
154
- # }
155
- # async with aiohttp.ClientSession() as session:
156
- # async with session.post(url, headers=headers, json=payload) as res:
157
- # if res.status == 201:
158
- # rewritten_text = await res.json()
159
- # rewritten_text = await no_conclusion_model.ainvoke(
160
- # {"messages": [("user", rewritten_text["rewrites"][0]["rewrite"])]})
161
- # else:
162
- # print("Error:", res.status, await res.text())
163
- # return {"messages": []}
164
  i = state["time"]
165
- # return {"messages": [messages.content], "time": i + 1}
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
- # Define the two nodes we will cycle between
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
- # Set the entrypoint as `agent`
202
- # This means that this node is the first one called
203
  workflow.set_entry_point("abstract_planner")
204
 
205
- # We now add a conditional edge
206
  workflow.add_conditional_edges(
207
- # First, we define the start node. We use `agent`.
208
- # This means these are the edges taken after the `agent` node is called.
209
  "action",
210
- # Next, we pass in the function that will determine which node is called next.
211
  should_end,
212
  )
213
 
214
- # We now add a normal edge from `tools` to `agent`.
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
- # Finally, we compile it!
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__":