|
10 | 10 | import re |
11 | 11 | from typing import List, Tuple, Dict |
12 | 12 | import clean_text |
| 13 | +from xai_sdk import Client |
| 14 | +from xai_sdk.chat import system, user |
13 | 15 |
|
14 | 16 | path_to = f'src/content/blog/{datetime.datetime.now().strftime("%Y-%m-%d")}' |
15 | 17 |
|
|
23 | 25 | start = time.time() |
24 | 26 | print(" Connecting remote:") |
25 | 27 | deepseek = OpenAI(base_url="https://api.deepseek.com", api_key=os.environ.get("DS_APIKEY")) |
| 28 | +xai_client = Client(api_key=os.getenv("XAI_API_KEY"), timeout=7200) |
26 | 29 | print(f" Time spent on init: {time.time() - start:.1f} s") |
27 | 30 |
|
28 | | -def generate(context, provider, model): |
| 31 | +def generate(context, provider, model): #for openrouter |
29 | 32 | completion = provider.chat.completions.create( |
30 | 33 | model=model, |
31 | 34 | messages=context |
32 | 35 | ) |
33 | 36 | return completion.choices[0].message.content.strip() |
34 | 37 |
|
| 38 | +def grok_generate(context, provider, model): #for xai |
| 39 | + """ |
| 40 | + e.g. |
| 41 | + model="grok-3-mini" |
| 42 | + provider=xai_client |
| 43 | + context=[system("You are a highly intelligent AI assistant."),user("What is 101*3?")] |
| 44 | + """ |
| 45 | + chat = provider.chat.create( |
| 46 | + model=model, |
| 47 | + messages=context, |
| 48 | + ) |
| 49 | + return chat.sample() |
| 50 | + |
35 | 51 | def scrape_website(url, css_selector): |
36 | 52 | response = requests.get(url) |
37 | 53 | if response.status_code == 200: |
@@ -73,30 +89,45 @@ def get_existing_blog_posts(): |
73 | 89 |
|
74 | 90 | def extract_topic(topics): |
75 | 91 | global deepseek, existing_posts_text |
76 | | - return generate([ |
77 | | - {"role": "system", "content": "你在为一篇技术博客确定一个主题。直接用中文输出主题。"}, |
78 | | - {"role": "user", "content": f"阅读以下是HackerNews的热门文章,然后写一个可以用于技术博客的主题。这个主题应当是一个通用、普通的技术,不能是一个事件或其它东西。\n\n{topics}\n\n以下是已有的博客文章,请避免选择相似的主题:\n{existing_posts_text}\n\n只需要一个主题,直接输出。"}, |
79 | | - ], deepseek, "deepseek-chat") |
| 92 | + # return generate([ |
| 93 | + # {"role": "system", "content": "你在为一篇技术博客确定一个主题。直接用中文输出主题。"}, |
| 94 | + # {"role": "user", "content": f"阅读以下是HackerNews的热门文章,然后写一个可以用于技术博客的主题。这个主题应当是一个通用、普通的技术,不能是一个事件或其它东西。\n\n{topics}\n\n以下是已有的博客文章,请避免选择相似的主题:\n{existing_posts_text}\n\n只需要一个主题,直接输出。"}, |
| 95 | + # ], deepseek, "deepseek-chat") |
| 96 | + return grok_generate([ |
| 97 | + system("你在为一篇技术博客确定一个主题。直接用中文输出主题。"), |
| 98 | + user(f"阅读以下是HackerNews的热门文章,然后写一个可以用于技术博客的主题。这个主题应当是一个通用、普通的技术,不能是一个事件或其它东西。\n\n{topics}\n\n以下是已有的博客文章,请避免选择相似的主题:\n{existing_posts_text}\n\n只需要一个主题,直接输出。") |
| 99 | + ], xai_client, "grok-3-mini") |
80 | 100 |
|
81 | 101 | def outline(topic): |
82 | 102 | global deepseek |
83 | | - return generate([ |
84 | | - {"role": "user", "content": f"我要写一篇关于「{topic}」的博客文章。帮我列一个详细的文章提纲。"} |
85 | | - ], deepseek, "deepseek-reasoner") |
| 103 | + # return generate([ |
| 104 | + # {"role": "user", "content": f"我要写一篇关于「{topic}」的博客文章。帮我列一个详细的文章提纲。"} |
| 105 | + # ], deepseek, "deepseek-reasoner") |
| 106 | + return grok_generate([ |
| 107 | + user(f"我要写一篇关于「{topic}」的博客文章。帮我列一个详细的文章提纲。") |
| 108 | + ], xai_client, "grok-3-mini") |
86 | 109 |
|
87 | 110 | def write_from_outline(outline): |
88 | 111 | global deepseek, existing_posts_text |
89 | | - return generate([ |
90 | | - {"role": "system", "content": "你是一位专业技术博客作者。在写作时请遵循以下中文排版规范:使用全角中文标点;专有名词大小写正确;英文、数字使用半角字符;使用直角引号「」。"}, |
91 | | - {"role": "user", "content": f"{outline}\n\n根据这个提纲中关于技术知识的部分,写出一篇技术博客文章。文章中避免出现图片,不能使用任何列表。每一段出现的代码都进行较为详细的解读。在讲述内容时尽量使用段落的语言,语言风格可以略偏专业,但保持清晰。使用Markdown(要求符合Common Markdown规范)输出,使用LaTeX公式(注意:数学的开闭定界符前后不能有字母或数字字符。像x$a + b = c$或$a + b = c$1将无法渲染为数学公式(所有$会被渲染为$);但x $\\infty$ 1和($\\infty$)会正常渲染),标题尽量只用一级标题 `#` 和二级标题 `##`,不要用分割线。请遵循中文排版规范,使用正确的标点符号。直接输出正文。"} |
92 | | - ], deepseek, "deepseek-reasoner") |
| 112 | + # return generate([ |
| 113 | + # {"role": "system", "content": "你是一位专业技术博客作者。在写作时请遵循以下中文排版规范:使用全角中文标点;专有名词大小写正确;英文、数字使用半角字符;使用直角引号「」。"}, |
| 114 | + # {"role": "user", "content": f"{outline}\n\n根据这个提纲中关于技术知识的部分,写出一篇技术博客文章。文章中避免出现图片,不能使用任何列表。每一段出现的代码都进行较为详细的解读。在讲述内容时尽量使用段落的语言,语言风格可以略偏专业,但保持清晰。使用Markdown(要求符合Common Markdown规范)输出,使用LaTeX公式(注意:数学的开闭定界符前后不能有字母或数字字符。像x$a + b = c$或$a + b = c$1将无法渲染为数学公式(所有$会被渲染为$);但x $\\infty$ 1和($\\infty$)会正常渲染),标题尽量只用一级标题 `#` 和二级标题 `##`,不要用分割线。请遵循中文排版规范,使用正确的标点符号。直接输出正文。"} |
| 115 | + # ], deepseek, "deepseek-reasoner") |
| 116 | + return grok_generate([ |
| 117 | + system("你是一位专业技术博客作者。在写作时请遵循以下中文排版规范:使用全角中文标点;专有名词大小写正确;英文、数字使用半角字符;使用直角引号「」。"), |
| 118 | + user(f"{outline}\n\n根据这个提纲中关于技术知识的部分,写出一篇技术博客文章。文章中避免出现图片,不能使用任何列表。每一段出现的代码都进行较为详细的解读。在讲述内容时尽量使用段落的语言,语言风格可以略偏专业,但保持清晰。使用Markdown(要求符合Common Markdown规范)输出,使用LaTeX公式(注意:数学的开闭定界符前后不能有字母或数字字符。像x$a + b = c$或$a + b = c$1将无法渲染为数学公式(所有$会被渲染为$);但x $\\infty$ 1和($\\infty$)会正常渲染),标题尽量只用一级标题 `#` 和二级标题 `##`,不要用分割线。请遵循中文排版规范,使用正确的标点符号。直接输出正文。") |
| 119 | + ], xai_client, "grok-3-mini") |
93 | 120 |
|
94 | 121 | def summary(article): |
95 | 122 | global deepseek |
96 | | - return generate([ |
97 | | - {"role": "system", "content": "你是一个技术博客简介写作者,简介不一定需要涵盖文章的全部内容,能起到一定的提示作用即可。直接输出简介。遵循以下中文排版规范:使用全角中文标点;专有名词大小写正确;英文、数字使用半角字符。注意简介被作为副标题使用,不是一句句子,不要以句号结尾。"}, |
98 | | - {"role": "user", "content": f"给这篇文章写一个15字的简短介绍:\n\n{article}"} |
99 | | - ], deepseek, "deepseek-chat") |
| 123 | + # return generate([ |
| 124 | + # {"role": "system", "content": "你是一个技术博客简介写作者,简介不一定需要涵盖文章的全部内容,能起到一定的提示作用即可。直接输出简介。遵循以下中文排版规范:使用全角中文标点;专有名词大小写正确;英文、数字使用半角字符。注意简介被作为副标题使用,不是一句句子,不要以句号结尾。"}, |
| 125 | + # {"role": "user", "content": f"给这篇文章写一个15字的简短介绍:\n\n{article}"} |
| 126 | + # ], deepseek, "deepseek-chat") |
| 127 | + return grok_generate([ |
| 128 | + system("你是一个技术博客简介写作者,简介不一定需要涵盖文章的全部内容,能起到一定的提示作用即可。直接输出简介。遵循以下中文排版规范:使用全角中文标点;专有名词大小写正确;英文、数字使用半角字符。注意简介被作为副标题使用,不是一句句子,不要以句号结尾。"), |
| 129 | + user(f"给这篇文章写一个15字的简短介绍:\n\n{article}") |
| 130 | + ], xai_client, "grok-3-mini") |
100 | 131 |
|
101 | 132 | # LaTeX error handling |
102 | 133 | def extract_latex_segments(markdown_text: str) -> List[Tuple[str, int, int]]: |
@@ -234,10 +265,14 @@ def modify_latex(markdown_text: str, error_report: Dict[Tuple[str,int], List[str |
234 | 265 | "\n\n上下文:\n" + context + |
235 | 266 | "\n\n请只返回修正后的完整片段,不要添加其它标记。" |
236 | 267 | ) |
237 | | - fixed = generate([ |
238 | | - {"role":"system","content":"你是 LaTeX 专家,负责修正以下代码:"}, |
239 | | - {"role":"user","content":user_msg} |
240 | | - ], deepseek, "deepseek-reasoner").strip() |
| 268 | + # fixed = generate([ |
| 269 | + # {"role":"system","content":"你是 LaTeX 专家,负责修正以下代码:"}, |
| 270 | + # {"role":"user","content":user_msg} |
| 271 | + # ], deepseek, "deepseek-reasoner").strip() |
| 272 | + fixed = grok_generate([ |
| 273 | + system("你是 LaTeX 专家,负责修正以下代码:"), |
| 274 | + user(user_msg) |
| 275 | + ], xai_client, "grok-3-mini").strip() |
241 | 276 |
|
242 | 277 | # 去掉```,如果不小心生成了 |
243 | 278 | if fixed.startswith("```") and fixed.endswith("```"): |
|
0 commit comments