【笔记】用cursor手搓cursor(四)

最近claude实行了新的定价,导致cursor也跟着改价格表。

claude的使用额度开始减少,于是尝试了一下让gemini-3-pro这样的便宜模型。

发现cursor是强绑定claude,一方面是claude的编程知识是真的丰富,它在解决问题的时候如果文档不齐全它会尽可能去猜测完成任务,而gemini-3-pro更像一个等待指令的worker,cursor和gemini的集成简直差到极点了。

原本如果cursor认真去做各种模型集成,然后让不同模型能取长补短。但现在是cursor专注于和claude集成,claude又出了自家claude code。感觉cursor离出局不远了。

所以最近宕开一笔,开始思考如何设计agent和小模型配合。

用了claude code,发现确实效果好了一些。对于9B和35B,真实场景下还是不能达到很好思考效果,即便是claude code,也会不停遇到要么request timeout了,要么在一些奇怪的地方打转,要么是提早就结束了任务,非常不稳定。即便claude code被迫开源,它也无法解决模型的短板,最多是为agent的设计提供了些许思路。LLM的短板其实最终形态就是完全symbolic化,然后LLM只做glue和后台持续学习更新symbolic知识结构。我们得一步一步来,虽然不一定能赶超AI自己改进自己的速度。但是至少像anthropic这样的公司还是热衷于LLM训练改进的,这个时间差上,我们还能做很多事情。

最近开始专心学习专家系统,看了下lisp的一些程序,又在选型graph db,比来比去,放弃了java的neo4j;尝试了下nebulagraph,编译通过,但是没能简单在单机add hosts一次成功。考虑到单graph可能还要再配合下postgres,所以把精力花在了arangodb上面。

随便找了个ubuntu编译,还发现gcc 13和arangodb不搭,直接bypass了gcc版本check,然后让claude给了workaround。

复制代码
[ 12%] Building CXX object lib/Futures/CMakeFiles/arango_futures.dir/src/Future.cpp.o
In file included from /arangodb/src/lib/Futures/include/Futures/Future.h:32,
                 from /arangodb/src/lib/Futures/src/Future.cpp:24:
/arangodb/src/lib/Async/Registry/promise.h: In lambda function:
/arangodb/src/lib/Async/Registry/promise.h:106:29: error: use of deleted function 'arangodb::containers::AtomicSharedOrRawPtr<arangodb::basics::ThreadInfo, void>::AtomicSharedOrRawPtr(const arangodb::containers::AtomicSharedOrRawPtr<arangodb::basics::ThreadInfo, void>&)'
  106 |                      return AtomicRequester{ptr};
      |                             ^~~~~~~~~~~~~~~~~~~~
In file included from /arangodb/src/lib/Containers/Concurrent/thread.h:26,
                 from /arangodb/src/lib/Containers/Concurrent/ThreadOwnedList.h:25,
                 from /arangodb/src/lib/Async/Registry/promise.h:31:
/arangodb/src/lib/Containers/Concurrent/shared.h:140:8: note: 'arangodb::containers::AtomicSharedOrRawPtr<arangodb::basics::ThreadInfo, void>::AtomicSharedOrRawPtr(const arangodb::containers::AtomicSharedOrRawPtr<arangodb::basics::ThreadInfo, void>&)' is implicitly deleted because the default definition would be ill-formed:
  140 | struct AtomicSharedOrRawPtr {
      |        ^~~~~~~~~~~~~~~~~~~~
/arangodb/src/lib/Containers/Concurrent/shared.h:140:8: error: use of deleted function 'std::atomic<long unsigned int>::atomic(const std::atomic<long unsigned int>&)'
In file included from /usr/include/c++/13/stop_token:36,
                 from /usr/include/c++/13/condition_variable:49,
                 from /arangodb/src/lib/Futures/include/Futures/Future.h:27:
/usr/include/c++/13/atomic:898:7: note: declared here
  898 |       atomic(const atomic&) = delete;
      |       ^~~~~~
/arangodb/src/lib/Async/Registry/promise.h: In lambda function:
/arangodb/src/lib/Async/Registry/promise.h:108:53: error: use of deleted function 'arangodb::containers::AtomicSharedOrRawPtr<arangodb::basics::ThreadInfo, void>::AtomicSharedOrRawPtr(const arangodb::containers::AtomicSharedOrRawPtr<arangodb::basics::ThreadInfo, void>&)'
  108 |                    [](PromiseId const& id) { return AtomicRequester{id.id}; }},
      |                                                     ^~~~~~~~~~~~~~~~~~~~~~
make[2]: *** [lib/Futures/CMakeFiles/arango_futures.dir/build.make:76: lib/Futures/CMakeFiles/arango_futures.dir/src/Future.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:10734: lib/Futures/CMakeFiles/arango_futures.dir/all] Error 2
make: *** [Makefile:166: all] Error 2
cpp 复制代码
--- a/lib/Async/Registry/promise.h
+++ b/lib/Async/Registry/promise.h
@@ -101,12 +101,16 @@ using CurrentRequester =
 struct AtomicRequester
     : containers::AtomicSharedOrRawPtr<basics::ThreadInfo, void> {
+  using Base = containers::AtomicSharedOrRawPtr<basics::ThreadInfo, void>;
+  using Base::Base;
+
   static auto from(CurrentRequester req) -> AtomicRequester {
-    return std::visit(
-        overloaded{[](containers::SharedPtr<basics::ThreadInfo> const& ptr) {
-                     return AtomicRequester{ptr};
-                   },
-                   [](PromiseId const& id) { return AtomicRequester{id.id}; }},
-        req);
+    if (auto* ptr =
+            std::get_if<containers::SharedPtr<basics::ThreadInfo>>(&req)) {
+      return AtomicRequester(*ptr);
+    } else {
+      return AtomicRequester(std::get<PromiseId>(req).id);
+    }
   }
 };

还有v8引擎的avx错误,我的小破机的cpu不支持avx指令。

shell 复制代码
grep -o 'sse[^ ]|avx[^ ]' /proc/cpuinfo | sort -u
sse
sse2
sse3
sse4_1
sse4_2

直接把 -mavx 抹掉;之后还有 ##__VA_ARGS__,,用 __VA_OPT__(__VA_ARGS__,) 代替了。

让它慢慢去编译吧。这个只是之后大型知识库需要的东西。之后,当然是继续学习专家系统。现在有这么强的AI了,当然是靠它进行学习------

于是赶紧让它生成一个专家系统,去生成一段python程序,这个python程序需要生成一个python script去打印hello文本,让我们看看prompt和它的output吧:

复制代码
write a python script as an expert system to generate "hello, xxx" program in python. where "xxx" is an user input as arg like python hello.py xxx
it should build knolwedge like:

what is python program entry point
how to define python function
how to print a message with built-in package/functions
how to use string
how to import built-in package
how to define arg parser
how to use variable
what is a class, class instance and how to use instance members
what is function call
what is if clause, what is loop clause, what is variable assignment
...
it is not an easy generator. please think carefully. we can use sqlite3 to build a simple knowledge base. we need to write some planner and reasoner and resolver/executor/aggregator/generator to make everything together and generate the python code.
python 复制代码
#!/usr/bin/env python3
"""
Expert System for Python Code Generation
==========================================
Generates a "Hello, xxx" Python program using:
  - SQLite3 knowledge base (concepts, dependencies, rules, facts)
  - Forward-chaining inference engine (Reasoner)
  - Dependency-aware Planner
  - Template-driven CodeGenerator
  - Aggregator to assemble final output

Usage:
    python hello.py <name>

Example:
    python hello.py World
    -> writes generated_hello.py that prints "Hello, World!"
"""

import sqlite3
import sys
import os
import textwrap
from collections import OrderedDict


# ═══════════════════════════════════════════════════════════════════════════════
#  KNOWLEDGE BASE
# ═══════════════════════════════════════════════════════════════════════════════

class KnowledgeBase:
    """SQLite-backed knowledge base storing concepts, dependencies, rules, and
    runtime facts for the expert system."""

    def __init__(self, db_path=":memory:"):
        self.conn = sqlite3.connect(db_path)
        self.conn.row_factory = sqlite3.Row
        self._create_schema()
        self._seed_concepts()
        self._seed_dependencies()
        self._seed_rules()

    # ── schema ────────────────────────────────────────────────────────────────

    def _create_schema(self):
        c = self.conn.cursor()
        c.executescript("""
        CREATE TABLE IF NOT EXISTS concepts (
            id          TEXT PRIMARY KEY,
            name        TEXT NOT NULL,
            category    TEXT NOT NULL,       -- statement | expression | structure | module
            description TEXT,
            template    TEXT,               -- syntax pattern using <placeholder> markers
            params      TEXT                -- comma-separated parameter names
        );

        CREATE TABLE IF NOT EXISTS dependencies (
            parent_id   TEXT NOT NULL,
            child_id    TEXT NOT NULL,
            relation    TEXT NOT NULL,       -- requires | contains | type_of
            PRIMARY KEY (parent_id, child_id, relation),
            FOREIGN KEY (parent_id) REFERENCES concepts(id),
            FOREIGN KEY (child_id)  REFERENCES concepts(id)
        );

        CREATE TABLE IF NOT EXISTS rules (
            id          INTEGER PRIMARY KEY AUTOINCREMENT,
            name        TEXT NOT NULL,
            priority    INTEGER DEFAULT 10,
            description TEXT,
            conditions  TEXT NOT NULL,       -- semicolon-separated fact patterns  type:key=value
            assertions  TEXT NOT NULL        -- semicolon-separated new facts      type:key=value
        );

        CREATE TABLE IF NOT EXISTS facts (
            id          INTEGER PRIMARY KEY AUTOINCREMENT,
            type        TEXT NOT NULL,       -- goal | need | use | strategy | done | config
            key         TEXT NOT NULL,
            value       TEXT,
            confidence  REAL DEFAULT 1.0,
            UNIQUE(type, key, value)
        );

        CREATE TABLE IF NOT EXISTS code_parts (
            section     TEXT NOT NULL,       -- docstring | imports | functions | main | entry
            seq         INTEGER NOT NULL,
            code        TEXT NOT NULL,
            concept_id  TEXT,
            PRIMARY KEY (section, seq)
        );
        """)
        self.conn.commit()

    # ── seed: concepts ────────────────────────────────────────────────────────

    def _seed_concepts(self):
        concepts = [
            # ── module-level structures ──────────────────────────────────────
            ("mod_docstring",  "Module Docstring",        "module",
             "Triple-quoted string at the top of a module providing documentation",
             '"""<text>"""',  "text"),

            ("import_stmt",    "Import Statement",        "statement",
             "Brings an external or built-in module into the current namespace",
             "import <module>",  "module"),

            ("entry_point",    "Entry-Point Guard",       "structure",
             "if __name__ == '__main__' idiom --- the Python program entry point",
             'if __name__ == "__main__":\n    <body>',  "body"),

            # ── function-related ─────────────────────────────────────────────
            ("func_def",       "Function Definition",     "structure",
             "Defines a reusable block of code with def keyword",
             "def <fname>(<fparams>):\n    <fbody>",  "fname,fparams,fbody"),

            ("func_call",      "Function Call",           "expression",
             "Invokes a previously defined function with arguments",
             "<cname>(<cargs>)",  "cname,cargs"),

            ("return_stmt",    "Return Statement",        "statement",
             "Returns a value from a function to its caller",
             "return <rval>",  "rval"),

            ("func_docstring", "Function Docstring",      "statement",
             "Triple-quoted documentation string inside a function body",
             '"""<fdoc>"""',  "fdoc"),

            # ── variables & assignment ───────────────────────────────────────
            ("var_assign",     "Variable Assignment",     "statement",
             "Binds a value to a name using the = operator",
             "<vname> = <vval>",  "vname,vval"),

            # ── string expressions ───────────────────────────────────────────
            ("fstring",        "F-String",                "expression",
             "Formatted string literal with embedded expressions using f'...'",
             "f\"<ftpl>\"",  "ftpl"),

            ("string_lit",     "String Literal",          "expression",
             "A plain string value enclosed in quotes",
             "\"<sval>\"",  "sval"),

            # ── class-related ────────────────────────────────────────────────
            ("class_def",      "Class Definition",        "structure",
             "Defines a new type using the class keyword",
             "class <clsname>:\n    <clsbody>",  "clsname,clsbody"),

            ("class_inst",     "Class Instantiation",     "expression",
             "Creates an instance of a class by calling its constructor",
             "<ciname>(<ciargs>)",  "ciname,ciargs"),

            ("inst_attr",      "Instance Attribute Access","expression",
             "Accesses a member attribute of a class instance using dot notation",
             "<obj>.<attr>",  "obj,attr"),

            ("inst_method",    "Instance Method Call",    "expression",
             "Calls a method on a class instance using dot notation",
             "<mobj>.<mname>(<margs>)",  "mobj,mname,margs"),

            # ── control flow ─────────────────────────────────────────────────
            ("if_clause",      "If Clause",               "structure",
             "Conditional execution using if keyword",
             "if <cond>:\n    <ifbody>",  "cond,ifbody"),

            ("for_loop",       "For Loop",                "structure",
             "Iterates over a sequence using for keyword",
             "for <itervar> in <iterable>:\n    <loopbody>",
             "itervar,iterable,loopbody"),

            # ── built-in I/O ─────────────────────────────────────────────────
            ("print_call",     "Print Call",              "expression",
             "Outputs a message to stdout using the built-in print() function",
             "print(<pval>)",  "pval"),

            # ── argparse specifics ───────────────────────────────────────────
            ("ap_create",      "Create ArgumentParser",   "expression",
             "Instantiates argparse.ArgumentParser --- a class instance creation",
             "argparse.ArgumentParser(description=<apdesc>)",  "apdesc"),

            ("ap_add_arg",     "Add Argument",            "expression",
             "Calls add_argument method on the parser instance",
             "<apobj>.add_argument(<apname>, help=<aphelp>)",
             "apobj,apname,aphelp"),

            ("ap_parse",       "Parse Arguments",         "expression",
             "Calls parse_args method to obtain a Namespace instance",
             "<apobj2>.parse_args()",  "apobj2"),

            ("ap_access",      "Access Parsed Argument",  "expression",
             "Reads a parsed value via instance attribute access",
             "<nsobj>.<nsattr>",  "nsobj,nsattr"),
        ]
        self.conn.executemany(
            "INSERT OR IGNORE INTO concepts VALUES (?,?,?,?,?,?)", concepts
        )
        self.conn.commit()

    # ── seed: dependencies ────────────────────────────────────────────────────

    def _seed_dependencies(self):
        deps = [
            # argparse pipeline requires import first
            ("ap_create",   "import_stmt",  "requires"),
            ("ap_add_arg",  "ap_create",    "requires"),
            ("ap_parse",    "ap_add_arg",   "requires"),
            ("ap_access",   "ap_parse",     "requires"),

            # class instantiation is a kind of class usage
            ("class_inst",  "class_def",    "type_of"),
            ("inst_attr",   "class_inst",   "requires"),
            ("inst_method", "class_inst",   "requires"),

            # argparse concepts are concrete instances of class/instance patterns
            ("ap_create",   "class_inst",   "type_of"),
            ("ap_add_arg",  "inst_method",  "type_of"),
            ("ap_parse",    "inst_method",  "type_of"),
            ("ap_access",   "inst_attr",    "type_of"),

            # function def may contain various statements
            ("func_def",    "return_stmt",  "contains"),
            ("func_def",    "var_assign",   "contains"),
            ("func_def",    "func_docstring","contains"),
            ("func_def",    "func_call",    "contains"),

            # print is a function call
            ("print_call",  "func_call",    "type_of"),

            # entry point contains a function call
            ("entry_point", "func_call",    "contains"),

            # f-string is a kind of string
            ("fstring",     "string_lit",   "type_of"),
        ]
        self.conn.executemany(
            "INSERT OR IGNORE INTO dependencies VALUES (?,?,?)", deps
        )
        self.conn.commit()

    # ── seed: production rules ────────────────────────────────────────────────

    def _seed_rules(self):
        rules = [
            # R1 --- goal decomposition
            ("Decompose Hello Goal",  100,
             "Break top-level goal into sub-needs",
             "goal:program=hello",
             "need:greeting=yes;need:cli_input=yes;need:output=yes;need:entry=yes;need:docs=yes"),

            # R2 --- CLI strategy selection
            ("Select CLI Strategy",   90,
             "Choose argparse when CLI input is needed and preference is set",
             "need:cli_input=yes;config:cli_method=argparse",
             "strategy:cli=argparse;use:import_stmt=yes;use:ap_create=yes;"
             "use:ap_add_arg=yes;use:ap_parse=yes;use:ap_access=yes;"
             "use:class_inst=yes;use:inst_method=yes;use:inst_attr=yes"),

            # R3 --- greeting function requirements
            ("Plan Greeting Function", 80,
             "Determine what the greeting helper function needs",
             "need:greeting=yes",
             "use:func_def=yes;use:fstring=yes;use:return_stmt=yes;"
             "use:var_assign=yes;use:func_docstring=yes;use:string_lit=yes"),

            # R4 --- output strategy
            ("Plan Output",           70,
             "Use print to display the greeting",
             "need:output=yes;need:greeting=yes",
             "use:print_call=yes;use:func_call=yes"),

            # R5 --- entry point structure
            ("Plan Entry Point",      60,
             "Use main() function + if __name__ guard",
             "need:entry=yes",
             "use:entry_point=yes;strategy:entry=main_guard"),

            # R6 --- module docs
            ("Plan Documentation",    50,
             "Generate module-level docstring",
             "need:docs=yes",
             "use:mod_docstring=yes"),

            # R7 --- if-clause awareness (entry point is an if)
            ("Entry Is If-Clause",    40,
             "The entry-point guard is structurally an if clause",
             "use:entry_point=yes",
             "use:if_clause=yes"),

            # R8 --- main function is a function
            ("Main Is Function",      30,
             "main() itself is a function definition",
             "need:entry=yes;use:func_def=yes",
             "use:func_def=yes"),
        ]
        self.conn.executemany(
            "INSERT OR IGNORE INTO rules (name,priority,description,conditions,assertions) "
            "VALUES (?,?,?,?,?)", rules
        )
        self.conn.commit()

    # ── fact management ───────────────────────────────────────────────────────

    def assert_fact(self, ftype, key, value="yes", confidence=1.0):
        try:
            self.conn.execute(
                "INSERT INTO facts (type,key,value,confidence) VALUES (?,?,?,?)",
                (ftype, key, value, confidence))
            self.conn.commit()
            return True  # new fact
        except sqlite3.IntegrityError:
            return False  # already known

    def has_fact(self, ftype, key, value=None):
        if value is not None:
            row = self.conn.execute(
                "SELECT 1 FROM facts WHERE type=? AND key=? AND value=?",
                (ftype, key, value)).fetchone()
        else:
            row = self.conn.execute(
                "SELECT 1 FROM facts WHERE type=? AND key=?",
                (ftype, key)).fetchone()
        return row is not None

    def get_fact_value(self, ftype, key):
        row = self.conn.execute(
            "SELECT value FROM facts WHERE type=? AND key=?",
            (ftype, key)).fetchone()
        return row["value"] if row else None

    def all_facts(self):
        return self.conn.execute(
            "SELECT type,key,value,confidence FROM facts ORDER BY id"
        ).fetchall()

    # ── concept queries ───────────────────────────────────────────────────────

    def get_concept(self, cid):
        return self.conn.execute(
            "SELECT * FROM concepts WHERE id=?", (cid,)).fetchone()

    def get_dependencies(self, cid, relation=None):
        if relation:
            return self.conn.execute(
                "SELECT child_id FROM dependencies WHERE parent_id=? AND relation=?",
                (cid, relation)).fetchall()
        return self.conn.execute(
            "SELECT child_id, relation FROM dependencies WHERE parent_id=?",
            (cid,)).fetchall()

    def get_all_rules(self):
        return self.conn.execute(
            "SELECT * FROM rules ORDER BY priority DESC").fetchall()

    # ── code part storage ─────────────────────────────────────────────────────

    def add_code_part(self, section, seq, code, concept_id=None):
        self.conn.execute(
            "INSERT OR REPLACE INTO code_parts VALUES (?,?,?,?)",
            (section, seq, code, concept_id))
        self.conn.commit()

    def get_code_parts(self, section):
        return self.conn.execute(
            "SELECT code FROM code_parts WHERE section=? ORDER BY seq",
            (section,)).fetchall()

    def close(self):
        self.conn.close()


# ═══════════════════════════════════════════════════════════════════════════════
#  REASONER  --- Forward-Chaining Inference Engine
# ═══════════════════════════════════════════════════════════════════════════════

class Reasoner:
    """Implements forward-chaining inference over the rule base.
    Each rule's conditions and assertions are encoded as semicolon-separated
    patterns of the form  type:key=value."""

    def __init__(self, kb: KnowledgeBase, verbose=False):
        self.kb = kb
        self.verbose = verbose
        self.rules_fired = []

    @staticmethod
    def _parse_patterns(text):
        """Parse 'type:key=value;type:key=value;...' into a list of tuples."""
        patterns = []
        for part in text.split(";"):
            part = part.strip()
            if not part:
                continue
            tk, _, val = part.partition("=")
            ftype, _, key = tk.partition(":")
            patterns.append((ftype.strip(), key.strip(), val.strip()))
        return patterns

    def run(self):
        """Run forward chaining until no new rules fire."""
        rules = self.kb.get_all_rules()
        fired_ids = set()
        iteration = 0

        while True:
            iteration += 1
            new_fire = False
            for rule in rules:
                rid = rule["id"]
                if rid in fired_ids:
                    continue

                # check all conditions
                conditions = self._parse_patterns(rule["conditions"])
                if all(self.kb.has_fact(t, k, v) for t, k, v in conditions):
                    # fire rule
                    assertions = self._parse_patterns(rule["assertions"])
                    any_new = False
                    for t, k, v in assertions:
                        if self.kb.assert_fact(t, k, v):
                            any_new = True
                    fired_ids.add(rid)
                    self.rules_fired.append(rule["name"])
                    new_fire = True

                    if self.verbose:
                        print(f"   🔥 Rule fired: {rule['name']}")
                        if any_new:
                            for t, k, v in assertions:
                                print(f"      → assert {t}:{k}={v}")

            if not new_fire:
                break

        if self.verbose:
            print(f"   ⏹  Inference complete after {iteration} iteration(s), "
                  f"{len(self.rules_fired)} rule(s) fired.\n")

        return self.rules_fired


# ═══════════════════════════════════════════════════════════════════════════════
#  PLANNER  --- Determines generation steps in order
# ═══════════════════════════════════════════════════════════════════════════════

class Planner:
    """Builds an ordered generation plan by examining inferred facts and
    resolving concept dependencies via topological walk."""

    def __init__(self, kb: KnowledgeBase, verbose=False):
        self.kb = kb
        self.verbose = verbose

    def build_plan(self):
        """Return an ordered list of (section, action, detail) tuples."""
        plan = []

        # 1. module docstring
        if self.kb.has_fact("use", "mod_docstring"):
            plan.append(("docstring", "emit_docstring", "mod_docstring"))

        # 2. imports
        if self.kb.has_fact("use", "import_stmt"):
            plan.append(("imports", "emit_import", "import_stmt"))

        # 3. helper functions (greeting)
        if self.kb.has_fact("need", "greeting"):
            plan.append(("functions", "emit_greeting_func", "func_def"))

        # 4. main function
        if self.kb.has_fact("need", "entry"):
            plan.append(("main", "emit_main_func", "func_def"))

        # 5. entry guard
        if self.kb.has_fact("use", "entry_point"):
            plan.append(("entry", "emit_entry_guard", "entry_point"))

        if self.verbose:
            print("   📋 Plan steps:")
            for sec, act, det in plan:
                concept = self.kb.get_concept(det)
                cname = concept["name"] if concept else det
                print(f"      [{sec:>10s}]  {act:<25s}  ({cname})")
            print()

        return plan


# ═══════════════════════════════════════════════════════════════════════════════
#  RESOLVER  --- Topological dependency resolution
# ═══════════════════════════════════════════════════════════════════════════════

class Resolver:
    """Walks the dependency graph to produce a topologically sorted list of
    concepts that must be understood/applied."""

    def __init__(self, kb: KnowledgeBase, verbose=False):
        self.kb = kb
        self.verbose = verbose

    def resolve(self):
        """Return ordered concept IDs by dependency."""
        facts = self.kb.all_facts()
        seeds = [f["key"] for f in facts if f["type"] == "use"]

        visited = set()
        order = []

        def dfs(cid):
            if cid in visited:
                return
            visited.add(cid)
            deps = self.kb.get_dependencies(cid)
            for dep in deps:
                child = dep["child_id"] if "child_id" in dep.keys() else dep[0]
                if self.kb.get_concept(child):
                    dfs(child)
            order.append(cid)

        for s in seeds:
            dfs(s)

        if self.verbose:
            print("   🔗 Resolved concept order:")
            for cid in order:
                c = self.kb.get_concept(cid)
                if c:
                    print(f"      • {c['name']:<30s}  ({cid})")
            print()

        return order


# ═══════════════════════════════════════════════════════════════════════════════
#  CODE GENERATOR  --- Template-driven code emitter
# ═══════════════════════════════════════════════════════════════════════════════

class CodeGenerator:
    """Generates Python source code by consulting knowledge-base concepts and
    filling their syntax templates with concrete values."""

    def __init__(self, kb: KnowledgeBase, target_name: str, verbose=False):
        self.kb = kb
        self.target = target_name
        self.verbose = verbose
        self._seq = {}  # per-section sequence counters

    # ── helpers ───────────────────────────────────────────────────────────────

    def _next_seq(self, section):
        self._seq[section] = self._seq.get(section, 0) + 1
        return self._seq[section]

    @staticmethod
    def _indent(text, level=1):
        pad = "    " * level
        return "\n".join(
            (pad + line) if line.strip() else ""
            for line in text.split("\n")
        )

    def _fill(self, concept_id, bindings: dict):
        """Look up a concept's template and substitute <placeholder> markers."""
        concept = self.kb.get_concept(concept_id)
        if not concept or not concept["template"]:
            return None
        tpl = concept["template"]
        for key, val in bindings.items():
            tpl = tpl.replace(f"<{key}>", str(val))
        if self.verbose:
            print(f"      ✏️  Apply [{concept['name']}]")
        return tpl

    def _note(self, concept_id):
        """Log that a concept is being utilised."""
        concept = self.kb.get_concept(concept_id)
        if self.verbose and concept:
            print(f"      📝 Using concept: {concept['name']} --- {concept['description']}")

    # ── section emitters ──────────────────────────────────────────────────────

    def emit_docstring(self):
        self._note("mod_docstring")
        code = self._fill("mod_docstring", {
            "text": f"Generated Hello program --- greets the specified person.\\n"
                    f"Usage: python generated_hello.py <name>"
        })
        # make it multi-line for readability
        code = '"""\n' \
               'Generated Hello program -- greets the specified person.\n' \
               'Usage: python generated_hello.py <name>\n' \
               '"""'
        self.kb.add_code_part("docstring", self._next_seq("docstring"),
                              code, "mod_docstring")

    def emit_import(self):
        self._note("import_stmt")
        code = self._fill("import_stmt", {"module": "argparse"})
        self.kb.add_code_part("imports", self._next_seq("imports"),
                              code, "import_stmt")

    def emit_greeting_func(self):
        """Build the create_greeting(name) helper."""
        self._note("func_def")
        self._note("func_docstring")
        self._note("var_assign")
        self._note("fstring")
        self._note("return_stmt")

        # docstring
        docstring_lines = [
            '"""',
            "Create a greeting message for the given name.",
            "",
            "Args:",
            "    name: The name of the person to greet.",
            "",
            "Returns:",
            "    A greeting string.",
            '"""',
        ]
        docstring = "\n".join(docstring_lines)

        # variable assignment with f-string
        fstring_expr = self._fill("fstring", {"ftpl": "Hello, {name}!"})  # f"Hello, {name}!"
        var_line = self._fill("var_assign", {"vname": "greeting", "vval": fstring_expr})

        # return
        ret_line = self._fill("return_stmt", {"rval": "greeting"})

        # assemble body
        body = self._indent(docstring) + "\n" + \
               self._indent(var_line) + "\n" + \
               self._indent(ret_line)

        # function wrapper
        func_sig = self._fill("func_def", {
            "fname": "create_greeting",
            "fparams": "name",
            "fbody": "..."
        })
        # replace placeholder body with real body
        header = func_sig.split("\n")[0]  # def create_greeting(name):
        code = header + "\n" + body

        self.kb.add_code_part("functions", self._next_seq("functions"),
                              code, "func_def")

    def emit_main_func(self):
        """Build the main() function with argparse logic."""
        self._note("func_def")
        self._note("func_docstring")
        self._note("class_inst")
        self._note("ap_create")
        self._note("ap_add_arg")
        self._note("ap_parse")
        self._note("ap_access")
        self._note("var_assign")
        self._note("inst_method")
        self._note("inst_attr")
        self._note("func_call")
        self._note("print_call")

        lines = ["def main():", ]

        # docstring
        doc = [
            '    """',
            "    Parse command-line arguments and print a greeting.",
            '    """',
        ]
        lines.extend(doc)

        # parser = argparse.ArgumentParser(description="...")
        ap_inst = self._fill("ap_create", {"apdesc": '"A friendly greeting program"'})
        assign_parser = self._fill("var_assign", {"vname": "parser", "vval": ap_inst})
        lines.append(self._indent(assign_parser))

        # parser.add_argument("name", help="...")
        add_arg = self._fill("ap_add_arg", {
            "apobj": "parser",
            "apname": '"name"',
            "aphelp": '"Name of the person to greet"',
        })
        lines.append(self._indent(add_arg))

        # args = parser.parse_args()
        parse_expr = self._fill("ap_parse", {"apobj2": "parser"})
        assign_args = self._fill("var_assign", {"vname": "args", "vval": parse_expr})
        lines.append(self._indent(assign_args))

        # blank line for readability
        lines.append("")

        # message = create_greeting(args.name)
        attr_access = self._fill("ap_access", {"nsobj": "args", "nsattr": "name"})
        call_expr = self._fill("func_call", {"cname": "create_greeting", "cargs": attr_access})
        assign_msg = self._fill("var_assign", {"vname": "message", "vval": call_expr})
        lines.append(self._indent(assign_msg))

        # print(message)
        print_stmt = self._fill("print_call", {"pval": "message"})
        lines.append(self._indent(print_stmt))

        code = "\n".join(lines)
        self.kb.add_code_part("main", self._next_seq("main"), code, "func_def")

    def emit_entry_guard(self):
        """Build if __name__ == '__main__': main()"""
        self._note("entry_point")
        self._note("if_clause")
        self._note("func_call")

        call = self._fill("func_call", {"cname": "main", "cargs": ""})
        code = self._fill("entry_point", {"body": call})

        self.kb.add_code_part("entry", self._next_seq("entry"),
                              code, "entry_point")

    # ── orchestrate ───────────────────────────────────────────────────────────

    def generate(self, plan):
        dispatch = {
            "emit_docstring":      self.emit_docstring,
            "emit_import":         self.emit_import,
            "emit_greeting_func":  self.emit_greeting_func,
            "emit_main_func":      self.emit_main_func,
            "emit_entry_guard":    self.emit_entry_guard,
        }
        for section, action, _detail in plan:
            if self.verbose:
                print(f"   ⚙️  Generating section: {section}")
            fn = dispatch.get(action)
            if fn:
                fn()


# ═══════════════════════════════════════════════════════════════════════════════
#  AGGREGATOR  --- Assembles final source code
# ═══════════════════════════════════════════════════════════════════════════════

class Aggregator:
    """Collects all generated code parts from the KB and joins them into a
    single coherent Python source file."""

    SECTION_ORDER = ["docstring", "imports", "functions", "main", "entry"]

    def __init__(self, kb: KnowledgeBase, verbose=False):
        self.kb = kb
        self.verbose = verbose

    def assemble(self):
        sections = []
        for sec in self.SECTION_ORDER:
            parts = self.kb.get_code_parts(sec)
            if parts:
                block = "\n".join(p["code"] for p in parts)
                sections.append(block)
                if self.verbose:
                    print(f"   📦 Assembled section: {sec} "
                          f"({len(parts)} part(s), {block.count(chr(10))+1} lines)")

        final = "\n\n\n".join(sections) + "\n"

        if self.verbose:
            total_lines = final.count("\n")
            print(f"\n   ✅ Total output: {total_lines} lines\n")

        return final


# ═══════════════════════════════════════════════════════════════════════════════
#  EXPERT SYSTEM  --- Top-level controller
# ═══════════════════════════════════════════════════════════════════════════════

class ExpertSystem:
    """Orchestrates Knowledge Base → Reasoner → Planner → Resolver →
    Generator → Aggregator pipeline."""

    def __init__(self, verbose=True):
        self.verbose = verbose
        self.kb = KnowledgeBase()

    def _header(self, title):
        if self.verbose:
            print(f"\n{'─'*60}")
            print(f"  {title}")
            print(f"{'─'*60}")

    def generate(self, target_name: str) -> str:
        # ── Phase 0: Seed initial facts ──────────────────────────────────────
        self._header("Phase 0 --- Seed Initial Facts")
        self.kb.assert_fact("goal", "program", "hello")
        self.kb.assert_fact("config", "target_name", target_name)
        self.kb.assert_fact("config", "cli_method", "argparse")
        if self.verbose:
            print(f"   • goal:program = hello")
            print(f"   • config:target_name = {target_name}")
            print(f"   • config:cli_method = argparse")

        # ── Phase 1: Forward-chaining inference ──────────────────────────────
        self._header("Phase 1 --- Forward-Chaining Inference")
        reasoner = Reasoner(self.kb, self.verbose)
        fired = reasoner.run()

        # ── Phase 2: Dependency resolution ───────────────────────────────────
        self._header("Phase 2 --- Dependency Resolution")
        resolver = Resolver(self.kb, self.verbose)
        resolved = resolver.resolve()

        # ── Phase 3: Plan generation ─────────────────────────────────────────
        self._header("Phase 3 --- Plan Generation")
        planner = Planner(self.kb, self.verbose)
        plan = planner.build_plan()

        # ── Phase 4: Code generation ─────────────────────────────────────────
        self._header("Phase 4 --- Code Generation")
        generator = CodeGenerator(self.kb, target_name, self.verbose)
        generator.generate(plan)

        # ── Phase 5: Aggregation ─────────────────────────────────────────────
        self._header("Phase 5 --- Code Aggregation")
        aggregator = Aggregator(self.kb, self.verbose)
        code = aggregator.assemble()

        # ── Summary ──────────────────────────────────────────────────────────
        self._header("Summary")
        facts = self.kb.all_facts()
        if self.verbose:
            print(f"   Facts derived  : {len(facts)}")
            print(f"   Rules fired    : {len(fired)}")
            print(f"   Concepts used  : {len(resolved)}")
            print(f"   Plan steps     : {len(plan)}")
            print(f"   Output lines   : {code.count(chr(10))}")

        self.kb.close()
        return code


# ═══════════════════════════════════════════════════════════════════════════════
#  ENTRY POINT
# ═══════════════════════════════════════════════════════════════════════════════

def main():
    if len(sys.argv) < 2:
        print(f"Usage: python {sys.argv[0]} <name>")
        print(f"  Generates a Python program that prints 'Hello, <name>!'")
        sys.exit(1)

    name = sys.argv[1]
    print("=" * 60)
    print("  Expert System for Python Code Generation")
    print("=" * 60)

    es = ExpertSystem(verbose=True)
    code = es.generate(name)

    # Display generated code
    print("\n" + "=" * 60)
    print("  GENERATED CODE")
    print("=" * 60)
    print()
    print(code)

    # Write to file
    out_path = "generated_hello.py"
    with open(out_path, "w") as f:
        f.write(code)
    print(f"  ✅ Written to {out_path}")
    print(f"  ▶  Run with:  python {out_path} {name}")
    print()


if __name__ == "__main__":
    main()

今天暂时到这里了,要好好看看这个示例代码,然后进行泛化。

相关推荐
313YPHU32 小时前
【笔记】Node.js 开发 CLI 工具
笔记
boy快快长大2 小时前
云服务器部署大模型
人工智能
Swift社区2 小时前
未来游戏形态:鸿蒙 + AI + 多端协同
人工智能·游戏·harmonyos
Kapaseker2 小时前
就这 9 行 Rule 让你省 63% 的 token
人工智能
GJGCY2 小时前
企业级AI智能体平台技术评测:9款产品架构差异与生产落地能力分析
大数据·人工智能·ai·智能体
知识靠谱2 小时前
【大模型】解剖黑盒:一次对 Claude Code 的“数字考古“之旅
人工智能
airuike1232 小时前
高性能MEMS IMU:机器人自主运动的核心感知中枢
人工智能·算法·机器人
jinanwuhuaguo2 小时前
OpenClaw v2026.4.1 深度剖析报告:任务系统、协作生态与安全范式的全面跃迁
java·大数据·开发语言·人工智能·深度学习
郝学胜-神的一滴2 小时前
PyTorch张量维度操控:transpose与permute深度拆解与实战指南
人工智能·pytorch·python·深度学习·算法·机器学习