tpf LLM 库总览
tpf 是自研工具库,LLM 部分分两层: ```text tpf/ ├── llm/ # 底层 LLM 网关 │ ├── openai.py # chat() 函数 + MyChat 类(多厂商门面)+ 文生图 │ ├── ollama.py # client_ollama / chat_ollama / chat(本地模型) │ ├── funcall.py # FuncCall 类(函数调用双引擎) │ ├── tools.py # Tools 类(JSON 解析 + 工具定义) │ ├── prompt.py # return_json1 输出契约 + SqlJiaoYi nl2sql 提示工厂 │ └── agent.py # Agent 类(Agently 框架封装) ├── cn/ # 高层"超级大脑" │ ├── link.py # Think 类(对话 + 函数自动生成) │ ├── prompt.py # Prompt 类(需求分析/代码生成提示模板) │ ├── funcs.py # 函数工具库 + _register_function 自动注册 │ └── tools/windows.py # BatchGenerator(cmd转bat,单例) └── funcs/base.py # append_code_to_file_safely 等通用函数 ``` 公开入口:`from tpf.llm import MyChat, chat, FuncCall, Tools`;`from tpf.cn import Think, BatchGenerator`。
**全库统一 JSON 返回契约**(`return_json1()`,所有 `return_json=True` 的调用都注入该约束): ```json { "query": "用户问题", "result": "最终回复(代码生成场景为纯 Python 代码)", "thinking": ["思考步骤1", "思考步骤2"] } ``` 解析链:模型输出含 ```` ```json ... ``` ```` 围栏 → `Tools.get_json_str()` 用正则 ```` ```json([\s\S]*?)``` ```` 剥离 → `json.loads`;**解析失败优雅降级返回原文**,不抛异常。
env 文件(默认 `.env`,回退 `env.txt` → `/wks/app/conf/env.txt`): ```text deepseek_api_key=sk-xxx deepseek_base_url=https://api.deepseek.com/v1 OPENAI_API_KEY=sk-xxx OPENAI_BASE_URL=https://.../v1 DASHSCOPE_API_KEY=sk-xxx # 通义 qianfan_ak=xxx / qianfan_sk=xxx # 千帆 ARK_API_KEY / ARK_BASE_URL # 火山方舟(豆包) glm_api_key / glm_base_url # 智谱 API_KEY / BASE_URL # 通用 request 裸调用 ``` 命名规范:`{厂商}_api_key` 与 `{厂商}_base_url`。
MyChat:多厂商统一门面
最底层 OpenAI 兼容对话函数(MyChat 各方法都经它转发): ```python from tpf.llm import chat content = chat( prompt_user="你好", prompt_system=None, response_format="text", # 传给 API 的 {"type": ...} model='deepseek-r1:1.5b', temperature=1, base_url='http://localhost:11434/v1/', # 默认走本地 ollama api_key='key', return_json=False # True 时注入 JSON 契约并解析 ) ``` 本地 ollama 也有专用封装: ```python from tpf.llm.ollama import chat_ollama res = chat_ollama("你好", model='deepseek-r1:1.5b', temperature=0) ```
MyChat 统一入口,一族方法打天下: ```python from tpf.llm import MyChat chat = MyChat(env_file="env.txt") # 对话类:deepseek / openai / tongyi / qianfan / ollama res = chat.deepseek(prompt_user="你好", models=['deepseek-chat','deepseek-reasoner'], temperature=0, return_json=True) print(res['result'], res['thinking']) res = chat.ollama(prompt_user="你好", model=["DeepSeek-R1-32B-Q8:latest"], # 列表=多备选 temperature=1) # 用 openai 方法走任意 OpenAI 兼容端点(例:deepseek) res = chat.openai(prompt_user="你好", models='deepseek-chat', temperature=0, base_url="https://api.deepseek.com/v1", api_key="...", return_json=True) # 函数调用类:*_func_call(见 FuncCall 页) res = chat.deepseek_func_call(query="请启动dcn服务", model_list=[...], func_index=0) # 本地模型注册(func_call 路由用) chat.set_local_model("DeepSeek-R1-14B-Q8:latest") ``` `set_local_model/get_local_model` 维护本地 ollama 名单——决定 func_call 走"本地自定义流程"还是"在线 tools 流程"。
三家文生图统一返回 `(url, img_save_path)`,自动下载落盘: ```python # 智谱 url, path = chat.glm_image("一张雪山的海报", outdir="", models=["glm-image","cogview-3"], size="1024x1024") # 通义(支持 negative_prompt / prompt_extend / watermark) url, path = chat.tongyi_image("一只柴犬", models=["wan2.6-t2i","qwen-image-max"], size="1024*1024", watermark=False) # 豆包(ARK,OpenAI SDK images.generate) url, path = chat.doubao_image("赛博朋克城市夜景", size="2K") ``` 实现要点:重试递增等待(max_retries=3)、120s 超时、文件名 `glm_时间戳.png`。
`request()` 方法做裸 HTTP 调用(URL 自动补 `/v1/chat/completions`,`**params` 直接并入请求体,支持 n/stream/presence_penalty/frequency_penalty/max_tokens/top_p): ```python content = chat.request( prompt_user="你好", models=["deepseek-chat"], temperature=0.1, base_url=None, api_key=None, top_p=0.9, max_tokens=1024 ) ``` 返回 `choices[0].message.content`,120 秒超时——适合调那些"OpenAI 兼容但 SDK 不认"的端点。
超脑·Think(tpf.cn)
`tpf.cn.link.Think` 是高层统一对话入口: ```python from tpf.cn import Think thk = Think() # 默认读 .env,回退 env.txt res = thk.thinking( prompt_user="帮我分析这段需求的实现思路:...", prompt_system=None, response_format="text", # "json_object" 时配合 return_json models=['deepseek-v4-flash','deepseek-reasoner','deepseek-chat'], # 只取第1个,列表便于换序 temperature=0.1, base_url=None, api_key=None, # None 则用 env 里的 deepseek 配置 return_json=False, # True 时经 ```json``` 围栏解析为 dict file=None # 指定则把结果写盘(json 用 ensure_ascii=False) ) ``` 内部流程:默认参数补全 → OpenAI 客户端 → [system]+[user] 消息 → chat.completions → content → (可选)JSON 解析/写盘 → 返回。 通义封装:`thk.tongyi(prompt_user, models=['qwen3-coder-plus'], temperature=0, return_json=True)` 内部转调 thinking 换 DashScope 端点。
Think 的特色:**"分析→生成→注册→调用"函数自动生成链**: ```python # 1. 需求分析:是否需要函数?要几个? ana = thk.deepseek_func_needing(query) # 返回 {"query","result":bool,"thinking":[(内容,是否需函数0/1,函数信息)],"tools_num":n} # 2. 代码生成:按分析结果生成函数代码(纯代码、语法自检、尾部自动加注册行) res = thk.deepseek_func_gen(query, func_path="/tmp/funcs.py") # 内部: Prompt.gen_fun -> thinking(return_json=True) -> append_code_to_file_safely 落盘 print(res['result']) # 函数代码文本 ``` 生成的函数尾部带 `_register_function(函数名)`,写入 `cn/funcs.py` 即自动注册进工具库(装饰器从 docstring 首行取描述、从签名取参数生成 schema)。 再经 `MyChat.add_funcs(tools_info, tools_mapping)` 注册给 FuncCall,随后 `chat.deepseek_func_call(query)` 即可调度——端到端把"一句话需求"变成"可调用工具"。 注意:`Think.func_from_file_call` 引用的 `func_call_add_head` 在当前 funcs.py 中不存在(历史遗留),此路径会 ImportError,待修复。
BatchGenerator(单例):把在 cmd/PowerShell 敲过的命令序列转成 .bat 脚本: ```python from tpf.cn import BatchGenerator bat = BatchGenerator().bat_gen( "pip install pandas\ndel /f temp.log" ) print(bat) # 生成完整 bat 脚本文本 ``` 实现要点:`__new__` 单例共享一个 Think;few-shot 用一对 ask/answer 示例教格式;输入经 `repr()` 转原始字符串避免反斜杠转义问题。
参考
     tpf 源码(aitpf 工程内)