
人工智能大模型提示工程AI 应用【免费下载链接】ellA language model programming library.项目地址https://gitcode.com/gh_mirrors/ell/ell点击查看免费下载导读本指南以 ell 仓库中的响应格式研究笔记 resposne_formats.md 为骨架系统梳理大模型 API 返回的各类响应格式——Chat Completions 统一骨架、Log Probs 逐 token 概率、结构化输出、图像输入与多模态内容、以及 Groq/OpenAI 与 Ollama 两大 Function Calling 协议。读完本文你将能看懂任意一次模型调用的原始返回报文并掌握 ell 如何通过 Provider 翻译层把这些异构响应统一收敛为Message/ContentBlock对象从而在ell.simple与ell.complex中直接消费。一、起点为什么需要理解模型响应格式在 ell 中ell.simple与ell.complex装饰的函数最终都会转化为一次对语言模型的 API 调用。无论底层是 OpenAI、Groq、Ollama 还是 Anthropic模型返回的原始 JSON 报文都遵循各家的 Chat Completions 协议而 ell 的 Provider 层负责在ell 内部统一的Message消息模型与各家原始响应格式之间做双向翻译。理解响应格式就等于理解了一次调用的usagetoken 消耗与finish_reason停止原因从哪里读取流式与非流式响应的组装方式有什么差异Log Probs、结构化输出、图像、工具调用这些非纯文本能力在报文中如何编码为什么同一个get_current_weather工具在 OpenAI/Groq 与 Ollama 的响应里长得不一样。二、Chat Completions一切响应的统一骨架原笔记中仅以标题列出 Chat Completions但它实际上是所有后续响应格式的公共容器。一个典型的 Chat Completions 响应由以下顶层字段构成以文档中的gpt-4o-mini示例为参照顶层字段含义id本次补全的唯一标识如chatcmpl-123object固定为chat.completion用于区分响应类型createdUnix 时间戳如1702685778model实际服务模型名如gpt-4o-minichoices补全结果数组n参数决定条目数每条含index、message、finish_reason及可选的logprobsusage计费 token 统计prompt_tokens、completion_tokens、total_tokenssystem_fingerprint服务端配置指纹可为nullchoices内的message又包含role通常为assistant、content文本内容Function Calling 时可能为null、tool_calls工具调用时出现等字段。finish_reason常见取值包括stop自然结束、tool_calls触发工具调用等。在 ell 的 OpenAI Provider 实现 providers/openai.py 中这个骨架被明确消费usage 与顶层元数据进入 metadata非流式路径下执行chat_completion.model_dump(exclude{choices})即把choices之外的全部顶层字段id、created、model、usage等作为元数据保留供 ell Studio 与追踪系统使用见 providers/openai.py每个 choice 转成一条 Message遍历chat_completion.choices把oai_choice.message中的content、parsed、tool_calls转换为对应的ContentBlock最终生成Message(roleassistant, contentcontent_blocks)见 providers/openai.py流式响应按choices下标分组流式模式下每个 chunk 的choices通过index归并到对应的消息流中再按 index 排序拼装出完整文本见 providers/openai.py。另外值得注意的是ell 默认以流式方式调用 OpenAI 兼容接口translate_to_provider中会设置streamTrue与stream_options{include_usage: True}只有当传入tools、response_format或模型本身不支持流式时才关闭见 providers/openai.py。这意味着你看到的大多数响应结构其实是由流式 chunk 增量组装出来的。三、Log Probs逐 token 概率与候选词分布原笔记为 Log Probs 给出了一个完整的gpt-4o-mini响应示例。这是理解模型内部决策最直观的窗口每个输出 token 不仅给出它自己还给出它在模型词表顶端的几个候选及各自的对数概率。完整示例继承自原文档如下{ id: chatcmpl-123, object: chat.completion, created: 1702685778, model: gpt-4o-mini, choices: [ { index: 0, message: { role: assistant, content: Hello! How can I assist you today? }, logprobs: { content: [ { token: Hello, logprob: -0.31725305, bytes: [72, 101, 108, 108, 111], top_logprobs: [ { token: Hello, logprob: -0.31725305, bytes: [72, 101, 108, 108, 111] }, { token: Hi, logprob: -1.3190403, bytes: [72, 105] } ] }, { token: !, logprob: -0.02380986, bytes: [ 33 ], top_logprobs: [ { token: !, logprob: -0.02380986, bytes: [33] }, { token: there, logprob: -3.787621, bytes: [32, 116, 104, 101, 114, 101] } ] }, { token: How, logprob: -0.000054669687, bytes: [32, 72, 111, 119], top_logprobs: [ { token: How, logprob: -0.000054669687, bytes: [32, 72, 111, 119] }, { token: |end|, logprob: -10.953937, bytes: null } ] }, { token: can, logprob: -0.015801601, bytes: [32, 99, 97, 110], top_logprobs: [ { token: can, logprob: -0.015801601, bytes: [32, 99, 97, 110] }, { token: may, logprob: -4.161023, bytes: [32, 109, 97, 121] } ] }, { token: I, logprob: -3.7697225e-6, bytes: [ 32, 73 ], top_logprobs: [ { token: I, logprob: -3.7697225e-6, bytes: [32, 73] }, { token: assist, logprob: -13.596657, bytes: [32, 97, 115, 115, 105, 115, 116] } ] }, { token: assist, logprob: -0.04571125, bytes: [32, 97, 115, 115, 105, 115, 116], top_logprobs: [ { token: assist, logprob: -0.04571125, bytes: [32, 97, 115, 115, 105, 115, 116] }, { token: help, logprob: -3.1089056, bytes: [32, 104, 101, 108, 112] } ] }, { token: you, logprob: -5.4385737e-6, bytes: [32, 121, 111, 117], top_logprobs: [ { token: you, logprob: -5.4385737e-6, bytes: [32, 121, 111, 117] }, { token: today, logprob: -12.807695, bytes: [32, 116, 111, 100, 97, 121] } ] }, { token: today, logprob: -0.0040071653, bytes: [32, 116, 111, 100, 97, 121], top_logprobs: [ { token: today, logprob: -0.0040071653, bytes: [32, 116, 111, 100, 97, 121] }, { token: ?, logprob: -5.5247097, bytes: [63] } ] }, { token: ?, logprob: -0.0008108172, bytes: [63], top_logprobs: [ { token: ?, logprob: -0.0008108172, bytes: [63] }, { token: ?\n, logprob: -7.184561, bytes: [63, 10] } ] } ] }, finish_reason: stop } ], usage: { prompt_tokens: 9, completion_tokens: 9, total_tokens: 18 }, system_fingerprint: null }这个示例揭示了 Log Probs 报文的四个关键细节logprobs挂在choices[i]上与message平级不是消息内容的一部分logprobs.content与输出 token 一一对应数组长度等于completion_tokens示例中usage.completion_tokens 9content恰好有 9 个条目logprob是对数概率值越接近 0 代表置信度越高。示例中 How的 logprob 为-0.000054669687几乎确定而 there候选为-3.787621低概率bytes给出 token 的 UTF-8 字节序列可用于理解空格、标点如何被 tokenizer 切分top_logprobs则给出每步采样的备选 token是分析模型摇摆度、做置信度校准或安全审查的原始素材。关于 ell 中的使用方式需要说明的是从 providers/openai.py 的当前实现看ell 的 Provider 翻译层主要消费content、parsed、tool_calls与顶层usage并未专门把logprobs结构进一步映射为内部字段api_params中的logprobs相关参数会原样透传给底层客户端。可以推断Log Probs 目前更适合作为直接查看原始响应的排查手段而非 ell 追踪系统内的一等公民。四、Structured Chat Completions结构化输出如何编码原笔记以标题列出 Sturcutred Chat Completions即 Structured Chat Completions。在 ell 中结构化输出围绕response_format参数与ContentBlock(parsed...)展开两种response_format形态JSON 模式dict 形态ell.simple(..., response_format{type: json_object})或{type: json_schema, json_schema: {...}}。这类 dict 形态可配合ell.simple使用simple.py 中会断言ell.simple只接受 dict 形态的response_formatPydantic 模型形态类形态ell.complex(..., response_formatSomePydanticModel)。这是 ell 最推荐的方式底层会切换到 OpenAI 的结构化解析端点。仓库中的 json_mode.py 给出了 dict 形态的两个完整示例——json_object模式与完整的json_schema含strict: true、additionalProperties: false、递归children引用等structured.py 则演示了类形态from pydantic import BaseModel, Field class Test(BaseModel): name: str Field(descriptionThe name of the person) age: int Field(descriptionThe age of the person) height_precise: float Field(descriptionThe height of the person in meters) is_cool: bool ell.complex(modelgpt-4o-2024-08-06, response_formatTest) def create_test(text: str): You are a test model. You are given a text and you need to return a pydantic object. return do it!底层调用链在 providers/openai.py 中provider_call_function会检测response_format是否为BaseModel的子类是则选用client.beta.chat.completions.parse否则回落到普通的client.chat.completions.create。在translate_from_provider的非流式分支中若响应消息带有parsed属性则生成ContentBlock(parsedparsed)见 providers/openai.py。消费方式ell.complex返回ell.Message通过.parsed属性即可拿到已解析的 Pydantic 实例。ContentBlock的parsed字段与Message.parsed属性在 message.py 中定义序列化时parsed通过model_dump(exclude_noneTrue, exclude_unsetTrue)转成纯 JSON见 message.py。两点边界必须注意有源码与官方文档依据结构化输出的 Pydantic 原生解析在官方文档 structured_outputs.rst 中明确标注目前仅面向gpt-4o-2024-08-06一类原生支持结构化输出的模型其他模型需在 prompt 中注入MovieReview.model_json_schema()并自行model_validate_jsonGroq 明确不支持response_formatproviders/groq.py 会直接断言response_format not in params因此给 Groq 模型传结构化输出会抛错。五、Image Inputs多模态图像如何进入与返回原笔记同样以标题形式列出 Image Inputs。在 ell 中图像不是响应格式而是消息内容格式——你既可以把它作为用户输入送入模型模型也可以在具备视觉能力的响应中产出图像相关信息。ell 用ImageContent封装图像它在 message.py 中定义核心字段为字段说明imagePIL.Image.Image像素数据三选一url远程图片 URL三选一detailOpenAIimage_url的detail参数如low/high三个字段只能存在一个model_validator会校验ImageContent.coerce接受strhttp(s) URL 或 base64 字符串、np.ndarray(H, W, 3)或(H, W, 4)、PIL.Image.Image并统一转为RGB/RGBA。两种 Provider 的图像编码差异OpenAIproviders/openai.py_content_block_to_openai_format将图像序列化为{type: image_url, image_url: {url: base64 data URL, detail: ...}}Anthropicproviders/anthropic.pyserialize_image_for_anthropic会将url下载requests.get或直接使用image像素编码为 PNG 后转 base64产出{type: image, source: {type: base64, media_type: image/png, data: ...}}。在消息侧Message.images属性可以取出所有ImageContent见 message.py。由于ell.simple会把任意多模态响应压成纯文本convert_multimodal_response_to_lstr见 simple.py要保留图像的完整结构应使用ell.complex。六、Function Calling两大协议响应形态对比这是原笔记着墨最重的部分——它完整给出了 Function Calling 在Groq/OpenAI 系与Ollama 原生两种协议下的响应报文。两者在模型决定调用工具时语义相同但编码差异明显。6.1 Groq / OpenAI 协议tool_calls JSON 字符串参数{ id: chatcmpl-abc123, object: chat.completion, created: 1699896916, model: gpt-4o-mini, choices: [ { index: 0, message: { role: assistant, content: null, tool_calls: [ { id: call_abc123, type: function, function: { name: get_current_weather, arguments: {\n\location\: \Boston, MA\\n} } } ] }, logprobs: null, finish_reason: tool_calls } ], usage: { prompt_tokens: 82, completion_tokens: 17, total_tokens: 99 } }要点调用工具时message.content为nullmessage.tool_calls是数组支持一次多工具并行调用每个tool_calls[i]含独立的id、type: function与function对象function.arguments是 JSON 字符串需要二次json.loads才能得到{location: Boston, MA}这样的对象finish_reason变为tool_calls用于快速判断这轮是否要求调工具。6.2 Ollama 原生协议内嵌对象参数{ model: llama3.1, created_at: 2024-07-22T20:33:28.123648Z, message: { role: assistant, content: , tool_calls: [ { function: { name: get_current_weather, arguments: { format: celsius, location: Paris, FR } } } ] }, done_reason: stop, done: true, total_duration: 885095291, load_duration: 3753500, prompt_eval_count: 122, prompt_eval_duration: 328493000, eval_count: 33, eval_duration: 552222000 }Ollama 系的关键差异顶层没有choices数组直接是message对象tool_calls元素不含id与typefunction直接内嵌arguments是真正的 JSON 对象而非字符串结束原因字段名也不同Ollama 用done_reason示例为stop并附带total_duration、load_duration、prompt_eval_count、eval_duration等本地推理耗时数据。6.3 ell 如何消费这两种协议在 ell 中工具调用被建模为ContentBlock(tool_callToolCall(...))其核心类型定义于 message.pyToolCall持有tool装饰后的可调用对象、tool_call_id与paramsPydantic 模型。转换链路如下发出工具声明ell.complex(..., tools[...])传入的工具在 OpenAI/Groq 侧被转换为{type: function, function: {name, description, parameters: tool.__ell_params_model__.model_json_schema()}}见 providers/openai.py在 Anthropic 侧转换为{name, description, input_schema: ...}见 providers/anthropic.py解析响应OpenAI/Groq 侧把tool_calls[i]中的name通过ell_call.get_tool_by_name匹配到真实工具arguments经json.loads后构造ToolCall见 providers/openai.pyAnthropic 侧则在流式事件中累积input_json_delta的 partial JSON 后同样json.loads还原见 providers/anthropic.py执行工具并回传response.call_tools_and_collect_as_message()会真正执行工具调用结果打包为ContentBlock(tool_resultToolResult(...))再传给模型时OpenAI 系翻译为{role: tool, tool_call_id: ..., content: ...}见 providers/openai.pyAnthropic 系翻译为{type: tool_result, tool_use_id: ...}见 providers/anthropic.py。工具参数的 JSON 序列化行为有测试锁定tests/test_tools.py验证了ell.tool()返回的任意结果会被json.dumps成文本ContentBlock除非本来就是ContentBlock列表并断言ToolResult.tool_call_id与内容正确回填。七、ell 的统一响应模型Message 与 ContentBlock尽管各家响应报文形态各异ell 用一套统一的内部模型收敛它们定义于 message.pyMessage(role..., content[ContentBlock, ...])ContentBlock是六选一的判别联合同一时刻只能有一个字段非空由model_validator保证见 message.pyContentBlock字段对应响应能力便捷属性text纯文本内容Message.text/text_onlyimage图像输入/输出Message.imagesaudio音频内容np.ndarray或样本列表Message.audiostool_call模型请求调用工具Message.tool_callsparsed结构化输出Pydantic 实例Message.parsedtool_result工具执行结果Message.tool_results配合ell.system(...)、ell.user(...)、ell.assistant(...)三个便捷构造函数见 message.pyell.complex返回的Message可以通过.text、.parsed、.tool_calls、.call_tools_and_collect_as_message()等接口直接编程消费属性定义见 message.py。Groq 的一个特殊约束由于 Groq API 要求 assistant 消息的content必须是字符串providers/groq.py 的messages_to_groq_message_format会把单元素文本列表压成字符串否则抛ValueError同时 Groq 不返回usage时会从x_groq.usage兜底填充见 providers/groq.py。八、在 ell 中消费各类响应simplevscomplex选择哪个装饰器直接决定你拿到的是哪种响应视图ell.simple文本视图。内部以post_callback把任何响应压成字符串——response.content[0].text见 simple.py。适合不需要结构化细节的生成任务此时response_format仅允许 dict 形态simple.py。ell.complex完整结构视图。返回Message保留parsed、tool_calls、tool_results、图像等全部信息并支持tools[...]参数。仓库 complex.py 的 docstring 中给出了结构化输出、多模态输入、并行工具执行的完整示例response_format还会被记录为_track的强制依赖见 complex.py用于版本追踪。端到端示例源自 tool_using_chatbot.py 的保险理赔机器人ell.complex(modelclaude-3-5-sonnet-20241022, tools[create_claim_draft, approve_claim], temperature0.1, max_tokens400) def insurance_claim_chatbot(message_history: List[Message]) - List[Message]: return [ell.system(You are an insurance adjuster AI. ...)] message_history response_message insurance_claim_chatbot(message_history) if response_message.tool_calls: # 响应包含工具调用 next_message response_message.call_tools_and_collect_as_message() message_history.append(next_message) # 把工具结果作为 user 消息回传 insurance_claim_chatbot(message_history)Ollama 接入通过 ollama_ex.py 中的ell.models.ollama.register(base_urlhttp://localhost:11434/v1)注册本地模型——该注册函数会用openai.Client(base_url..., api_keyollama)拉取/api/tags中的模型清单并逐个注册见 models/ollama.py。注意Ollama 原生 JSON 报文如文档中tool_calls.function.arguments为对象只在直接请求 Ollama 原生端点时出现ell 走的是 OpenAI 兼容端点/v1因此报文形态遵循第六节中的 OpenAI 协议。Groq 的接入方式见 groq_ex.pyell.models.groq.register()读取GROQ_API_KEY环境变量批量注册模型。九、能力对照与排查建议响应能力OpenAIGroqOllama经/v1AnthropicChat Completions 骨架支持继承 OpenAIOpenAI 兼容端点messages.createLog Probs底层 API 支持ell 当前未专门映射未专门处理视兼容端点无Anthropic 不提供结构化输出response_format支持Pydantic 类→parse明确断言不支持视兼容端点未单独处理图像输入base64 data URLimage_url继承 OpenAI 格式视兼容端点PNG base64imagesourceFunction Callingtool_calls JSON 字符串参数继承 OpenAI 格式OpenAI 兼容格式tool_use/tool_result排查响应问题时可以从三个层面入手原始报文打开 Provider 的translate_from_provider观察流式 chunk 组装与非流式分支的实际字段消费逻辑内部模型确认Message.text含非文本 repr、Message.parsed、Message.tool_calls、Message.images各自返回是否符合预期Provider 差异重点核对 Groq 的 assistant 字符串约束与response_format断言、Anthropic 对max_tokens的强校验缺省会直接报错见 providers/anthropic.py。综上从 Chat Completions 的统一骨架到 Log Probs 的逐 token 分布再到结构化输出、图像与双协议 Function Calling——理解这些响应格式是阅读 ell 源码、调试多 Provider 应用、以及扩展自有 Provider 的必经之路。建议结合本文给出的源码路径边对照边验证即可在几分钟内建立完整的响应格式→ell 内部模型心智地图。赞分享人工智能大模型提示工程AI 应用【免费下载链接】ellA language model programming library.项目地址https://gitcode.com/gh_mirrors/ell/ell点击查看免费下载相关推荐ell 中 Chat 与消息历史的设计演进从反模式到 ell.function、ell.chat 与解析式 LMPell 中 Chat 与消息历史的设计演进从反模式到 ell.function 、 ell.chat 与解析式 LMP 本文以 ell 项目 0.1.0 设人工智能大模型提示工程AI 应用从 Function Calling 到 MCPLLM Zoomcamp 2025 Agents 模块作业实战详解从 Function Calling 到 MCPLLM Zoomcamp 2025 Agents 模块作业实战详解 本篇技术指南基于 LLM Zoomcamp示例工程教程人工智能大模型3 步上手 Whisper 说话人分离完整指南3 步上手 Whisper 说话人分离完整指南 Whisper Diarization 是一个基于 OpenAI Whisper 的开源工具专门做多说话人语音语音人工智能音频处理上一篇BingGPT用户界面原型设计理念和迭代过程下一篇Protege Desktop常见问题解决新手必知的15个本体编辑技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考