🍊 Pomelli, and the same idea on your own laptop · Pomelli กับแนวคิดเดียวกันบนแล็ปท็อปของคุณเอง · Pomelli,以及在你自己笔记本上的同一个想法

Google's free marketing tool reads your website and writes in your voice. It only works in English. So here is what it does. Then the same three ideas in Python, in any language. · เครื่องมือการตลาดฟรีของกูเกิลอ่านเว็บไซต์ของคุณแล้วเขียนด้วยน้ำเสียงของคุณ แต่ใช้ได้เฉพาะภาษาอังกฤษ หน้านี้จึงเล่าว่ามันทำอะไร แล้วทำสามอย่างเดียวกันด้วย Python บนเครื่องคุณ ในภาษาไหนก็ได้ · Google 的免费营销工具会读你的网站,用你的口吻写东西,但只支持英文。所以这一页先讲它做什么,再用 Python 在你自己机器上做同样的三件事,语言随你挑。

🇬🇧 English

Pomelli is a free tool from Google Labs. You give it your website. It reads the site, works out how your business talks, and writes marketing that sounds like you.

It is genuinely good, and there is one catch for readers here. The whole thing is in English only.

So this page does both. First what Pomelli does, and how to use it. Then the same three ideas, built on your own laptop, in Python, in any language you like.

🇹🇭 ไทย

Pomelli คือเครื่องมือฟรีจาก Google Labs คุณให้เว็บไซต์ของคุณกับมัน มันจะอ่านเว็บนั้น คิดออกว่าธุรกิจของคุณพูดจาแบบไหน แล้วเขียนงานการตลาดที่ฟังดูเหมือนคุณ

มันดีจริง และมีข้อติดอยู่อย่างเดียวสำหรับคนอ่านที่นี่ ทั้งระบบเป็นภาษาอังกฤษล้วน

หน้านี้จึงทำทั้งสองอย่าง เริ่มจาก Pomelli ทำอะไรและใช้ยังไง แล้วต่อด้วยสามแนวคิดเดียวกัน ที่สร้างบนแล็ปท็อปของคุณเอง ด้วย Python และใช้ภาษาไหนก็ได้

🇨🇳 中文

Pomelli 是 Google Labs 出的免费工具。你把网站给它,它读你的网站,弄清楚你的生意是怎么说话的,然后写出听起来像你的营销内容。

它是真的好用,但对这里的读者有一个卡点:整个界面只有英文。

所以这一页两件事都做。先讲 Pomelli 做什么、怎么用;再把同样的三个想法,用 Python 搬到你自己的笔记本上,想用什么语言都行。

('Pomelli', 'Pomelli', 'Pomelli')("This page's version", 'แบบในหน้านี้', '这一页的版本')
Reads your websiteอ่านเว็บไซต์ของคุณ读你的网站the sameเหมือนกัน一样
Runs on Google's computersรันบนเครื่องของกูเกิล跑在 Google 的机器上runs on yoursรันบนเครื่องคุณ跑在你的机器上
English onlyภาษาอังกฤษเท่านั้น只有英文any language the model knowsภาษาไหนก็ได้ที่โมเดลรู้จัก模型会的任何语言
Makes pictures tooทำรูปภาพให้ด้วย还会做图words onlyเฉพาะข้อความ只做文字
Free for nowตอนนี้ฟรี目前免费free, and yoursฟรี และเป็นของคุณเอง免费,而且是你自己的

🍊 Tutorial 1 — What Pomelli does · บทที่ 1 — Pomelli ทำอะไร · 教程 1 —— Pomelli 是做什么的

🇬🇧 English

Three stages, and the first one is the interesting idea.

It reads your site and writes down what it learned, as a profile it calls your Business DNA. Everything it makes afterwards is checked against that profile, so it stays in your voice.

Go to labs.google/pomelli, sign in with a Google account, and paste your web address. You need to be 18, and it is free.

🇹🇭 ไทย

สามขั้นตอน และขั้นแรกคือแนวคิดที่น่าสนใจที่สุด

มันอ่านเว็บของคุณแล้วจดสิ่งที่เรียนรู้ไว้เป็นโปรไฟล์ ที่มันเรียกว่า Business DNA ทุกอย่างที่มันสร้างหลังจากนั้นจะถูกเทียบกับโปรไฟล์นั้น เพื่อให้ยังเป็นเสียงของคุณ

เข้า labs.google/pomelli ล็อกอินด้วยบัญชีกูเกิล แล้ววางที่อยู่เว็บของคุณ ต้องอายุ 18 ขึ้นไป และใช้ฟรี

🇨🇳 中文

三个阶段,第一个才是真正有意思的想法。

它读你的网站,把学到的东西写成一份档案,叫做 Business DNA。之后它做的每样东西都会拿这份档案对一遍,好让内容一直是你的口吻。

去 labs.google/pomelli,用 Google 账号登录,再把你的网址粘进去。需要满 18 岁,免费。

('Stage', 'ขั้น', '阶段')('What happens', 'เกิดอะไรขึ้น', '发生什么')
1. Business DNA1. Business DNA1. Business DNAIt reads the site and writes down your tone, colours and audience.มันอ่านเว็บ แล้วจดโทนเสียง สี และกลุ่มลูกค้าของคุณไว้它读网站,把你的语气、配色和受众记下来。
2. Campaign ideas2. ไอเดียแคมเปญ2. 活动点子It suggests directions. You pick one, or type your own.มันเสนอแนวทางมาให้ คุณเลือกอันหนึ่ง หรือพิมพ์ของคุณเองก็ได้它给出几个方向。你挑一个,或者自己输入。
3. The assets3. ชิ้นงาน3. 成品Posts and images, sized for each place you post them.โพสต์และรูปภาพ ปรับขนาดให้พอดีกับแต่ละที่ที่คุณจะลง帖子和图片,按你要发的每个平台调好尺寸。
IT IS AN EXPERIMENT, AND IT SAYS SO Google calls Pomelli an early experiment. It is free now, in English, and in over 190 countries including Thailand. All three of those could change. Google also says the AI may alter fine details. That includes your logo and colours. Look hard at anything before you publish it. กูเกิลเรียก Pomelli ว่าเป็นการทดลองช่วงแรก ตอนนี้ฟรี เป็นภาษาอังกฤษ และใช้ได้ในกว่า 190 ประเทศรวมทั้งไทย ทั้งสามข้อนี้เปลี่ยนได้ทุกเมื่อ กูเกิลยังบอกด้วยว่า AI อาจเปลี่ยนรายละเอียดเล็ก ๆ รวมถึงโลโก้และสีของคุณ ดูให้ดีทุกครั้งก่อนเผยแพร่ Google 自己说 Pomelli 是早期实验。现在免费、英文、覆盖 190 多个国家和地区,包括泰国。这三点都可能变。Google 还说 AI 可能会改动细节,包括你的标志和配色。发布之前,每样东西都要仔细看过。
YOUR TURN
  1. Open labs.google/pomelli and sign in.
  2. Paste a website you know well. Yours, or your school's.
  3. Check: read the Business DNA. Is it right about you?
  4. Write down one thing it got wrong. You will need it in step 1.
  1. เปิด labs.google/pomelli แล้วล็อกอิน
  2. วางที่อยู่เว็บที่คุณรู้จักดี ของคุณเอง หรือของโรงเรียน
  3. ตรวจ: อ่าน Business DNA ที่ได้ มันเข้าใจคุณถูกไหม
  4. จดไว้หนึ่งข้อที่มันเข้าใจผิด คุณจะได้ใช้ในขั้นที่ 1
  1. 打开 labs.google/pomelli 登录。
  2. 粘一个你很熟的网站:你自己的,或者你学校的。
  3. 检查:读那份 Business DNA。它说得对吗?
  4. 记下它弄错的一件事,第 1 步会用到。

🧬 Tutorial 2 — Business DNA on your own laptop · บทที่ 2 — Business DNA บนแล็ปท็อปของคุณเอง · 教程 2 —— 在你自己笔记本上做 Business DNA

🇬🇧 English

The idea is not secret. Read the website, ask a model to describe the business, and keep the description.

Ollama from the email lessons is enough. Three short files, and it works in Thai.

🇹🇭 ไทย

แนวคิดนี้ไม่ได้เป็นความลับ อ่านเว็บไซต์ ให้โมเดลอธิบายธุรกิจนั้น แล้วเก็บคำอธิบายไว้

ใช้ Ollama จากบทเรียนอีเมลก็พอแล้ว ไฟล์สั้น ๆ สามไฟล์ และใช้กับภาษาไทยได้

🇨🇳 中文

这个想法不是秘密:读网站,让模型描述这门生意,把描述留下来。

用邮件课里的 Ollama 就够了。三个短文件,而且中文泰文都能用。

1 Read the site, and describe the business · อ่านเว็บ แล้วอธิบายธุรกิจ · 读网站,然后描述这门生意

🇬🇧 English

A web page is mostly tags. Strip them, and what is left is the words a person reads. That is what the model needs.

Then one instruction, with the keys named. format: json makes Ollama answer with data instead of a paragraph about data.

🇹🇭 ไทย

หน้าเว็บส่วนใหญ่คือแท็ก ลอกมันออก สิ่งที่เหลือคือคำที่คนอ่านจริง ๆ นั่นแหละคือสิ่งที่โมเดลต้องการ

จากนั้นสั่งครั้งเดียว โดยบอกชื่อคีย์ไว้ด้วย format: json ทำให้ Ollama ตอบเป็นข้อมูล ไม่ใช่ย่อหน้าที่พูดถึงข้อมูล

🇨🇳 中文

网页大部分是标签。把它们剥掉,剩下的就是人会读的那些字,也正是模型需要的。

然后给一条指令,把键名写清楚。format: json 让 Ollama 直接回数据,而不是回一段谈论数据的话。

📄 NEW FILE · dna1.py

"""dna1.py — read a website, and work out how it talks."""
import html
import json
import re
import sys
import urllib.request

OLLAMA = "http://localhost:11434/api/chat"
MODEL = "llama3.2"
SITE = "https://krueng.ai/"

sys.stdout.reconfigure(encoding="utf-8")

DNA_PROMPT = """Here is the text of a small business website.

=== WEBSITE ===
{text}
=== END ===

Describe the business as JSON with exactly these keys:
business, audience, tone, three_words, avoid, offer.
Keep every value under fifteen words. Answer with JSON only."""


def page_text(address):
    """Fetch a page and keep only the words a person would read."""
    request = urllib.request.Request(address, headers={"User-Agent": "Mozilla/5.0"})
    with urllib.request.urlopen(request, timeout=60) as response:
        raw = response.read().decode("utf-8", errors="replace")

    # Script and style hold code, not words. Drop them before the tags.
    without_code = re.sub(r"<script[\s\S]*?</script>|<style[\s\S]*?</style>", " ", raw)
    words = html.unescape(re.sub(r"<[^>]+>", " ", without_code))
    return " ".join(words.split())


def ask_for_json(prompt):
    """One call to Ollama, with format=json so the answer is always parseable."""
    payload = json.dumps({
        "model": MODEL,
        "stream": False,
        "format": "json",          # Ollama then refuses to answer with prose
        "options": {"num_ctx": 8192, "temperature": 0.2},
        "messages": [{"role": "user", "content": prompt}],
    }).encode()
    request = urllib.request.Request(
        OLLAMA, data=payload, headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(request, timeout=900) as response:
        return json.loads(json.load(response)["message"]["content"])


def main():
    """Turn one web address into a short description of the business."""
    text = page_text(SITE)
    print("read", len(text.split()), "words from", SITE)

    # Long pages cost time and add nothing. The top of a site says the most.
    dna = ask_for_json(DNA_PROMPT.format(text=text[:6000]))

    with open("dna.json", "w", encoding="utf-8") as saved:
        json.dump(dna, saved, ensure_ascii=False, indent=2)

    print()
    for key, value in dna.items():
        print(key.ljust(12), value)
    print()
    print("saved: dna.json")


if __name__ == "__main__":
    main()
LineWhat it does · ทำอะไร · 做什么
re.sub(r"<script[\s\S]*?</script>|<style[\s\S]*?</style>", " ", raw)Take the code out before the tags. Otherwise you feed it JavaScript.ลอกโค้ดออกก่อนจะลอกแท็ก ไม่อย่างนั้นคุณจะป้อน JavaScript ให้มันกิน先把代码去掉,再去标签。不然你喂给它的是 JavaScript。
"format": "json",Ollama then refuses to answer with prose. The reply always parses.Ollama จะไม่ตอบเป็นร้อยแก้วอีก คำตอบแปลงเป็นข้อมูลได้เสมอOllama 就不会再用散文回答了。回复永远能解析。
text[:6000]The top of a site says the most. More text costs time and adds little.ส่วนบนของเว็บบอกอะไรมากที่สุด ข้อความที่เกินมากินเวลาแต่ได้เพิ่มไม่เท่าไร网站上半部分信息最多。多喂文字费时间,收获不大。

🖥️ WHAT IT PRINTED · run against the real krueng.ai

read 1359 words from https://krueng.ai/

business     Language learning platform with AI-powered tools
audience     Thai learners
tone         Friendly and interactive
three_words  Learn English Online
avoid        Expensive courses
offer        Free English lessons and tools

saved: dna.json
THIS IS THE STEP TO ARGUE WITH Six lines, and they decide everything written later. Read them as if a stranger wrote them about your shop. If audience is wrong, every post after it is wrong too. And wrong in a confident voice. Edit dna.json by hand. That is allowed. หกบรรทัดนี้ตัดสินทุกอย่างที่จะถูกเขียนต่อจากนี้ อ่านมันเหมือนกับว่าคนแปลกหน้าเขียนถึงร้านของคุณ ถ้า audience ผิด ทุกโพสต์หลังจากนั้นก็ผิดตามไปด้วย และมันจะผิดด้วยน้ำเสียงที่มั่นใจมาก แก้ dna.json ด้วยมือได้เลย 六行字,却决定了之后写出来的一切。把它们当成一个陌生人写你店铺的评语来读。如果 audience 错了,后面每一条帖子都会跟着错,而且错得非常自信。直接手改 dna.json,这是允许的。
YOUR TURN
  1. Change SITE to a website you know. Run it.
  2. Check: read all six lines. Which one is wrong?
  3. Fix that line in dna.json by hand.
  4. Compare it with what Pomelli said about the same site.
  1. เปลี่ยน SITE เป็นเว็บที่คุณรู้จัก แล้วรัน
  2. ตรวจ: อ่านทั้งหกบรรทัด อันไหนผิด
  3. แก้บรรทัดนั้นใน dna.json ด้วยมือ
  4. เทียบกับสิ่งที่ Pomelli พูดถึงเว็บเดียวกัน
  1. 把 SITE 换成你熟悉的网站,运行。
  2. 检查:六行都读一遍,哪一行错了?
  3. 手动把 dna.json 里那一行改掉。
  4. 再和 Pomelli 对同一个网站的说法比一比。

2 Three ideas, and where each came from · สามไอเดีย กับที่มาของแต่ละอัน · 三个点子,以及每个是从哪来的

🇬🇧 English

Now the description goes back in, with a goal. Out come three campaigns.

The useful part is why. Each idea has to say which line of the description it leans on. An idea that cannot point at one is an idea about nobody.

🇹🇭 ไทย

คราวนี้เอาคำอธิบายใส่กลับเข้าไป พร้อมเป้าหมาย ผลที่ได้คือแคมเปญสามอัน

ส่วนที่มีประโยชน์คือ why ทุกไอเดียต้องบอกว่ามันอิงจากบรรทัดไหนของคำอธิบาย ไอเดียที่ชี้ไม่ได้ คือไอเดียที่ไม่ได้พูดถึงใครเลย

🇨🇳 中文

现在把那份描述连同一个目标再送回去,出来三个活动方案。

有用的是 why。每个点子都必须说出它靠的是描述里的哪一行。指不出来的点子,就是没有对象的点子。

📄 NEW FILE · dna2.py

"""dna2.py — turn the business description into campaign ideas."""
import json
import sys
import urllib.request

OLLAMA = "http://localhost:11434/api/chat"
MODEL = "llama3.2"
GOAL = "get more people to try one free lesson this month"

sys.stdout.reconfigure(encoding="utf-8")

IDEAS_PROMPT = """You are helping a small business plan its marketing.

The business, described in its own words:
{dna}

The goal: {goal}

Give exactly three campaign ideas as JSON: an object with the key "ideas",
holding a list of three objects. Each has: title, hook, why.
title is under six words. hook is one sentence a person would actually read.
why says which part of the description it leans on. Answer with JSON only."""


def ask_for_json(prompt):
    """One call to Ollama, with format=json so the answer is always parseable."""
    payload = json.dumps({
        "model": MODEL,
        "stream": False,
        "format": "json",
        "options": {"num_ctx": 8192, "temperature": 0.7},
        "messages": [{"role": "user", "content": prompt}],
    }).encode()
    request = urllib.request.Request(
        OLLAMA, data=payload, headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(request, timeout=900) as response:
        return json.loads(json.load(response)["message"]["content"])


def main():
    """Read yesterday's description, and ask for three ways to use it."""
    with open("dna.json", encoding="utf-8") as saved:
        dna = json.load(saved)

    # The description goes in as text, so the model reads it the way you would.
    described = ""
    for key, value in dna.items():
        described = described + key + ": " + str(value) + "\n"

    answer = ask_for_json(IDEAS_PROMPT.format(dna=described, goal=GOAL))
    ideas = answer["ideas"]

    with open("ideas.json", "w", encoding="utf-8") as saved:
        json.dump(ideas, saved, ensure_ascii=False, indent=2)

    for number, idea in enumerate(ideas, start=1):
        print(number, "-", idea["title"])
        print("   hook:", idea["hook"])
        print("   why :", idea["why"])
        print()

    print("saved: ideas.json")


if __name__ == "__main__":
    main()
LineWhat it does · ทำอะไร · 做什么
described = described + key + ": " + str(value)The description goes in as plain text. The model reads it as you would.คำอธิบายใส่เข้าไปเป็นข้อความธรรมดา โมเดลจะได้อ่านแบบเดียวกับคุณ描述以纯文字送进去,模型就和你一样地读它。
why says which part of the description it leans on.Asking for the reason stops it inventing a business you never had.การขอเหตุผลคือสิ่งที่กันไม่ให้มันแต่งธุรกิจที่คุณไม่ได้ทำขึ้นมา要它给理由,才挡得住它凭空编出一门你没有的生意。
"temperature": 0.7Higher than step 1. Describing wants care. Suggesting wants a little nerve.สูงกว่าขั้นที่ 1 การบรรยายต้องการความระมัดระวัง การเสนอไอเดียต้องการความกล้านิดหน่อย比第 1 步高。描述需要谨慎,出点子需要一点胆子。

🖥️ WHAT IT PRINTED · a real run

1 - Thai Learner Challenge
   hook: Want to improve your English in just 10 minutes a day?
   why : friendly and interactive tone

2 - Free Lesson Friday
   hook: Kickstart your English learning journey with a FREE lesson every Friday!
   why : offer of free English lessons

3 - No-Cost Boost
   hook: Unlock the power of AI-powered tools for FREE!
   why : avoidance of expensive courses
IT PROMISED A FRIDAY NOBODY AGREED TO Look at idea two. A free lesson every Friday. Nothing on the website says that. The model made it up. It sounded like marketing. This is the ordinary failure, not a rare one. Every line has to be true before it leaves your laptop. ดูไอเดียที่สอง เรียนฟรีทุกวันศุกร์ ไม่มีอะไรในเว็บไซต์บอกแบบนั้นเลย โมเดลแต่งขึ้นมาเองเพราะมันฟังดูเหมือนการตลาด นี่คือความผิดพลาดแบบธรรมดา ไม่ใช่ของหายาก ทุกบรรทัดต้องเป็นเรื่องจริงก่อนที่มันจะออกจากแล็ปท็อปของคุณ 看第二个点子:每周五一节免费课。网站上根本没这回事,模型编出来是因为它听起来像营销话术。这是很普通的失误,不是稀罕事。每一行都必须是真的,才能离开你的笔记本。
YOUR TURN
  1. Change GOAL to something your business actually wants.
  2. Run it. Check: does every why point at a real line?
  3. Find one promise the business never made. There is usually one.
  4. Run it twice. The ideas change. That tells you how firm they are.
  1. เปลี่ยน GOAL เป็นสิ่งที่ธุรกิจของคุณอยากได้จริง ๆ
  2. รันดู ตรวจ: ทุก why ชี้ไปที่บรรทัดจริงหรือเปล่า
  3. หาคำสัญญาที่ธุรกิจไม่เคยให้ไว้ มักจะมีสักอัน
  4. รันสองครั้ง ไอเดียจะเปลี่ยน นั่นบอกคุณว่ามันหนักแน่นแค่ไหน
  1. 把 GOAL 换成你生意真正想要的东西。
  2. 运行。检查:每个 why 都指向真实的那一行吗?
  3. 找出一个这门生意从没许过的承诺。通常总有一个。
  4. 跑两次,点子会变。这告诉你它们有多靠得住。

🇹🇭 Tutorial 3 — The part Pomelli cannot do for you · บทที่ 3 — ส่วนที่ Pomelli ทำให้คุณไม่ได้ · 教程 3 —— Pomelli 替你做不了的那部分

🇬🇧 English

Pomelli writes in English. Your customers may not read it.

The same file writes in both, and swapping the model changes how good the Thai is. That difference is worth measuring, so we did.

🇹🇭 ไทย

Pomelli เขียนเป็นภาษาอังกฤษ ลูกค้าของคุณอาจอ่านไม่ออก

ไฟล์เดียวกันเขียนได้ทั้งสองภาษา และการเปลี่ยนโมเดลทำให้ภาษาไทยดีขึ้นหรือแย่ลง ความต่างนั้นวัดได้ เราจึงวัดมา

🇨🇳 中文

Pomelli 只写英文,而你的客人可能看不懂。

同一个文件两种语言都写,而换一个模型,泰文的好坏就不一样。这个差别是可以量的,所以我们量了。

3 Write the post, in two languages · เขียนโพสต์ สองภาษา · 把帖子写出来,两种语言

🇬🇧 English

One idea, the description, and a rule against inventing anything. Out comes the post, twice.

The address and the model are read from the terminal, so the same file can borrow a bigger model on another machine.

🇹🇭 ไทย

หนึ่งไอเดีย คำอธิบาย และกฎห้ามแต่งเรื่องขึ้นมาเอง ผลที่ได้คือโพสต์ สองภาษา

ที่อยู่กับชื่อโมเดลอ่านมาจากเทอร์มินัล ไฟล์เดียวกันจึงยืมโมเดลใหญ่กว่า จากอีกเครื่องมาใช้ได้

🇨🇳 中文

一个点子、那份描述,外加一条不许瞎编的规矩,出来一条帖子,两种语言。

地址和模型名从终端读进来,所以同一个文件可以去借另一台机器上更大的模型。

📄 NEW FILE · dna3.py

"""dna3.py — write the post, in English and in Thai."""
import json
import os
import sys
import urllib.request

# Point these at another machine to borrow a bigger model. A model that knows
# Thai well is worth the trip: a small English model writes stiff Thai.
OLLAMA = os.environ.get("OLLAMA_URL", "http://localhost:11434/api/chat")
MODEL = os.environ.get("OLLAMA_MODEL", "llama3.2")
IDEA = 1          # which of the three ideas to write up

sys.stdout.reconfigure(encoding="utf-8")

POST_PROMPT = """Write one short social media post for this business.

The business:
{dna}

The campaign:
title: {title}
hook: {hook}

Rules. Keep the tone the business already uses. Use its three words if they
fit. Do not invent prices, dates or promises the business did not make.

Answer as JSON with two keys: english and thai. Each is the whole post,
under forty words, ready to paste. The thai one must be natural Thai, not
a word for word translation. Answer with JSON only."""


def ask_for_json(prompt):
    """One call to Ollama, with format=json so the answer is always parseable."""
    payload = json.dumps({
        "model": MODEL,
        "stream": False,
        "format": "json",
        "options": {"num_ctx": 8192, "temperature": 0.7},
        "messages": [{"role": "user", "content": prompt}],
    }).encode()
    request = urllib.request.Request(
        OLLAMA, data=payload, headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(request, timeout=900) as response:
        return json.loads(json.load(response)["message"]["content"])


def pick(answer, wanted):
    """Find one key, whatever case or spacing the model chose for it.

    format=json promises valid JSON. It does not promise the keys you asked
    for, and the same model does not use the same ones twice. Asking for
    "thai" has come back as "thai" on one run and "thailand" on the next.
    """
    for key in answer:
        if key.strip().lower() == wanted:
            return answer[key]
    return None


def has(answer, wanted):
    """Did the model actually give us this one?"""
    return pick(answer, wanted) is not None


def main():
    """Take one idea and the description, and write the post twice."""
    with open("dna.json", encoding="utf-8") as saved:
        dna = json.load(saved)
    with open("ideas.json", encoding="utf-8") as saved:
        ideas = json.load(saved)

    idea = ideas[IDEA - 1]

    described = ""
    for key, value in dna.items():
        described = described + key + ": " + str(value) + "\n"

    prompt = POST_PROMPT.format(
        dna=described, title=idea["title"], hook=idea["hook"])

    # Ask again if the keys came back wrong. The model is not the same twice,
    # so the second try often lands even though nothing changed.
    post = None
    for attempt in range(3):
        answer = ask_for_json(prompt)
        if has(answer, "english") and has(answer, "thai"):
            post = answer
            break
        print("try", attempt + 1, "came back with:", ", ".join(answer.keys()))
    if post is None:
        raise SystemExit("Three tries, and never both keys. Try another model.")

    print("model:", MODEL)
    print("idea :", idea["title"])
    print()
    print("--- English")
    print(pick(post, "english"))
    print()
    print("--- ไทย")
    print(pick(post, "thai"))

    with open("post.json", "w", encoding="utf-8") as saved:
        json.dump(post, saved, ensure_ascii=False, indent=2)


if __name__ == "__main__":
    main()
LineWhat it does · ทำอะไร · 做什么
OLLAMA = os.environ.get("OLLAMA_URL", "http://localhost:11434/api/chat")Your machine by default. Point it elsewhere without touching the file.ปกติใช้เครื่องคุณเอง จะชี้ไปที่อื่นก็ได้โดยไม่ต้องแก้ไฟล์默认用你自己的机器。想指到别处,不用动文件。
def pick(answer, wanted):Find the key whatever case the model chose. See the warning below.หาคีย์ให้เจอไม่ว่าโมเดลจะใช้ตัวพิมพ์แบบไหน ดูคำเตือนข้างล่าง不管模型用什么大小写,都要找到那个键。看下面的警告。
for attempt in range(3):Ask again if the keys came back wrong. The model is not the same twice.ถามใหม่ถ้าคีย์กลับมาผิด โมเดลไม่เหมือนเดิมสองครั้ง键不对就再问一次。模型两次不会一模一样。
Do not invent prices, dates or promisesSay it in the prompt. It does not always listen, but it listens more often.เขียนไว้ในพรอมต์เลย มันไม่ได้เชื่อฟังทุกครั้ง แต่เชื่อฟังบ่อยขึ้น在提示词里写明。它不是每次都听,但听的次数会变多。

🖥️ THE SMALL ENGLISH MODEL · llama3.2, on the laptop

--- English
Want to improve your English in just 10 minutes a day? Join our Thai
Learner Challenge and get free English lessons and tools!

--- ไทย
ลองฝึกภาษาอังกฤษ 10 นาทีต่อวัน สังเกตผลเปลี่ยนแปลงของคุณ!
เรามีคำแนะนำและเครื่องมือฟรีให้คุณเริ่มต้น

🖥️ A MODEL THAT KNOWS THAI · typhoon2.1-gemma3-12b, same file

--- English
Want to improve your English in just 10 mins a day? The Thai Learner
Challenge is on! Join now for free English lessons & AI-powered tools.

--- ไทย
อยากพัฒนาการใช้ภาษาอังกฤษใน 10 นาทีต่อวันไหม ลองดู Thai Learner
Challenge กัน! มีบทเรียนฟรีและเครื่องมือ AI ที่ช่วยคุณได้
มาเรียนอังกฤษง่าย ๆ ออนไลน์กันเถอะ!
format json PROMISES VALID JSON, NOT YOUR KEYS Both runs came back as proper JSON. One of them named the second key thailand instead of thai. The first version of this file died on it. The model does not choose the same names twice. Look the key up loosely. Check it arrived. Ask again if it did not. การรันทั้งสองครั้งได้ JSON ที่ถูกต้องกลับมา แต่ครั้งหนึ่งมันตั้งชื่อคีย์ที่สองว่า thailand แทนที่จะเป็น thai และไฟล์นี้เวอร์ชันแรกก็ตายตรงนั้น โมเดลไม่ได้เลือกชื่อเดิมสองครั้ง ให้ค้นหาคีย์แบบหลวม ๆ ตรวจว่ามันมาจริง แล้วถามใหม่ถ้ามันไม่มา 两次运行回来的都是合法 JSON。但其中一次把第二个键叫成了 thailand 而不是 thai,这个文件的第一版就死在那里。模型不会两次选一样的名字。用宽松的方式找键,确认它到了,没到就再问一次。
READ IT BEFORE ANYBODY ELSE DOES In one run the bigger model wrote Thai Learmer Challenge. In another it said ten minutes per second. Better Thai is not correct Thai. Somebody who speaks the language must read every post. Before it goes out. มีรันหนึ่งที่โมเดลตัวใหญ่เขียนว่า Thai Learmer Challenge และอีกรันหนึ่งเขียนภาษาไทยว่าสิบนาทีต่อวินาที ภาษาไทยที่ดีขึ้น ไม่ได้แปลว่าภาษาไทยที่ถูกต้อง ต้องมีคนที่ใช้ภาษานั้นจริงอ่านทุกโพสต์ก่อนปล่อยออกไป 有一次那个更大的模型写成了 Thai Learmer Challenge,另一次把十分钟写成了每秒十分钟。泰文更好,不等于泰文正确。每一条帖子发出去之前,都要有一个真正会这门语言的人读过。
YOUR TURN
  1. Run it as it is, on your own machine.
  2. Run it again pointed at a bigger model, if you can reach one.
  3. Check: read both Thai posts aloud. Which sounds like a person?
  4. Change IDEA to 2 and write up the second campaign.
  1. รันตามที่เป็นอยู่ บนเครื่องของคุณเอง
  2. รันอีกครั้งโดยชี้ไปที่โมเดลใหญ่กว่า ถ้าคุณเข้าถึงได้
  3. ตรวจ: อ่านโพสต์ภาษาไทยทั้งสองออกเสียงดู อันไหนฟังเหมือนคนเขียน
  4. เปลี่ยน IDEA เป็น 2 แล้วเขียนแคมเปญที่สอง
  1. 就照原样,在你自己机器上跑一次。
  2. 如果你能连到更大的模型,再指过去跑一次。
  3. 检查:把两段泰文都念出来。哪一段像人写的?
  4. 把 IDEA 改成 2,把第二个活动写出来。

🇬🇧 English

Pomelli is the easier of the two, and for English it is very good. Use it if it fits.

What the three files give you instead is control. The description is a file you can edit. The language is yours to choose. Nothing is sent to anybody.

And the thing both share: neither one knows what is true about your business. You do, and that is the job the tool cannot take.

🇹🇭 ไทย

Pomelli ง่ายกว่าในสองทางนี้ และถ้าเป็นภาษาอังกฤษมันเก่งมาก ถ้ามันเหมาะกับคุณก็ใช้เลย

สิ่งที่สามไฟล์นั้นให้แทนคือการควบคุม คำอธิบายเป็นไฟล์ที่คุณแก้ได้ ภาษาเป็นของคุณที่จะเลือก และไม่มีอะไรถูกส่งไปหาใคร

และสิ่งที่ทั้งสองทางเหมือนกัน คือไม่มีอันไหนรู้ว่าอะไรจริงเกี่ยวกับธุรกิจของคุณ คุณรู้ และนั่นคืองานที่เครื่องมือรับไปแทนไม่ได้

🇨🇳 中文

两者之中 Pomelli 更省事,英文内容它做得很好。合适就用。

那三个文件给你的是另一样东西:控制权。描述是一个你可以改的文件,语言由你选,而且什么都不会发给别人。

它们的共同点是:两边都不知道关于你生意什么才是真的。你知道,而这正是工具替不了你的那份活。

('You want', 'คุณอยากได้', '你想要')('Look up', 'ไปหาคำว่า', '去查')
Pictures, not just wordsรูปภาพ ไม่ใช่แค่ข้อความ图片,不只是文字Pomelli, or the Spark image pagesPomelli หรือหน้าสร้างภาพด้วย SparkPomelli,或者 Spark 那几页生图的教程
The same post for five placesโพสต์เดียวลงห้าที่同一条帖子发五个地方one more key in the promptเพิ่มคีย์อีกอันในพรอมต์提示词里多加一个键
It to run every Mondayให้มันทำงานทุกวันจันทร์让它每周一自己跑the n8n pageหน้า n8nn8n 那一页
Better Thai than thisภาษาไทยที่ดีกว่านี้比这更好的泰文a model trained on Thaiโมเดลที่ฝึกมากับภาษาไทย用泰文训练过的模型

Fifteen lines, your own address, and an app password. That is the whole trick. · สิบห้าบรรทัด อีเมลของคุณเอง และ app password หนึ่งอัน เคล็ดลับมีแค่นี้ · 十五行代码、你自己的邮箱地址,加一个应用专用密码。诀窍就这些。

The three Python files on this page were run on 22 September 2026 against the live krueng.ai and a local Ollama, and every output shown is copied from those runs, including the free Friday lesson the model invented and the run where it renamed a JSON key to thailand. The Pomelli half is different and is marked as such: it is drawn from Google Labs own documentation and from the sign-in page, because Pomelli sits behind a Google account and we did not sign in to generate marketing under anybody else name. Availability, price and language were checked on Google Labs help pages on that date and all three can change.