<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>edge49</title>
        <link>https://paragraph.com/@edge49</link>
        <description>Forest night</description>
        <lastBuildDate>Fri, 17 Apr 2026 03:57:07 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>edge49</title>
            <url>https://storage.googleapis.com/papyrus_images/4a7c97209b15243925c3d73687191ad8f7d271f74dacc20900e2cb2a72562a03.png</url>
            <link>https://paragraph.com/@edge49</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[与AI共生20250326：想建构自己的MCP服务]]></title>
            <link>https://paragraph.com/@edge49/ai-20250326-mcp</link>
            <guid>2OsiyA9T1LncDDX2S2Wf</guid>
            <pubDate>Wed, 26 Mar 2025 10:14:45 GMT</pubDate>
            <description><![CDATA[I： 你好，我在本地离线部署了一些人工智能大模型，用我电脑上的显卡运行，使用ollama作为启动工具，可以通过API调用在自己写的应用程序中与这些大模型进行交互。现在我想在本地电脑上离线（也可以访问网络）构建自己 MCP服务，以自动化操纵指定的网站为例子：我的想法是，先向本地大模型提供要操纵的网页的内容（实时的html源内容），要求本地大模型提供一个可以执行的javascript或者python脚本文件代码，用于操纵这个网页指定的部分（比如抓取主要内容），如果执行这一步之后，网页内容又有了新的变化 ，又提供新的实时Html源代码给大模型，要求继续完成后续操作。我的设想的主要部分在于：让本地大模型写出调用Playwright库的js代码脚本或python代码脚本，我也不清楚，Playwright库是否用js可用的库以上是我的初步设想，没有经过验证，或者你有更好的想法？ Gemini2.0Flash: 你的想法很有意思，可行性较高，并且结合了本地大模型和 Playwright 的优势，可以在一定程度上实现自动化网页操作。下面我将分析你的设想，提出一些建议和补充，并探讨更好的方法： 对...]]></description>
            <content:encoded><![CDATA[<p>I：</p><p>你好，我在本地离线部署了一些人工智能大模型，用我电脑上的显卡运行，使用ollama作为启动工具，可以通过API调用在自己写的应用程序中与这些大模型进行交互。现在我想在本地电脑上离线（也可以访问网络）构建自己 MCP服务，以自动化操纵指定的网站为例子：我的想法是，先向本地大模型提供要操纵的网页的内容（实时的html源内容），要求本地大模型提供一个可以执行的javascript或者python脚本文件代码，用于操纵这个网页指定的部分（比如抓取主要内容），如果执行这一步之后，网页内容又有了新的变化 ，又提供新的实时Html源代码给大模型，要求继续完成后续操作。我的设想的主要部分在于：让本地大模型写出调用Playwright库的js代码脚本或python代码脚本，我也不清楚，Playwright库是否用js可用的库以上是我的初步设想，没有经过验证，或者你有更好的想法？</p><p>Gemini2.0Flash:</p><p>你的想法很有意思，可行性较高，并且结合了本地大模型和 Playwright 的优势，可以在一定程度上实现自动化网页操作。下面我将分析你的设想，提出一些建议和补充，并探讨更好的方法：</p><p><strong>对你设想的分析：</strong></p><ul><li><p><strong>优势：</strong></p><ul><li><p><strong>离线部署：</strong> 保护数据隐私，降低对网络依赖。</p></li><li><p><strong>大模型驱动：</strong> 利用大模型的理解和生成能力，自动生成脚本。</p></li><li><p><strong>Playwright：</strong> 提供可靠的网页控制能力，支持多种浏览器。</p></li><li><p><strong>动态适应：</strong> 能够根据网页内容变化动态调整操作。</p></li></ul></li><li><p><strong>可能遇到的问题：</strong></p><ul><li><p><strong>大模型能力：</strong> 大模型能否准确理解网页结构和需求，并生成正确的 Playwright 代码？这取决于模型的训练数据和提示词设计。</p></li><li><p><strong>错误处理：</strong> 大模型生成的代码可能存在错误，需要进行测试和调试，并设计相应的错误处理机制。</p></li><li><p><strong>网页复杂度：</strong> 对于复杂的网页，大模型可能难以生成完整的操作脚本，需要进行分解和逐步完成。</p></li><li><p><strong>安全性：</strong> 执行大模型生成的代码可能存在安全风险，需要进行代码审计和沙箱环境隔离。</p></li><li><p><strong>Playwright 的学习曲线：</strong> 大模型可能需要经过一定的训练才能掌握 Playwright 的 API 和最佳实践。</p></li><li><p><strong>状态管理：</strong> 如何维护网页操作的状态，例如登录状态、Cookie 等，需要在设计中考虑。</p></li></ul></li></ul><p><strong>建议和补充：</strong></p><ol><li><p><strong>细化提示词：</strong> 提示词的设计至关重要，需要明确指示大模型生成 Playwright 代码，并提供足够的上下文信息，例如：</p><ul><li><p>明确指定编程语言（JavaScript 或 Python）。</p></li><li><p>提供要操作的网页的 HTML 源代码。</p></li><li><p>详细描述要完成的任务，例如“抓取商品名称和价格”，“点击“加入购物车”按钮”。</p></li><li><p>提供示例代码片段，帮助大模型理解你的期望。</p></li><li><p>指定代码风格和格式要求。</p></li></ul></li><li><p><strong>分步执行：</strong> 将复杂的任务分解成多个简单的步骤，逐步执行，并根据每一步的结果调整后续操作。</p></li><li><p><strong>验证机制：</strong> 在执行大模型生成的代码之前，进行初步的验证，例如检查代码的语法是否正确，是否包含敏感操作。</p></li><li><p><strong>错误处理：</strong> 在执行代码时，捕获异常，并提供错误信息给大模型，让其进行自我修复。</p></li><li><p><strong>人工干预：</strong> 对于难以自动完成的任务，允许人工干预，并记录人工操作，用于训练大模型。</p></li><li><p><strong>使用 Prompt Engineering 技巧：</strong></p><ul><li><p><strong>Few-shot learning：</strong> 提供几个示例输入和对应的 Playwright 代码，让大模型学习。</p></li><li><p><strong>Chain-of-thought prompting：</strong> 引导大模型一步一步地思考，并解释每一步的决策过程。</p></li><li><p><strong>Self-consistency：</strong> 让大模型生成多个代码片段，然后选择最可靠的一个。</p></li></ul></li></ol><p><strong>关于 Playwright 和 JavaScript：</strong></p><ul><li><p><strong>Playwright 支持 JavaScript 和 Python。</strong> 你可以使用 JavaScript (Node.js) 或 Python 来编写 Playwright 脚本。</p></li><li><p>JavaScript 是前端的通用语言，Playwright 本身也是用 JavaScript 编写的，因此使用 JavaScript 更加自然。</p></li><li><p>Python 具有更强大的生态系统，例如数据分析、机器学习等，如果你需要对抓取的数据进行处理，Python 可能更适合。</p></li><li><p>Ollama 可以使用 Javascript 和 Python。</p></li></ul><p><strong>更好的想法：</strong></p><ol><li><p><strong>结合视觉信息：</strong> 除了 HTML 源代码，还可以将网页的截图提供给大模型，帮助其更准确地理解网页的布局和内容。</p></li><li><p><strong>使用选择器辅助工具：</strong> 开发一个辅助工具，让用户手动选择要操作的网页元素，然后将选择器信息提供给大模型，减少大模型理解网页结构的难度。</p></li><li><p><strong>构建领域特定语言 (DSL)：</strong> 定义一种简单的 DSL，用于描述网页操作，然后让大模型将 DSL 代码转换成 Playwright 代码。</p></li><li><p><strong>使用更强大的大模型：</strong> 考虑使用专门针对代码生成的模型，例如 Codex (现在集成到 GitHub Copilot 中)。</p></li><li><p><strong>反馈循环：</strong> 建立一个反馈循环，根据代码的执行结果，不断调整提示词和模型参数，提高代码生成的准确率。</p></li><li><p><strong>使用记录回放工具 + 大模型重构:</strong> Playwright 本身就带有代码生成工具，可以录制用户的操作，然后生成 playwright 的代码。你可以先手动操作一遍，然后使用 Playwright 代码生成工具导出代码，然后将导出的代码给大模型，让大模型做优化和改造，并添加容错逻辑。</p></li></ol><p><strong>总结:</strong></p><p>你的想法很有潜力，但是需要进行仔细的设计和测试，才能实现自动化网页操作。关键在于如何有效地利用大模型的能力，并结合 Playwright 的功能，最终构建一个可靠、灵活的 MCP 服务。</p><p><strong>行动建议：</strong></p><ol><li><p><strong>选择编程语言：</strong> 根据你的需求和熟悉程度，选择 JavaScript 或 Python。</p></li><li><p><strong>设计提示词：</strong> 从简单的任务开始，逐步增加复杂度，不断优化提示词。</p></li><li><p><strong>测试和调试：</strong> 编写测试用例，对大模型生成的代码进行充分的测试和调试。</p></li><li><p><strong>收集数据：</strong> 记录失败的案例，分析原因，并用于改进模型。</p></li><li><p><strong>迭代开发：</strong> 不断迭代，逐步完善 MCP 服务的功能和性能。</p></li></ol><p>祝你成功！</p><p>I:</p><p>谢谢你，你的建议与鼓励对我很有帮助。我对上面你提到的构建领域特定语言 (DSL)： 定义一种简单的 DSL，用于描述网页操作，然后让大模型将 DSL 代码转换成 Playwright 代码。这一部分不是很了解，没有听说过这方面的内容，你能简单介绍一下什么是DSL吗？</p><p>Gemini2.0Flash:</p><p>当然，很乐意为你详细介绍一下领域特定语言（DSL）：</p><p><strong>什么是领域特定语言 (DSL)？</strong></p><p>领域特定语言（Domain-Specific Language，简称 DSL）是一种专门为解决特定领域问题而设计的编程语言或标记语言。与通用编程语言（如 Python、Java、C++）不同，DSL 专注于特定的领域，并提供针对该领域的概念、语法和操作。</p><p><strong>DSL 的特点：</strong></p><ul><li><p><strong>目标明确：</strong> DSL 旨在解决特定领域的问题，而不是像通用语言那样适用于各种场景。</p></li><li><p><strong>语法简洁：</strong> DSL 的语法通常比通用语言更简洁、更易于理解，因为它只包含该领域所需的元素。</p></li><li><p><strong>表达力强：</strong> DSL 能够以更自然、更直观的方式表达领域内的概念和操作。</p></li><li><p><strong>易于学习：</strong> 由于语法简单，DSL 通常比通用语言更容易学习和使用。</p></li><li><p><strong>提高效率：</strong> 使用 DSL 可以减少代码量，提高开发效率，并降低出错的风险。</p></li></ul><p><strong>DSL 的类型：</strong></p><ul><li><p><strong>内部 DSL (Internal DSL)：</strong> 内部 DSL 是基于现有通用语言实现的，利用该语言的语法和特性来定义领域特定的语法和操作。例如，使用 Ruby 的元编程能力来创建内部 DSL。</p></li><li><p><strong>外部 DSL (External DSL)：</strong> 外部 DSL 是一种独立的语言，具有自己的语法和解析器。例如，SQL 是一种用于数据库查询的外部 DSL。</p></li></ul><p><strong>DSL 的用途：</strong></p><p>DSL 可以用于各种领域，例如：</p><ul><li><p><strong>网页开发：</strong> 用于描述网页布局、样式和交互行为，例如 HTML、CSS、JavaScript。</p></li><li><p><strong>数据查询：</strong> 用于查询和操作数据库，例如 SQL。</p></li><li><p><strong>构建自动化：</strong> 用于描述软件构建过程，例如 Maven、Gradle。</p></li><li><p><strong>规则引擎：</strong> 用于定义业务规则，例如 Drools。</p></li><li><p><strong>模型驱动开发：</strong> 用于描述软件模型，例如 UML。</p></li></ul><p><strong>在你的场景中，如何使用 DSL？</strong></p><p>你可以设计一种 DSL，用于描述网页操作，例如：</p><pre data-type="codeBlock" text="// DSL 示例
操作 登录 {
  类型: 点击
  目标: 元素(&quot;id=login_button&quot;)
}

操作 输入用户名 {
  类型: 输入
  目标: 元素(&quot;id=username&quot;)
  内容: &quot;your_username&quot;
}

操作 输入密码 {
  类型: 输入
  目标: 元素(&quot;id=password&quot;)
  内容: &quot;your_password&quot;
}

操作 提交 {
  类型: 点击
  目标: 元素(&quot;id=submit_button&quot;)
}

操作 抓取商品信息 {
  类型: 抓取
  目标: 元素(&quot;.product-item&quot;)
  属性: [&quot;名称&quot;, &quot;价格&quot;]
}
"><code>// DSL 示例
操作 登录 {
  类型: 点击
  目标: 元素(<span class="hljs-string">"id=login_button"</span>)
}

操作 输入用户名 {
  类型: 输入
  目标: 元素(<span class="hljs-string">"id=username"</span>)
  内容: <span class="hljs-string">"your_username"</span>
}

操作 输入密码 {
  类型: 输入
  目标: 元素(<span class="hljs-string">"id=password"</span>)
  内容: <span class="hljs-string">"your_password"</span>
}

操作 提交 {
  类型: 点击
  目标: 元素(<span class="hljs-string">"id=submit_button"</span>)
}

操作 抓取商品信息 {
  类型: 抓取
  目标: 元素(<span class="hljs-string">".product-item"</span>)
  属性: [<span class="hljs-string">"名称"</span>, <span class="hljs-string">"价格"</span>]
}
</code></pre><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/224554d460901b08eb23ddb47b1ff5bbffe5b50e852271ed88f93b1f91a6bd62.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>这个 DSL 使用简单的键值对来描述网页操作，例如 操作、类型、目标、内容 等。你可以根据你的需求定义更多的操作类型和属性。</p><p><strong>使用 DSL 的好处：</strong></p><ul><li><p><strong>简化大模型的工作：</strong> 大模型只需要将 DSL 代码转换成 Playwright 代码，而不需要理解复杂的网页结构和操作逻辑。</p></li><li><p><strong>提高代码的可读性和可维护性：</strong> DSL 代码比 Playwright 代码更易于理解和修改。</p></li><li><p><strong>降低出错的风险：</strong> DSL 的语法更简单，可以减少编写错误代码的可能性。</p></li><li><p><strong>更容易进行自动化测试：</strong> 可以使用 DSL 代码来描述测试用例，并自动执行测试。</p></li></ul><p><strong>如何实现 DSL？</strong></p><ol><li><p><strong>定义 DSL 语法：</strong> 确定 DSL 的关键字、操作类型、属性等。</p></li><li><p><strong>编写解析器：</strong> 使用工具（如 ANTLR、PLY）或手动编写解析器，将 DSL 代码转换成抽象语法树 (AST)。</p></li><li><p><strong>编写代码生成器：</strong> 遍历 AST，生成 Playwright 代码。</p></li></ol><p><strong>与大模型结合：</strong></p><ol><li><p><strong>提示词：</strong> 提供 DSL 语法和示例代码给大模型。</p></li><li><p><strong>任务分解：</strong> 将任务分解成 DSL 代码生成和 Playwright 代码生成两个步骤。</p></li><li><p><strong>训练数据：</strong> 收集 DSL 代码和对应的 Playwright 代码，用于训练大模型。</p></li></ol><p><strong>总结：</strong></p><p>DSL 是一种强大的工具，可以帮助你简化网页自动化任务，并提高效率。虽然实现 DSL 需要一定的工作量，但它可以带来长期的收益。通过将 DSL 与大模型结合，你可以构建一个更加智能、灵活的 MCP 服务。</p><p>I:</p><p>谢谢你，你解释得非常仔细，我一下子就看懂了，原来我早就使用过DSL语言了，像SQL语言是早就用过的了。你的解释又给了我更多的想法与灵感，谢谢你。我现在开始去尝试实践。有新问题或新想法再来与你交流。</p><p>Gemini2.0Flash:</p><p>很高兴我的解释对你有所帮助！ 实践是检验真理的唯一标准，期待你的实践成果。 非常欢迎你随时来交流新的问题和想法。 祝你一切顺利！</p><div data-type="youtube" videoId="w-13Jq9ULJc">
      <div class="youtube-player" data-id="w-13Jq9ULJc" style="background-image: url('https://i.ytimg.com/vi/w-13Jq9ULJc/hqdefault.jpg'); background-size: cover; background-position: center">
        <a href="https://www.youtube.com/watch?v=w-13Jq9ULJc">
          <img src="{{DOMAIN}}/editor/youtube/play.png" class="play"/>
        </a>
      </div></div>]]></content:encoded>
            <author>edge49@newsletter.paragraph.com (edge49)</author>
        </item>
        <item>
            <title><![CDATA[Forest]]></title>
            <link>https://paragraph.com/@edge49/forest</link>
            <guid>UbrKwCMi7IFPNu1Y8Kud</guid>
            <pubDate>Fri, 01 Sep 2023 11:46:21 GMT</pubDate>
            <description><![CDATA[As the sun sinks below the horizon, dusk settles over the forest. Sparse moonlight filters through the trees, casting a mottled silver glow on the ground. A gentle breeze blows by, rustling the leaves with a serene melody. Occasional bird calls ring out clearly in the stillness. The forest creatures gradually settle in for the night, with only the drone of insects continuing unabated. Walking along the forest path, surrounded by dark tranquility, one feels a sense of mystery and comfort. Look...]]></description>
            <content:encoded><![CDATA[<p>As the sun sinks below the horizon, dusk settles over the forest. Sparse moonlight filters through the trees, casting a mottled silver glow on the ground.</p><p>A gentle breeze blows by, rustling the leaves with a serene melody. Occasional bird calls ring out clearly in the stillness. The forest creatures gradually settle in for the night, with only the drone of insects continuing unabated.</p><p>Walking along the forest path, surrounded by dark tranquility, one feels a sense of mystery and comfort. Looking up, the canopy obscures much of the night sky, revealing just a spattering of stars.</p><p>Moonlight and starlight intermingle, adding a touch of dreamlike quality to the night. The cool, fresh air is redolent with the scents of grass and trees.</p><p>The whole forest slumbers in the quiet of night, awaiting the return of dawn.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4a7c97209b15243925c3d73687191ad8f7d271f74dacc20900e2cb2a72562a03.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure>]]></content:encoded>
            <author>edge49@newsletter.paragraph.com (edge49)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/a7ce528b6050c06047e50ac642fc153653809531aa6fc497672d07ca03175abb.jpg" length="0" type="image/jpg"/>
        </item>
    </channel>
</rss>