| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- """
- lambdagent Hello World
- 从最简单开始,逐步展示 11 个 Lambda 构造。
- 每一步都标注 Lambda 演算对应。
- 用法:
- export ANTHROPIC_API_KEY=sk-...
- python hello.py
- """
- import sys, os
- sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
- from lambdagent import (
- Lam, Tool, Compose, If, Loop, Pair, Fst, Snd,
- Route, Guard, Context, Dataset,
- )
- from lambdagent.extensions import Memory
- def main():
- ctx = Context()
- # ════════════════════════════════════════════
- # 1. Lam — λ 抽象
- # λx. LLM(x)
- # ════════════════════════════════════════════
- print("─── 1. Lam (λ abstraction) ───")
- hello = Lam(
- "hello",
- "You are a friendly assistant. Reply in one short sentence.",
- max_tokens=64,
- )
- print(f" λ> {hello('Hello!', ctx)}")
- print()
- # ════════════════════════════════════════════
- # 2. Tool — 原语 / Oracle
- # λx. f(x) where f is a Python function
- # ════════════════════════════════════════════
- print("─── 2. Tool (primitive) ───")
- shout = Tool("shout", lambda x: str(x).upper() + "!!!")
- print(f" λ> {shout('hello world', ctx)}")
- print()
- # ════════════════════════════════════════════
- # 3. Compose — 函数组合
- # f >> g = λx. g(f(x))
- # ════════════════════════════════════════════
- print("─── 3. Compose (f >> g) ───")
- pipeline = hello >> shout # 先让 LLM 回复,再全大写
- print(f" λ> {pipeline('Hi there', ctx)}")
- print()
- # ════════════════════════════════════════════
- # 4. Dataset → Lam — 数据集变函数
- # D.to_lam() = λx. LLM_{prompt=encode(D)}(x)
- # ════════════════════════════════════════════
- print("─── 4. Dataset → Lam ───")
- succ = Dataset(
- examples=[("0","1"), ("1","2"), ("2","3"), ("9","10")],
- description="Given n, output n+1. Output ONLY the number.",
- ).to_lam("SUCC")
- print(f" SUCC(41) = {succ('41', ctx)}")
- print(f" SUCC(99) = {succ('99', ctx)}")
- print()
- # ════════════════════════════════════════════
- # 5. Pair / Fst / Snd — Church 对
- # PAIR = λa.λb.λf. f a b
- # ════════════════════════════════════════════
- print("─── 5. Pair / Fst / Snd ───")
- both = Pair(hello, shout)
- result = both("Hey", ctx)
- print(f" Pair result: {result}")
- print(f" Fst: {Fst()('(a, b) tuple test: ' + str(result), ctx) if False else result[0]}")
- print(f" Snd: {result[1]}")
- print()
- # ════════════════════════════════════════════
- # 6. If — Church 条件
- # IF c t e = c t e
- # ════════════════════════════════════════════
- print("─── 6. If (Church boolean) ───")
- branch = If(
- cond=lambda x: int(x) > 10,
- then_=Tool("big", lambda x: f"{x} is BIG"),
- else_=Tool("small", lambda x: f"{x} is small"),
- )
- print(f" If(5 > 10): {branch('5', ctx)}")
- print(f" If(42 > 10): {branch('42', ctx)}")
- print()
- # ════════════════════════════════════════════
- # 7. Loop — Y 组合子
- # Y(λself.λx. if done then x else self(body(x)))
- # ════════════════════════════════════════════
- print("─── 7. Loop (Y combinator) ───")
- counter = Tool("inc", lambda x: str(int(x) + 1))
- loop = Loop(
- body=counter,
- condition=lambda result, step: int(result) >= 5,
- max_steps=20,
- )
- print(f" Y(inc)(0) until ≥5: {loop('0', ctx)}")
- print()
- # ════════════════════════════════════════════
- # 8. Route — 广义 Church 布尔 (CASE)
- # CASE classifier(x) [(l₁,a₁), (l₂,a₂), ...]
- # ════════════════════════════════════════════
- print("─── 8. Route (CASE) ───")
- classifier = Lam(
- "classify",
- "Classify the input as exactly one word: 'math' or 'greeting'. Output ONLY that word.",
- max_tokens=8,
- )
- router = Route(
- classifier=classifier,
- routes={
- "math": Tool("math_handler", lambda x: f"[MATH] {x}"),
- "greeting": Tool("greet_handler", lambda x: f"[GREET] Hello! {x}"),
- },
- default=Tool("default", lambda x: f"[DEFAULT] {x}"),
- )
- print(f" Route('2+2'): {router('2+2', ctx)}")
- print(f" Route('Hi!'): {router('Hi!', ctx)}")
- print()
- # ════════════════════════════════════════════
- # 9. Guard — 依赖类型 {x:T | P(x)}
- # if P(result) then result else retry
- # ════════════════════════════════════════════
- print("─── 9. Guard (dependent type) ───")
- strict_num = Guard(
- agent=succ,
- validator=lambda x: str(x).strip().isdigit(),
- retry=2,
- )
- print(f" Guard(SUCC(7)): {strict_num('7', ctx)}")
- print()
- # ════════════════════════════════════════════
- # 10. Memory — 环境扩展 Γ' = Γ ∪ store
- # ════════════════════════════════════════════
- print("─── 10. Memory (Γ extension) ───")
- greeter = Lam(
- "greeter",
- "Greet the user. If you know their name from memory, use it. One sentence.",
- max_tokens=64,
- )
- stateful = Memory(greeter, store={"user_name": "Alice", "mood": "happy"})
- print(f" Memory(greeter): {stateful('Hello!', ctx)}")
- print()
- # ════════════════════════════════════════════
- # 11. 组合: 完整 Agent pipeline
- # extract >> Pair(analyze, critique) >> synthesize >> Loop(refine)
- # ════════════════════════════════════════════
- print("─── 11. Full pipeline ───")
- extract = Lam("extract", "Extract the key claim from this text. One sentence.", max_tokens=64)
- analyze = Lam("analyze", "Is this claim true or false? One sentence.", max_tokens=64)
- combine = Tool("combine", lambda pair: f"Claim: {pair[0]}\nAnalysis: {pair[1]}")
- full = extract >> Pair(analyze, shout) >> combine
- result = full("The Earth orbits the Sun in approximately 365 days.", ctx)
- print(f" {result}")
- print()
- # ════════════════════════════════════════════
- # β-规约追踪
- # ════════════════════════════════════════════
- print("─── β-reduction trace ───")
- ctx.print_trace()
- print(f"\nTotal: {len(ctx.trace)} β-reductions")
- if __name__ == "__main__":
- main()
|